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

AsyncSocket.h

Go to the documentation of this file.
00001 /*  AsyncSocket.h - SSL communication through the Schannel API
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_AsyncSocket_h
00027 #define OW32_AsyncSocket_h
00028 
00029 #include <OW32/windows.h>
00030 #include <OW32/OW32Libs.h>
00031 #include <OW32/IoCompletion.h>
00032 #include <OW32/Thread.h>
00033 #include <OW32/IoTimeoutManager.h>
00034 #include <OW32/SyncObjects.h>
00035 #include <OW32/RefCounted.h>
00036 #include <OW32/SockAddrIn.h>
00037 #include <tchar.h>
00038 #include <cstddef>
00039 
00040 // Open Win32 namespace
00041 namespace OW32
00042 {
00043 
00045 enum AsyncIoType
00046 {
00048     AsyncIo_IoCompletion,
00050     AsyncIo_Blocking,
00052     AsyncIo_Message,
00054     AsyncIo_APC
00055 };
00056 
00058 class OW32_LIB_EXPORT CAsyncSocketCallback
00059 {
00060 public:
00067     virtual void onReadCompletion(BOOL /*bRet*/, DWORD /*cbReceived*/) {}
00068 
00075     virtual void onSendCompletion(BOOL /*bRet*/, DWORD /*cbSent*/) {}
00076 
00083     virtual void onTransmitFileCompletion(BOOL /*bRet*/, DWORD /*cbSent*/) {}
00084 
00090     virtual void onConnectCompletion(BOOL /*bRet*/) {}
00091 
00097     virtual void onCloseCompletion(BOOL /*bRet*/) {}
00098 
00104     virtual void onAcceptCompletion(BOOL /*bRet*/) {}
00105 
00112     virtual void onTimeout() {}
00113 
00119     virtual void onAllNotificationsProcessed() {}
00120 };
00121 
00125 class OW32_LIB_EXPORT CAsyncSocketLib
00126 {
00127 public:
00142     static bool initialise(
00143         AsyncIoType     model,
00144         HINSTANCE       hInstance = NULL,
00145         WORD            wSocketsVersion = MAKEWORD(0,0),
00146         HANDLE          hCompletionPort = NULL);
00147 
00156     static bool terminate();
00157     
00186     static bool initialiseThread();
00187     
00194     static bool terminateThread();
00195 
00202     static CIoTimeoutManager *getTimeoutManager();
00203 };
00204 
00212 class OW32_LIB_EXPORT CAsyncConnectionThread : public CThread
00213 {
00214 public:
00215     CAsyncConnectionThread() : 
00216         CThread(false),
00217         m_fOK(false)
00218     {
00219     }
00220 
00225     virtual BOOL postTerminate() {
00226         return PostThreadMessage(GetId(), WM_QUIT, 0, 0);
00227     }
00228 
00232     virtual BOOL terminate() {
00233         if (GetHandle() != NULL)
00234         {
00235             if (!postTerminate())
00236                 return FALSE;
00237             return WaitForSingleObject(GetHandle(), INFINITE) == WAIT_OBJECT_0;
00238         }
00239         return TRUE;
00240     }
00241 
00246     virtual BOOL initialise() {
00247         if (!Create())
00248             return FALSE;
00249         if (WaitForSingleObject(m_threadReady, INFINITE) != WAIT_OBJECT_0)
00250             return FALSE;
00251         
00252         if (!m_fOK) {
00253             if (WaitForSingleObject(GetHandle(), INFINITE) != WAIT_OBJECT_0)
00254                 return FALSE;
00255         }
00256         return (BOOL)m_fOK;
00257     }
00258 
00259     virtual unsigned int Run() {
00260         m_fOK = CAsyncSocketLib::initialiseThread();
00261         m_threadReady.Set();
00262         if (!m_fOK)
00263             return 0;
00264 
00265         MSG msg;
00266         while (GetMessage(&msg, NULL, 0, 0) > 0) {
00267             TranslateMessage(&msg);
00268             DispatchMessage(&msg);
00269         }
00270         (void)CAsyncSocketLib::terminateThread();
00271         return 0;
00272     }
00273 
00274 private:
00275     // No copy or assignment
00276     CAsyncConnectionThread(const CAsyncConnectionThread& other);
00277     CAsyncConnectionThread& operator=(const CAsyncConnectionThread& other);
00278 
00279     bool    m_fOK;
00280     CEvent  m_threadReady;
00281 };
00282 
00286 class OW32_LIB_EXPORT CAsyncSocketBase
00287 {
00288 public:
00294     CAsyncSocketBase(CAsyncSocketCallback* pCallback) :
00295         m_pCallback(pCallback),
00296         m_socket(INVALID_SOCKET),
00297         m_timeout(static_cast<DWORD>(-1))
00298     {
00299     }
00300 
00307     CAsyncSocketBase(CAsyncSocketCallback* pCallback, SOCKET s) :
00308         m_pCallback(pCallback),
00309         m_socket(s),
00310         m_timeout(static_cast<DWORD>(-1))
00311     {
00312     }
00313     
00317     virtual ~CAsyncSocketBase()
00318     {
00319         if (m_socket != INVALID_SOCKET)
00320             ::closesocket(m_socket);
00321     }
00322 
00328     void setCallback(CAsyncSocketCallback* pCallback)
00329     {
00330         m_pCallback = pCallback; 
00331     }
00332 
00338     CAsyncSocketCallback* getCallback() const 
00339     {
00340         return m_pCallback; 
00341     }
00342 
00346     operator SOCKET() { return m_socket; }
00347 
00351     operator HANDLE() { return (HANDLE)m_socket; }
00352 
00356     SOCKET detach()
00357     {
00358         SOCKET s = m_socket;
00359         m_socket = INVALID_SOCKET;
00360         return s;
00361     }
00362 
00368     void attach(SOCKET s)
00369     {
00370         if (m_socket != INVALID_SOCKET)
00371             ::closesocket(m_socket);
00372         m_socket = s;
00373     }
00374 
00380     virtual void setTimeout(DWORD timeout)
00381     {
00382         m_timeout = timeout;
00383     }
00384 
00390     virtual DWORD getTimeout()
00391     {
00392         return m_timeout;
00393     }
00394 
00398     virtual int close()
00399     {
00400         if (m_socket != INVALID_SOCKET)
00401         {
00402             int ret = ::closesocket(m_socket);
00403             m_socket = INVALID_SOCKET;
00404             return ret;
00405         }
00406         return 0;
00407     }
00408 
00416     int bind(const struct sockaddr* name, int namelen)
00417     {
00418         return ::bind(m_socket, name, namelen);
00419     }
00420 
00427     int bind(CSockAddrIn& sockaddr_in)
00428     {
00429         return bind((const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in));
00430     }
00431 
00438     int listen(int backlog = SOMAXCONN)
00439     {
00440         return ::listen(m_socket, backlog);
00441     }
00442 
00451     virtual SOCKET accept(sockaddr* addr, int* addrlen)
00452     {
00453         return ::accept(m_socket, addr, addrlen);
00454     }
00455 
00463     virtual SOCKET accept(CSockAddrIn& sockaddr_in)
00464     {
00465         int len = sizeof(sockaddr_in);
00466         return accept((struct sockaddr *)&sockaddr_in, &len);
00467     }
00468 
00476     virtual int connect(const struct sockaddr* name, int namelen)
00477     {
00478         return ::connect(m_socket, name, namelen);
00479     }
00480 
00487     virtual int connect(CSockAddrIn& sockaddr_in)
00488     {
00489         return connect((const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); 
00490     }
00491 
00497     virtual int shutdown(int how)
00498     {
00499         return ::shutdown(m_socket, how);
00500     }
00501 
00512     virtual int recv(char* buf, int len) = 0;
00513 
00524     virtual int send(const char* buf, int len) = 0;
00525 
00536     virtual int sendv(WSABUF *bufs, DWORD nbufs)
00537     {
00538         bufs;
00539         nbufs;
00540         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00541         return SOCKET_ERROR;
00542     }
00543 
00554     virtual int transmitFile(HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, 
00555                              LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags)
00556     {
00557         hFile;
00558         nNumberOfBytesToWrite;
00559         nNumberOfBytesPerSend;
00560         lpTransmitBuffers;
00561         dwFlags;
00562         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00563         return SOCKET_ERROR;
00564     }
00565 
00566 protected:
00570     CAsyncSocketCallback    *m_pCallback;
00571 
00575     SOCKET                  m_socket;
00576 
00580     DWORD                   m_timeout;
00581 
00582 private:
00583     // No copy or assignment
00584     CAsyncSocketBase(const CAsyncSocketBase &other);
00585     CAsyncSocketBase& operator=(const CAsyncSocketBase &other);
00586 };
00587 
00589 class OW32_LIB_EXPORT CAsyncBlockingSocket : public CAsyncSocketBase
00590 {
00591 public:
00592     CAsyncBlockingSocket(CAsyncSocketCallback* pCallback, SOCKET s) :
00593         CAsyncSocketBase(pCallback, s)
00594     {
00595     }
00596 
00597     CAsyncBlockingSocket(CAsyncSocketCallback* pCallback) :
00598         CAsyncSocketBase(pCallback)
00599     {
00600     }
00601 
00602     virtual int recv(char* buf, int len);
00603     virtual int send(const char* buf, int len);
00604     virtual int connect(const struct sockaddr* name, int namelen);
00605     virtual int connect(CSockAddrIn& sockaddr_in) { return connect((const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); }
00606 
00607 private:
00608     // No copy or assignment
00609     CAsyncBlockingSocket(const CAsyncBlockingSocket& other);
00610     CAsyncBlockingSocket& operator=(const CAsyncBlockingSocket& other);
00611 };
00612 
00614 class OW32_LIB_EXPORT CAsyncIoCompletionSocket : 
00615     private CIoCompletion,
00616     public CAsyncSocketBase,
00617     public CIoTimeoutCallback
00618 {
00619 public:
00620     DLL_IMPLEMENT_IO_COMPLETION(CAsyncIoCompletionSocket, OW32_LIB_EXPORT)
00621 
00622     
00628     CAsyncIoCompletionSocket(CAsyncSocketCallback* pCallback, SOCKET s) :
00629         CAsyncSocketBase(pCallback,s),
00630         m_notificationCount(0),
00631         m_timeoutRefs(0)
00632     {
00633         Init();
00634     }
00635 
00641     CAsyncIoCompletionSocket(CAsyncSocketCallback* pCallback) :
00642         CAsyncSocketBase(pCallback),
00643         m_notificationCount(0),
00644         m_timeoutRefs(0)
00645     {
00646         Init();
00647     }
00648 
00652     virtual ~CAsyncIoCompletionSocket();
00653 
00659     bool associateWithIoCompletionPort(HANDLE hCompletionPort)
00660     {
00661         return !!CreateIoCompletionPort((HANDLE)(SOCKET)m_socket, hCompletionPort, (ULONG_PTR)this, 0) != NULL;
00662     }
00663 
00668     virtual int close();
00669 
00677     virtual int connect(const struct sockaddr* name, int namelen);
00678 
00685     virtual int connect(CSockAddrIn& sockaddr_in)
00686     {
00687         return connect((const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); 
00688     }
00689 
00695     virtual int shutdown(int how);
00696 
00702     virtual void setTimeout(DWORD timeout);
00703 
00714     virtual int recv(char* buf, int len);
00715 
00726     virtual int send(const char* buf, int len);
00727 
00738     virtual int sendv(WSABUF *bufs, DWORD nbufs);
00739 
00750     virtual int transmitFile(HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, 
00751                              LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags);
00752 
00753 
00758     void expectNotification()
00759     {
00760         InterlockedIncrement(&m_notificationCount);
00761     }
00762 
00766     void receivedNotification();
00767 
00768 private:
00769     // No copy or assignment
00770     CAsyncIoCompletionSocket(const CAsyncIoCompletionSocket& other);
00771     CAsyncIoCompletionSocket& operator=(const CAsyncIoCompletionSocket& other);
00772 
00773 // CIoTimeoutCallback
00774     virtual void onTimeout(LPVOID Context);
00775 
00776 // IOCP notification functions
00777     friend static LRESULT CALLBACK SocketNotifyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
00778     void onConnectCompletion(BOOL bRet, DWORD cbBytesReceived, LPOVERLAPPED lpOS);
00779     void onSendCompletion(BOOL bRet, DWORD cbBytesSent, LPOVERLAPPED lpOS);
00780     void onReadCompletion(BOOL bRet, DWORD cbBytesReceived, LPOVERLAPPED lpOS);
00781     void onTransmitFileCompletion(BOOL bRet, DWORD cbBytesReceived, LPOVERLAPPED lpOS);
00782 
00786     inline bool AddTimeout();
00787 
00791     inline void ReleaseTimeout();
00792 
00796     void Init()
00797     {
00798         ZeroMemory(&m_osRead, sizeof(m_osRead));
00799         m_osRead.lpCompletion = onReadCompletion;
00800 
00801         ZeroMemory(&m_osSend, sizeof(m_osSend));
00802 
00803         m_SocketMap = 0;
00804     }
00805 
00807     CCriticalSection    m_socketLock;
00808 
00810     LONG                m_notificationCount;
00811 
00813     LONG                m_timeoutRefs;
00814 
00819     LPVOID              m_SocketMap;
00820     unsigned __int64    m_mapKey;
00821 
00823     OVERLAPPEDPLUS      m_osSend;
00824     OVERLAPPEDPLUS      m_osRead;
00825 };
00826 
00828 class OW32_LIB_EXPORT CAsyncAPCSocket : 
00829     public CAsyncSocketBase
00830 {
00831 public:
00832     CAsyncAPCSocket(CAsyncSocketCallback* pCallback, SOCKET s) :
00833         CAsyncSocketBase(pCallback,s)
00834     {
00835         ZeroMemory(&m_osRead, sizeof(m_osRead));
00836         m_osRead.pParent = this;
00837         ZeroMemory(&m_osSend, sizeof(m_osSend));
00838         m_osSend.pParent = this;
00839     }
00840 
00841     CAsyncAPCSocket(CAsyncSocketCallback* pCallback) :
00842         CAsyncSocketBase(pCallback)
00843     {
00844         ZeroMemory(&m_osRead, sizeof(m_osRead));
00845         m_osRead.pParent = this;
00846         ZeroMemory(&m_osSend, sizeof(m_osSend));
00847         m_osSend.pParent = this;
00848     }
00849 
00850     virtual ~CAsyncAPCSocket();
00851 
00852     virtual int recv(char* buf, int len);
00853     virtual int send(const char* buf, int len);
00854     virtual int connect(const struct sockaddr* name, int namelen);
00855     virtual int connect(CSockAddrIn& sockaddr_in) { return connect((const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); }
00856 
00857 private:
00858     // No copy or assignment
00859     CAsyncAPCSocket(const CAsyncAPCSocket& other);
00860     CAsyncAPCSocket& operator=(const CAsyncAPCSocket& other);
00861 
00862     static void CALLBACK onSendCompletion(DWORD nErrorCode, DWORD cbTransferred, LPOVERLAPPED lpOverlapped);
00863     static void CALLBACK onReadCompletion(DWORD nErrorCode, DWORD cbTransferred, LPOVERLAPPED lpOverlapped);
00864 
00865     struct OW32_LIB_EXPORT OVERLAPPEDPLUS : public OVERLAPPED
00866     {
00867         CAsyncAPCSocket* pParent;
00868     };
00869 
00870     OVERLAPPEDPLUS m_osSend;
00871     OVERLAPPEDPLUS m_osRead;
00872 };
00873 
00875 class OW32_LIB_EXPORT CAsyncMessageSocket : 
00876     public CAsyncSocketBase
00877 {
00878 public:
00879     CAsyncMessageSocket(CAsyncSocketCallback* pCallback, SOCKET s) :
00880         CAsyncSocketBase(&m_callback,s),
00881         m_pCallback(pCallback),
00882         m_readBuf(0),
00883         m_sendBuf(0)
00884     {
00885         (void)setAsync();
00886     }
00887 
00888     CAsyncMessageSocket(CAsyncSocketCallback* pCallback) :
00889         CAsyncSocketBase(&m_callback),
00890         m_pCallback(pCallback),
00891         m_readBuf(0),
00892         m_sendBuf(0)
00893     {
00894     }
00895 
00896     ~CAsyncMessageSocket();
00897 
00898     virtual int recv(char* buf, int len);
00899     virtual int send(const char* buf, int len);
00900     virtual int connect(const struct sockaddr* name, int namelen);
00901     virtual int connect(CSockAddrIn& sockaddr_in) { return connect((const struct sockaddr *)&sockaddr_in, sizeof(sockaddr_in)); }
00902 
00903 private:
00904     // No copy or assignment
00905     CAsyncMessageSocket(const CAsyncMessageSocket& other);
00906     CAsyncMessageSocket& operator=(const CAsyncMessageSocket& other);
00907 
00908     // Two slightly bent functions that make this fit into the IOCP model
00909     void onSendCompletion() { m_pCallback->onSendCompletion(TRUE, m_sendLen); }
00910     void onReadCompletion() { m_pCallback->onReadCompletion(TRUE, m_readLen); }
00911     friend static LRESULT CALLBACK SocketNotifyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
00912 
00913     // interception layer
00914     class OW32_LIB_EXPORT CAsyncMessageSocketCallback : public CAsyncSocketCallback
00915     {
00916     public:
00917         virtual void onReadCompletion(BOOL bRet, DWORD cbReceived);
00918         virtual void onSendCompletion(BOOL bRet, DWORD cbSent);
00919         virtual void onConnectCompletion(BOOL bRet) { 
00920             CAsyncMessageSocket* pParent = (CAsyncMessageSocket*)((char*)this - offsetof(CAsyncMessageSocket,m_callback));
00921             pParent->m_pCallback->onConnectCompletion(bRet); 
00922         }
00923         virtual void onCloseCompletion(BOOL bRet) {
00924             CAsyncMessageSocket* pParent = (CAsyncMessageSocket*)((char*)this - offsetof(CAsyncMessageSocket,m_callback));
00925             pParent->m_pCallback->onCloseCompletion(bRet); 
00926         }
00927     };
00928     friend CAsyncMessageSocketCallback;
00929     CAsyncMessageSocketCallback m_callback;
00930 
00931     int setAsync();
00932 
00933     // We need to keep this for sending ourselves messages
00934     HWND m_hWnd;
00935 
00936     CAsyncSocketCallback* m_pCallback;
00937 
00938     char* m_readBuf;
00939     int m_readLen;
00940 
00941     const char* m_sendBuf;
00942     int m_sendLen;
00943 };
00944 
00945 }; // namespace OW32
00946 
00947 #endif // OW32_AsyncSocket_h

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