00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00026 #ifndef OW32_Listener_h
00027 #define OW32_Listener_h
00028
00029 #include <OW32/Socket.h>
00030 #include <OW32/AsyncSocket.h>
00031 #include <OW32/XSOCKET.h>
00032 #include <OW32/IoCompletion.h>
00033 #include <OW32/SyncObjects.h>
00034
00035 namespace OW32
00036 {
00037
00038 class OW32_LIB_EXPORT CListener;
00039
00041 class OW32_LIB_EXPORT CListenerCallback
00042 {
00043 public:
00050 virtual BOOL onAcceptCompletion(CListener* , BOOL bRet, DWORD ) { return bRet; }
00051 };
00052
00054 class OW32_LIB_EXPORT CListener
00055 {
00056 public:
00060 CListener(CListenerCallback* pCallback) :
00061 m_pCallback(pCallback),
00062 m_port(0)
00063 {
00064 }
00065
00067 virtual ~CListener() = 0 {}
00068
00072 virtual void Cancel()
00073 {
00074 m_sListen.close();
00075 }
00076
00080 virtual bool Cancelled()
00081 {
00082 return m_sListen == INVALID_SOCKET;
00083 }
00084
00086 CListenerCallback *GetCallback() const
00087 {
00088 return m_pCallback;
00089 }
00090
00092 int GetPort() const { return m_port; }
00093
00097 virtual BOOL Listen(int port)
00098 {
00099
00100
00101 m_sListen.Attach(WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED));
00102 if (m_sListen == INVALID_SOCKET)
00103 return FALSE;
00104
00105
00106 CSockAddrIn local_sin(htons (static_cast<u_short>(port)));
00107 if (m_sListen.bind(local_sin)==SOCKET_ERROR)
00108 return FALSE;
00109
00110
00111 if (m_sListen.listen (SOMAXCONN) == SOCKET_ERROR)
00112 return FALSE;
00113
00114 m_port = port;
00115 return TRUE;
00116 }
00117
00119 virtual int Accept()=0;
00120
00124 virtual int ListenAndAccept(int port)
00125 {
00126 return (Listen(port) != SOCKET_ERROR && Accept() != SOCKET_ERROR) ? 0 : SOCKET_ERROR;
00127 }
00128
00133 virtual int GetAddresses(sockaddr_in** local_address, sockaddr_in** remote_address)=0;
00134
00138 virtual int GetRemoteAddress(sockaddr_in** remote_address)
00139 {
00140 return GetAddresses(NULL,remote_address);
00141 }
00142
00146 virtual int GetLocalAddress(sockaddr_in** local_address)
00147 {
00148 GetAddresses(local_address,NULL);
00149 return 0;
00150 }
00151
00153 virtual SOCKET DetachAcceptedSocket() {
00154 return m_sAccepted.Detach();
00155 }
00156
00157 protected:
00159 int m_port;
00161 CSocket m_sListen;
00163 XSOCKET m_sAccepted;
00165 CListenerCallback* m_pCallback;
00166 };
00167
00169 class OW32_LIB_EXPORT CIoCompletionListener :
00170 public CListener,
00171 public CIoCompletion
00172 {
00173 public:
00175 DLL_IMPLEMENT_IO_COMPLETION(CIoCompletionListener, OW32_LIB_EXPORT)
00176
00177
00180 CIoCompletionListener(CListenerCallback* pCallback) :
00181 CListener(pCallback)
00182 {
00183 ZeroMemory(&m_os, sizeof(m_os));
00184 m_os.lpCompletion = onAcceptCompletion;
00185 }
00186
00190 virtual void Cancel()
00191 {
00192 CSingleLock lock(m_socketLock);
00193 m_sListen.close();
00194 }
00195
00199 virtual bool Cancelled()
00200 {
00201 CSingleLock lock(m_socketLock);
00202 return m_sListen == INVALID_SOCKET;
00203 }
00204
00206 void onAcceptCompletion(BOOL bRet, DWORD cbTransferred, LPOVERLAPPED )
00207 {
00208 if (m_pCallback->onAcceptCompletion(this, bRet, cbTransferred))
00209 {
00210 while (Accept() == SOCKET_ERROR && m_pCallback->onAcceptCompletion(this, FALSE, 0))
00211 ;
00212 }
00213 }
00214
00218 virtual int Listen(int port)
00219 {
00220
00221
00222 m_sListen.Attach(WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED));
00223 if (m_sListen == INVALID_SOCKET)
00224 return FALSE;
00225
00226
00227 CSockAddrIn local_sin(htons (static_cast<u_short>(port)));
00228 if (m_sListen.bind(local_sin)==SOCKET_ERROR)
00229 return SOCKET_ERROR;
00230
00231
00232 if (m_sListen.listen (SOMAXCONN) == SOCKET_ERROR)
00233 return SOCKET_ERROR;
00234
00235 m_port = port;
00236 return 0;
00237 }
00238
00240 virtual int Accept()
00241 {
00242
00243
00244 m_sAccepted = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);
00245 if (m_sAccepted == SOCKET_ERROR)
00246 return SOCKET_ERROR;
00247
00248 DWORD dwDummy=0;
00249 CSingleLock lock(m_socketLock);
00250 if (!AcceptEx(m_sListen, m_sAccepted, m_buffer, 0,
00251 sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16,
00252 &dwDummy, &m_os))
00253 {
00254 DWORD error = ::GetLastError();
00255 lock.Unlock();
00256 if (error != ERROR_IO_PENDING)
00257 return SOCKET_ERROR;
00258 }
00259 return 0;
00260 }
00261
00263 int ListenAndAcceptWithPort(int Port, HANDLE hCompletionPort)
00264 {
00265 return (Listen(Port) != SOCKET_ERROR &&
00266 associateWithIoCompletionPort(hCompletionPort) &&
00267 Accept() != SOCKET_ERROR) ? 0 : SOCKET_ERROR;
00268 }
00269
00274 virtual int GetAddresses(sockaddr_in** local_address, sockaddr_in** remote_address)
00275 {
00276 INT local_address_len = sizeof(sockaddr_in);
00277 INT remote_address_len = sizeof(sockaddr_in);
00278 sockaddr *temp_local, *temp_remote;
00279 GetAcceptExSockaddrs(m_buffer, 0, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16,
00280 local_address ? (sockaddr**)local_address : &temp_local, &local_address_len,
00281 remote_address ? (sockaddr**)remote_address : &temp_remote, &remote_address_len);
00282 return 0;
00283 }
00284
00289 BOOL associateWithIoCompletionPort(HANDLE hCompletionPort)
00290 {
00291 return CreateIoCompletionPort(
00292 (HANDLE)(SOCKET)m_sListen, hCompletionPort,
00293 reinterpret_cast<ULONG_PTR>(static_cast<CIoCompletion*>(this)), 0) != NULL;
00294 }
00295
00297 operator SOCKET() { return m_sListen; }
00298
00299 private:
00300
00301 CIoCompletionListener(const CIoCompletionListener& other);
00302 CIoCompletionListener& operator=(const CIoCompletionListener& other);
00303
00304 char m_buffer[(sizeof(sockaddr_in)+16)*2];
00305 OVERLAPPEDPLUS m_os;
00306 CCriticalSection m_socketLock;
00307 };
00308
00310 class OW32_LIB_EXPORT CMessageListener :
00311 public CListener,
00312 public CAsyncSocketCallback
00313 {
00314 public:
00318 CMessageListener(CListenerCallback* pCallback) :
00319 CListener(pCallback)
00320 {
00321 }
00322
00324 void onAcceptCompletion(BOOL bRet)
00325 {
00326 bRet;
00327 int sock_addr_len = sizeof(m_remote_addr);
00328 m_sAccepted = m_sListen.accept(&m_remote_addr, &sock_addr_len);
00329 if (m_pCallback->onAcceptCompletion(this, m_sAccepted!=SOCKET_ERROR, 0))
00330 {
00331 while (!Accept() && m_pCallback->onAcceptCompletion(this, FALSE, 0))
00332 ;
00333 }
00334 }
00335
00337 int Accept();
00338
00343 virtual int GetAddresses(sockaddr_in** local_addr, sockaddr_in** remote_addr)
00344 {
00345 if (remote_addr)
00346 *remote_addr = (sockaddr_in*)&m_remote_addr;
00347 if (local_addr)
00348 {
00349 *local_addr = 0;
00350 int local_addr_len = sizeof(m_local_addr);
00351 if (getsockname(m_sAccepted, &m_local_addr, &local_addr_len)==SOCKET_ERROR)
00352 return SOCKET_ERROR;
00353 *local_addr = (sockaddr_in*)&m_local_addr;
00354 }
00355 return 0;
00356 }
00357
00359 operator SOCKET() { return m_sListen; }
00360
00361 private:
00362
00363 CMessageListener(const CMessageListener& other);
00364 CMessageListener& operator=(const CMessageListener& other);
00365
00366 sockaddr m_remote_addr,m_local_addr;
00367 };
00368
00369 }
00370
00371 #endif // OW32_Listener_h