00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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 , DWORD ) {}
00068
00075 virtual void onSendCompletion(BOOL , DWORD ) {}
00076
00083 virtual void onTransmitFileCompletion(BOOL , DWORD ) {}
00084
00090 virtual void onConnectCompletion(BOOL ) {}
00091
00097 virtual void onCloseCompletion(BOOL ) {}
00098
00104 virtual void onAcceptCompletion(BOOL ) {}
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
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
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
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
00770 CAsyncIoCompletionSocket(const CAsyncIoCompletionSocket& other);
00771 CAsyncIoCompletionSocket& operator=(const CAsyncIoCompletionSocket& other);
00772
00773
00774 virtual void onTimeout(LPVOID Context);
00775
00776
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
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
00905 CAsyncMessageSocket(const CAsyncMessageSocket& other);
00906 CAsyncMessageSocket& operator=(const CAsyncMessageSocket& other);
00907
00908
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
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
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 };
00946
00947 #endif // OW32_AsyncSocket_h