Donatien Garnier / NetServicesLPC1768

Dependents:   SimpleLCDClock readCard2Twitter_http AnalogClock_StepperMotor_NTP ServoCamV1

services/http/client/HttpClient.h

Committer:
donatien
Date:
2010-05-24
Revision:
0:a2dd0ba6cd2d
Child:
1:7043cc0db03c

File content as of revision 0:a2dd0ba6cd2d:

#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H

class HttpData;

#include "if/net/net.h"
#include "api/TcpSocket.h"
#include "api/DnsRequest.h"
#include "HttpData.h"
#include "mbed.h"

#include <string>
using std::string;

#include <map>
using std::map;

#define HTTP_REQUEST_TIMEOUT 30000//15000
#define HTTP_PORT 80

enum HttpResult
{
  HTTP_OK,
  HTTP_PROCESSING,
  HTTP_PARSE, //URI Parse error
  HTTP_DNS, //Could not resolve name
  HTTP_PRTCL, //Protocol error
  HTTP_NOTFOUND, //404 Error
  HTTP_REFUSED, //403 Error
  HTTP_ERROR, //xxx error
  HTTP_TIMEOUT, //Connection timeout
  HTTP_CONN //Connection error
};



class HttpClient : protected NetService
{
public:
  HttpClient();
  virtual ~HttpClient();
  
  void basicAuth(const char* user, const char* password); //Basic Authentification
  
  //High Level setup functions
  HttpResult get(const char* uri, HttpData* pDataIn); //Blocking
  HttpResult get(const char* uri, HttpData* pDataIn, void (*pMethod)(HttpResult)); //Non blocking
  template<class T> 
  //Linker bug : Must be defined here :(
  HttpResult get(const char* uri, HttpData* pDataIn, T* pItem, void (T::*pMethod)(HttpResult)) //Non blocking
  {
    setOnResult(pItem, pMethod);
    doGet(uri, pDataIn);
    return HTTP_PROCESSING;
  }
  
  HttpResult post(const char* uri, const HttpData& dataOut, HttpData* pDataIn); //Blocking
  HttpResult post(const char* uri, const HttpData& dataOut, HttpData* pDataIn, void (*pMethod)(HttpResult)); //Non blocking
  template<class T> 
  //Linker bug : Must be defined here :(
  HttpResult post(const char* uri, const HttpData& dataOut, HttpData* pDataIn, T* pItem, void (T::*pMethod)(HttpResult)) //Non blocking  
  {
    setOnResult(pItem, pMethod);
    doPost(uri, dataOut, pDataIn);
    return HTTP_PROCESSING;
  }
  
  void doGet(const char* uri, HttpData* pDataIn);  
  void doPost(const char* uri, const HttpData& dataOut, HttpData* pDataIn); 
  
  void setOnResult( void (*pMethod)(HttpResult) );
  class CDummy;
  template<class T> 
  //Linker bug : Must be defined here :(
  void setOnResult( T* pItem, void (T::*pMethod)(HttpResult) )
  {
    m_pCb = NULL;
    m_pCbItem = (CDummy*) pItem;
    m_pCbMeth = (void (CDummy::*)(HttpResult)) pMethod;
  }
  
  void setTimeout(int ms);
  
  virtual void poll(); //Called by NetServices
  
  int getHttpResponseCode();
  void setRequestHeader(const string& header, const string& value);
  string& getResponseHeader(const string& header);
  void resetRequestHeaders();
  
protected:
  void resetTimeout();
  
  void init();
  void close();
  
  void setup(const char* uri, HttpData* pDataOut, HttpData* pDataIn); //Setup request, make DNS Req if necessary
  void connect(); //Start Connection
  
  int  tryRead(); //Read data and try to feed output
  void readData(); //Data has been read
  void writeData(); //Data has been written & buf is free
  
  void onTcpSocketEvent(TcpSocketEvent e);
  void onDnsReply(DnsReply r);
  void onResult(HttpResult r); //Called when exchange completed or on failure
  void onTimeout(); //Connection has timed out
  
private:
  HttpResult blockingProcess(); //Called in blocking mode, calls Net::poll() until return code is available

  bool readHeaders(); //Called first when receiving data
  bool writeHeaders(); //Called to create req
  int readLine(char* str, int maxLen);
  
  enum HTTP_METH
  {
    HTTP_GET,
    HTTP_POST,
    HTTP_HEAD
  };
  
  HTTP_METH m_meth;
  
  CDummy* m_pCbItem;
  void (CDummy::*m_pCbMeth)(HttpResult);
  
  void (*m_pCb)(HttpResult);
  
  TcpSocket* m_pTcpSocket;
  map<string, string> m_reqHeaders;
  map<string, string> m_respHeaders;
  
  Timer m_watchdog;
  int m_timeout;
  
  DnsRequest* m_pDnsReq;
  
  Host m_server;
  string m_path;
  
  bool m_closed;
  
  enum HttpStep
  {
   // HTTP_INIT,
    HTTP_WRITE_HEADERS,
    HTTP_WRITE_DATA,
    HTTP_READ_HEADERS,
    HTTP_READ_DATA,
    HTTP_READ_DATA_INCOMPLETE,
    HTTP_DONE,
    HTTP_CLOSED
  };
  
  HttpStep m_state;
  
  HttpData* m_pDataOut;
  HttpData* m_pDataIn;
  
  bool m_dataChunked; //Data is encoded as chunks
  int m_dataPos; //Position in data
  int m_dataLen; //Data length
  char* m_buf;
  char* m_pBufRemaining; //Remaining
  int m_bufRemainingLen; //Data length in m_pBufRemaining
  
  int m_httpResponseCode;
  
  HttpResult m_blockingResult; //Result if blocking mode
  
};

//Including data containers here for more convenience
#include "data/HttpFile.h"
#include "data/HttpStream.h"
#include "data/HttpText.h"
#include "data/HttpMap.h"

#endif