Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

http.h

Go to the documentation of this file.
00001 /*  http.h - simple HTTP request library
00002     Copyright (C) 2001-2004 Mark Weaver
00003     Written by Mark Weaver <mark@npsl.co.uk>
00004 
00005     Part of the Open-Win32 library.
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public
00017     License along with this library; if not, write to the
00018     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA  02111-1307, USA.
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> // for std::auto_ptr
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* /*http*/) {}
00107 
00111     virtual void OnConnectionClosed(CHTTP* /*http*/) {}
00112 
00116     virtual void OnError(CHTTP* /*http*/) {}
00117 
00121     virtual void OnPageReceived(CHTTP* /*http*/) {}
00122 
00127     virtual void OnChunkReceived(CHTTP* /*http*/, int /*currentLength*/) {}
00128 
00138     virtual bool OnRedirect(CHTTP* /*http*/) { return false; }
00139 
00144     virtual void OnRequestCompleted(CHTTP* /*http*/) {}
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     // const int initialisers in class declaration
00226     // are unsupported by VC++ so we use an enum instead
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     // Helper functions
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 } // namespace OW32
00755 
00756 #endif // OW32_http_h

Generated on Sun Jun 5 01:29:17 2005 for OW32 by  doxygen 1.3.9.1