00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00026 #ifndef OW32_http_h
00027 #define OW32_http_h
00028
00029 #include <OW32/OW32Libs.h>
00030 #include <OW32/AsyncSecureSocketClient.h>
00031 #include <OW32/auto_buf.h>
00032 #include <OW32/RefCounted.h>
00033 #include <OW32/URIComponents.h>
00034 #include <OW32/SyncObjects.h>
00035
00036 #include <memory>
00037
00038 namespace OW32
00039 {
00040
00042 enum HTTP_ERRORS
00043 {
00045 HTTP_NO_ERROR = 0,
00046
00048 HTTP_NO_HTTP_PREFIX,
00050 HTTP_INVALID_VERSION,
00052 HTTP_INVALID_SERVER_RESPONSE,
00054 HTTP_INVALID_STATUS_CODE,
00056 HTTP_INVALID_CONTENT_LENGTH,
00058 HTTP_INVALID_TRANSFER_ENCODING,
00060 HTTP_SERVER_CLOSED_CONNECTION,
00062 HTTP_INVALID_CHUNK_HEADER,
00064 HTTP_REDIRECT_WITHOUT_LOCATION,
00065
00067 HTTP_MAXIMUM_REDIRECTS_EXCEEDED,
00069 HTTP_MAXIMUM_SIZE_EXCEEDED,
00070
00072 HTTP_READ_TIMEOUT,
00074 HTTP_SEND_TIMEOUT,
00076 HTTP_CONNECT_TIMEOUT,
00078 HTTP_SOCKET_FAILED,
00080 HTTP_IOCP_FAILED,
00082 HTTP_BIND_FAILED,
00084 HTTP_CONNECT_FAILED,
00086 HTTP_SHUTDOWN_FAILED,
00088 HTTP_READ_FAILED,
00090 HTTP_SEND_FAILED,
00092 HTTP_IO_PENDING,
00094 HTTP_NAME_RESOLUTION_FAILED
00095 };
00096
00097 class OW32_LIB_EXPORT CHTTP;
00098
00100 class OW32_LIB_EXPORT CHTTPListener
00101 {
00102 public:
00106 virtual void OnConnection(CHTTP* ) {}
00107
00111 virtual void OnConnectionClosed(CHTTP* ) {}
00112
00116 virtual void OnError(CHTTP* ) {}
00117
00121 virtual void OnPageReceived(CHTTP* ) {}
00122
00127 virtual void OnChunkReceived(CHTTP* , int ) {}
00128
00138 virtual bool OnRedirect(CHTTP* ) { return false; }
00139
00144 virtual void OnRequestCompleted(CHTTP* ) {}
00145 };
00146
00147 #ifdef _MSC_VER
00148 #pragma warning(disable: 4251)
00149 #endif
00150
00153 class OW32_LIB_EXPORT CConnectionThread;
00154
00156 class OW32_LIB_EXPORT CHTTP :
00157 public CAsyncSocketCallback,
00158 public CRefCounted
00159 {
00160 public:
00161
00165 static int initialise();
00166
00168 static void terminate();
00169
00173 static CHTTP* createObject() { return new CHTTP; }
00174
00178 void Reset();
00179
00189 void setListener(CHTTPListener* listener) {
00190 m_pListener = listener;
00191 }
00192
00198 CHTTPListener* getListener() { return m_pListener; }
00199
00202 void close() {
00203 if (m_pSocket.get()) m_pSocket->shutdown(SD_SEND);
00204 }
00205
00208 void abort() {
00209 if (m_pSocket.get()) m_pSocket->close();
00210 }
00211
00215 std::string lastErrorMessage();
00216
00219 int lastError() const { return m_lastError; }
00220
00223 DWORD lastAPIError() const { return m_lastAPIError; }
00224
00225
00226
00228 enum HTTP_OPTIONS {
00230 OPT_FOLLOW_REDIRECT=1,
00232 OPT_KEEP_ALIVE=2,
00233 };
00234
00239 bool isOptionSet(int opt) const { return !!(m_options & opt); }
00240
00244 bool getOption(int opt) const { return (m_options & opt) != 0; }
00245
00250 int setOption(int opt) { int old=m_options; m_options |= opt; return old & opt; }
00251
00255 void clearOption(int opt) { m_options &= ~opt; }
00256
00261 int setOptions(int opt) { int old=m_options; m_options=opt; return old; }
00262
00266 int getOptions() const { return m_options; }
00267
00282 int setMaximumResponseSize(int maxResponseSize) {
00283 int oldMaxResponseSize = m_maxResponseSize;
00284 m_maxResponseSize = maxResponseSize;
00285 return oldMaxResponseSize;
00286 }
00287
00294 int getMaximumResponseSize() const {
00295 return m_maxResponseSize;
00296 }
00297
00304 int setTimeout(int timeout) {
00305 int oldTimeout = m_timeout;
00306 m_timeout = timeout;
00307 return oldTimeout;
00308 }
00309
00313 int getTimeout() const {
00314 return m_timeout;
00315 }
00316
00323 int setMaximumRedirects(int maxRedirects) {
00324 int oldRedirects = m_maxRedirects;
00325 m_maxRedirects = maxRedirects;
00326 return oldRedirects;
00327 }
00328
00334 int getMaximumRedirects() const {
00335 return m_maxRedirects;
00336 }
00337
00339 CURIComponents &getURI() { return m_URI; }
00340
00342 void setURI(const CURIComponents &URI) {
00343 m_URI = URI;
00344 }
00345
00349 void setProxyServer(const char* proxyServer) { m_proxyServer = proxyServer; }
00350
00354 const std::string& getProxyServer() const { return m_proxyServer; }
00355
00359 void setProxyPort(int proxyPort) { m_proxyPort = proxyPort; }
00360
00364 int getProxyPort() const { return m_proxyPort; }
00365
00370 void parseURI(const char *URIString, std::string::size_type URILength)
00371 {
00372 m_URI.parse(URIString, URILength);
00373 }
00374
00378 void parseURI(const std::string &URIString)
00379 {
00380 m_URI.parse(URIString);
00381 }
00382
00386 std::string getCanonicalURI() const
00387 {
00388 return m_URI.make();
00389 }
00390
00394 auto_byte_buf& getRequest() { return m_request; }
00395
00399 int getStatusCode() const { return m_statusCode; }
00400
00409 bool isResponseValid() const { return m_lastError == HTTP_NO_ERROR && m_statusCode != -1; }
00410
00414 const unsigned char *getResponse() const { return m_response.str(); }
00415
00419 unsigned char *detachResponse() { return m_response.detach(); }
00420
00422 size_t getResponseLength() const { return m_response.length(); }
00423
00425 size_t getHeaderLength() const { return m_bodyOffset; }
00426
00428 const unsigned char *getBody() const { return m_bodyOffset ? m_response.str() + m_bodyOffset : NULL; }
00429
00432 size_t getBodyOffset() const { return m_bodyOffset; }
00433
00435 size_t getBodyLength() const {
00436 return m_trailerOffset ? m_trailerOffset - m_bodyOffset : m_response.length() ? m_response.length() - m_bodyOffset : 0;
00437 }
00438
00440 size_t getTrailerOffset() const { return m_trailerOffset; }
00441
00443 size_t getTrailerLength() const { return m_response.length() ? m_response.length() - m_trailerOffset : 0; }
00444
00448 int connect(AsyncIoType tAsyncIo, HANDLE hCompletionPort = NULL);
00449
00459 int makeRequest(bool fInitial = true);
00460
00464 void addHeader(const char *header);
00465
00473 int formatGETRequest();
00474
00478 bool isConnected() const { return m_connected; }
00479
00485 static void urlEncode(auto_byte_buf& out, const unsigned char* data, int len);
00486
00495 static unsigned char *findLineEnd(const unsigned char *start, const unsigned char *end);
00496
00504 unsigned char *getHeader(const char *header);
00505
00513 std::string getHeaderValue(const char *header);
00514
00515 private:
00517 CHTTP();
00518
00522 ~CHTTP();
00523
00525 virtual void onConnectCompletion(BOOL bRet);
00527 virtual void onReadCompletion(BOOL bRet, DWORD cbReceived);
00529 virtual void onSendCompletion(BOOL bRet, DWORD cbSent);
00531 virtual void onCloseCompletion(BOOL bRet);
00533 virtual void onTimeout();
00535 virtual void onAllNotificationsProcessed();
00536
00538 typedef void (CHTTP::*HTTPIoCompletionFn)(BOOL bRet, DWORD BytesReceived, BOOL bChain);
00539
00541 void OnRecvHeaders(BOOL bRet, DWORD BytesReceived, BOOL bChain);
00543 void OnRecvContentLength(BOOL bRet, DWORD BytesReceived, BOOL bChain);
00545 void OnRecvCompleteStream(BOOL bRet, DWORD BytesReceived, BOOL bChain);
00547 void OnRecvChunked(BOOL bRet, DWORD BytesReceived, BOOL bChain);
00549 void OnRecvFooter(BOOL bRet, DWORD BytesReceived, BOOL bChain);
00551 void OnSend(BOOL bRet, DWORD BytesSent, BOOL bChain);
00552
00554 void OnConnect(int ErrorCode);
00555
00557 friend class CConnectionThread;
00558
00559
00560
00566 BOOL BeginRead(HTTPIoCompletionFn CompletionFn, DWORD dwLength);
00567
00573 BOOL BeginSend(HTTPIoCompletionFn CompletionFn, DWORD dwLength);
00574
00578 BOOL ReadLine(HTTPIoCompletionFn CompletionFn);
00579
00582 BOOL ReadLineChunked();
00583
00587 void PageReceived();
00588
00590 void ChunkReceived();
00591
00598 int error(bool fNotifyListnener, int errnum, DWORD lastAPIError = ERROR_SUCCESS);
00599
00604 void clearError();
00605
00607 CHTTPListener* m_pListener;
00608
00610 CHTTP* m_nextFree;
00611
00613 std::auto_ptr<CAsyncSocketBase> m_pSocket;
00614
00616 int m_statusCode;
00617
00619 int m_bodyOffset;
00620
00622 int m_trailerOffset;
00623
00625 CURIComponents m_URI;
00626
00628 std::string m_proxyServer;
00630 int m_proxyPort;
00631
00633 int m_options;
00634
00635
00643 CCriticalSection m_errorLock;
00644
00646 int m_lastError;
00647
00649 DWORD m_lastAPIError;
00650
00652 OW32::auto_byte_buf m_request;
00653
00655 OW32::auto_byte_buf m_headers;
00656
00658 OW32::auto_byte_buf m_response;
00659
00661 enum HTTP_State
00662 {
00664 Initial,
00666 Header,
00668 Content,
00670 Chunks,
00672 Entity_Header,
00674 CompleteStream,
00676 Complete
00677 };
00678
00680 HTTP_State m_RecvState;
00681
00683 HTTPIoCompletionFn m_SendCompletionFn;
00684
00686 HTTPIoCompletionFn m_ReadCompletionFn;
00687
00690 int m_ContentLength;
00691
00693 bool m_bChunked;
00694
00696 int m_maxResponseSize;
00697
00699 int m_maxRedirects;
00700
00702 int m_timeout;
00703
00705 int m_redirects;
00706
00708 int m_totalData;
00709
00711 int m_pos;
00712
00714 int m_lineStart;
00715
00717 int m_eof;
00718
00720 enum LineState {
00721 LS_SEEK,
00722 LS_MAYBE_CRLF,
00723 LS_MAYBE_CONTINUATION
00724 };
00726 LineState m_lineState;
00727
00729 bool m_bFirstChunk;
00730
00732 int m_totalSent;
00733
00735 bool m_connected;
00736
00738 bool m_autoRedirect;
00739
00741 AsyncIoType m_AsyncIoType;
00742
00744 HANDLE m_hCompletionPort;
00745 };
00746
00747 #ifdef _MSC_VER
00748 #pragma warning(default: 4251)
00749 #endif
00750
00752 typedef CAutoRefCountedPtr<CHTTP> CHTTPPtr;
00753
00754 }
00755
00756 #endif // OW32_http_h