SocketHandle.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. /*
  2. ** Copyright 2003-2009, Ernest Laurentin (http://www.ernzo.com/)
  3. **
  4. ** Licensed under the Apache License, Version 2.0 (the "License");
  5. ** you may not use this file except in compliance with the License.
  6. ** You may obtain a copy of the License at
  7. **
  8. ** http://www.apache.org/licenses/LICENSE-2.0
  9. **
  10. ** Unless required by applicable law or agreed to in writing, software
  11. ** distributed under the License is distributed on an "AS IS" BASIS,
  12. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ** See the License for the specific language governing permissions and
  14. ** limitations under the License.
  15. **
  16. ** File: SocketHandle.cpp
  17. ** Version: 1.4 - IPv6 support
  18. ** 1.3 - Update for Asynchronous mode / Linux port
  19. ** 1.2 - Update interface for TCP remote connection
  20. ** 1.1 - Added multicast support
  21. */
  22. #include "stdafx.h"
  23. #ifdef WIN32
  24. #include <stdlib.h>
  25. #ifndef UNDER_CE
  26. #include <crtdbg.h>
  27. #endif
  28. #include <strsafe.h>
  29. #endif
  30. #include "SocketHandle.h"
  31. #ifndef BUFFER_SIZE
  32. #define BUFFER_SIZE 64*1024
  33. #endif
  34. #ifndef SOCKHANDLE_TTL
  35. #define SOCKHANDLE_TTL 5
  36. #endif
  37. #ifndef SOCKHANDLE_HOPS
  38. #define SOCKHANDLE_HOPS 10
  39. #endif
  40. #define HOSTNAME_SIZE MAX_PATH
  41. #define STRING_LENGTH 40
  42. #if !defined(PLATFORM_HAS_INETFUNC)
  43. const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
  44. int inet_pton(int af, const char *src, void *dst);
  45. #endif
  46. #ifdef WIN32
  47. #ifndef UNDER_CE
  48. #pragma comment(lib, "ws2_32.lib")
  49. #else
  50. #pragma comment(lib, "Ws2.lib")
  51. #endif
  52. #endif
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // SockAddrIn Struct
  55. SockAddrIn SockAddrIn::NULLAddr;
  56. ///////////////////////////////////////////////////////////////////////////////
  57. // Constructs
  58. SockAddrIn::SockAddrIn()
  59. {
  60. Clear();
  61. }
  62. SockAddrIn::SockAddrIn(const SockAddrIn& sin)
  63. {
  64. Copy( sin );
  65. }
  66. SockAddrIn::~SockAddrIn()
  67. {
  68. }
  69. ///////////////////////////////////////////////////////////////////////////////
  70. // Clear
  71. void SockAddrIn::Clear()
  72. {
  73. memset(this, 0, sizeof(sockaddr_storage));
  74. }
  75. ///////////////////////////////////////////////////////////////////////////////
  76. // Copy
  77. SockAddrIn& SockAddrIn::Copy(const SockAddrIn& sin)
  78. {
  79. ss_family = sin.ss_family;
  80. memcpy(this, &sin, Size());
  81. return *this;
  82. }
  83. ///////////////////////////////////////////////////////////////////////////////
  84. // IsEqual
  85. bool SockAddrIn::IsEqual(const SockAddrIn& sin) const
  86. {
  87. // Is it Equal? - ignore 'sin_zero'
  88. if ( ss_family == AF_INET ) {
  89. return (memcmp(this, &sin, Size()-8) == 0);
  90. }
  91. return (memcmp(this, &sin, Size()) == 0);
  92. }
  93. ///////////////////////////////////////////////////////////////////////////////
  94. // CreateFrom
  95. bool SockAddrIn::CreateFrom(LPCTSTR pszAddr, LPCTSTR pszService, int nFamily /*=AF_INET*/)
  96. {
  97. Clear();
  98. CSocketHandle::GetAddressInfo(pszAddr, pszService, nFamily, *this);
  99. SOCKADDR_IN* psin = reinterpret_cast<SOCKADDR_IN*>(this);
  100. psin->sin_addr.s_addr = htonl(INADDR_ANY);
  101. return !IsNull();
  102. }
  103. ///////////////////////////////////////////////////////////////////////////////
  104. // CreateFrom
  105. bool SockAddrIn::CreateFrom(ULONG lIPAddr, USHORT nPort, int nFamily /*= AF_INET*/, bool bFmtHost /*= true*/)
  106. {
  107. Clear();
  108. _ASSERTE( nFamily == AF_INET ); // supports IPv4 only
  109. SOCKADDR_IN* psin = reinterpret_cast<SOCKADDR_IN*>(this);
  110. psin->sin_family = static_cast<short>(nFamily);
  111. if ( bFmtHost )
  112. {
  113. psin->sin_addr.s_addr = htonl( lIPAddr );
  114. psin->sin_port = htons( nPort );
  115. }
  116. else
  117. {
  118. psin->sin_addr.s_addr = lIPAddr;
  119. psin->sin_port = nPort;
  120. }
  121. return !IsNull();
  122. }
  123. ///////////////////////////////////////////////////////////////////////////////
  124. // CSocketHandle
  125. CSocketHandle::CSocketHandle()
  126. : m_hSocket(INVALID_SOCKET)
  127. {
  128. }
  129. CSocketHandle::~CSocketHandle()
  130. {
  131. Close();
  132. }
  133. ///////////////////////////////////////////////////////////////////////////////
  134. // IsOpen
  135. bool CSocketHandle::IsOpen() const
  136. {
  137. return ( INVALID_SOCKET != m_hSocket );
  138. }
  139. ///////////////////////////////////////////////////////////////////////////////
  140. // GetSocket
  141. SOCKET CSocketHandle::GetSocket() const
  142. {
  143. return m_hSocket;
  144. }
  145. ///////////////////////////////////////////////////////////////////////////////
  146. // GetSocketType
  147. int CSocketHandle::GetSocketType() const
  148. {
  149. int type = -1;
  150. if ( INVALID_SOCKET != m_hSocket ) {
  151. socklen_t optlen = sizeof(int);
  152. if ( getsockopt(GetSocket(), SOL_SOCKET, SO_TYPE, reinterpret_cast<char*>(&type),
  153. &optlen) == SOCKET_ERROR)
  154. {
  155. SetLastError( WSAGetLastError() );
  156. }
  157. }
  158. return type;
  159. }
  160. ///////////////////////////////////////////////////////////////////////////////
  161. // Attach
  162. bool CSocketHandle::Attach(SOCKET sock)
  163. {
  164. if ( INVALID_SOCKET == m_hSocket )
  165. {
  166. m_hSocket = sock;
  167. return true;
  168. }
  169. return false;
  170. }
  171. ///////////////////////////////////////////////////////////////////////////////
  172. // Detach
  173. SOCKET CSocketHandle::Detach()
  174. {
  175. SOCKET sock = m_hSocket;
  176. ::InterlockedExchange(reinterpret_cast<long*>(&m_hSocket), INVALID_SOCKET);
  177. return sock;
  178. }
  179. ///////////////////////////////////////////////////////////////////////////////
  180. // GetSockName
  181. bool CSocketHandle::GetSockName(SockAddrIn& saddr_in) const
  182. {
  183. _ASSERTE( IsOpen() );
  184. if (IsOpen()) {
  185. socklen_t namelen = (socklen_t)saddr_in.Size();
  186. if (SOCKET_ERROR != getsockname(GetSocket(), saddr_in, &namelen))
  187. {
  188. return true;
  189. }
  190. SetLastError( WSAGetLastError() );
  191. }
  192. return false;
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////
  195. // GetPeerName
  196. bool CSocketHandle::GetPeerName(SockAddrIn& saddr_in) const
  197. {
  198. _ASSERTE( IsOpen() );
  199. if (IsOpen()) {
  200. socklen_t namelen = (socklen_t)saddr_in.Size();
  201. if (SOCKET_ERROR != getpeername(GetSocket(), saddr_in, &namelen))
  202. {
  203. return true;
  204. }
  205. SetLastError( WSAGetLastError() );
  206. }
  207. return false;
  208. }
  209. ///////////////////////////////////////////////////////////////////////////////
  210. // Close
  211. void CSocketHandle::Close()
  212. {
  213. if ( IsOpen() )
  214. {
  215. ShutdownConnection(static_cast<SOCKET>(
  216. ::InterlockedExchange((LONG*)&m_hSocket, INVALID_SOCKET)
  217. ));
  218. }
  219. }
  220. ///////////////////////////////////////////////////////////////////////////////
  221. // AddMembership
  222. bool CSocketHandle::AddMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC)
  223. {
  224. _ASSERTE( IsOpen() );
  225. if ( IsOpen() )
  226. {
  227. int nType = 0;
  228. socklen_t nOptLen = sizeof(int);
  229. if ( SOCKET_ERROR != getsockopt(m_hSocket, SOL_SOCKET, SO_TYPE, (char*)&nType, &nOptLen))
  230. {
  231. if ( nType == SOCK_DGRAM )
  232. {
  233. // Setup interface for multicast traffic
  234. SockAddrIn mcastAddr;
  235. if (GetAddressInfo(pszIPAddr, NULL, AF_UNSPEC, mcastAddr))
  236. {
  237. SockAddrIn interfAddr;
  238. GetAddressInfo(pszNIC, NULL, mcastAddr.ss_family, interfAddr);
  239. if ( mcastAddr.ss_family == AF_INET )
  240. {
  241. int nTTL = SOCKHANDLE_TTL;
  242. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&nTTL, sizeof(nTTL)))
  243. {
  244. ULONG ulNIC = interfAddr.GetIPAddr();
  245. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_IF,(char *) &ulNIC, sizeof(ulNIC)))
  246. {
  247. ip_mreq mreq = { 0 };
  248. mreq.imr_multiaddr.s_addr = mcastAddr.GetIPAddr();
  249. mreq.imr_interface.s_addr = ulNIC;
  250. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)))
  251. {
  252. return true;
  253. }
  254. }
  255. }
  256. }
  257. else if ( mcastAddr.ss_family == AF_INET6 )
  258. {
  259. int nTTL = SOCKHANDLE_HOPS;
  260. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&nTTL, sizeof(nTTL)))
  261. {
  262. ipv6_mreq mreq6 = { 0 };
  263. IN6_ADDR mcin6 = ((sockaddr_in6*)&mcastAddr)->sin6_addr;
  264. memcpy(&(mreq6.ipv6mr_multiaddr), &mcin6, sizeof(IN6_ADDR));
  265. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq6, sizeof(mreq6)))
  266. {
  267. return true;
  268. }
  269. }
  270. }
  271. else
  272. {
  273. // invalid socket option
  274. WSASetLastError(WSAENOPROTOOPT);
  275. }
  276. }
  277. }
  278. else
  279. {
  280. // invalid socket option
  281. WSASetLastError(WSAENOPROTOOPT);
  282. }
  283. }
  284. SetLastError( WSAGetLastError() );
  285. }
  286. return false;
  287. }
  288. ///////////////////////////////////////////////////////////////////////////////
  289. // DropMembership
  290. bool CSocketHandle::DropMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC)
  291. {
  292. _ASSERTE( IsOpen() );
  293. if ( IsOpen() )
  294. {
  295. int nType = 0;
  296. socklen_t nOptLen = sizeof(int);
  297. if ( SOCKET_ERROR != getsockopt(m_hSocket, SOL_SOCKET, SO_TYPE, (char*)&nType, &nOptLen))
  298. {
  299. if ( nType == SOCK_DGRAM )
  300. {
  301. SockAddrIn mcastAddr;
  302. if (GetAddressInfo(pszIPAddr, NULL, AF_UNSPEC, mcastAddr))
  303. {
  304. SockAddrIn interfAddr;
  305. GetAddressInfo(pszNIC, NULL, mcastAddr.ss_family, interfAddr);
  306. if ( mcastAddr.ss_family == AF_INET )
  307. {
  308. ip_mreq mreq;
  309. mreq.imr_multiaddr.s_addr = mcastAddr.GetIPAddr();
  310. mreq.imr_interface.s_addr = interfAddr.GetIPAddr();;
  311. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)))
  312. {
  313. return true;
  314. }
  315. }
  316. else if ( mcastAddr.ss_family == AF_INET6 )
  317. {
  318. ipv6_mreq mreq6 = { 0 };
  319. IN6_ADDR mcin6 = ((sockaddr_in6*)&mcastAddr)->sin6_addr;
  320. memcpy(&(mreq6.ipv6mr_multiaddr), &mcin6, sizeof(IN6_ADDR));
  321. if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (const char*)&mreq6, sizeof(mreq6)))
  322. {
  323. return true;
  324. }
  325. }
  326. else
  327. {
  328. // invalid socket option
  329. WSASetLastError(WSAENOPROTOOPT);
  330. }
  331. }
  332. }
  333. else
  334. {
  335. // invalid socket option
  336. WSASetLastError(WSAENOPROTOOPT);
  337. }
  338. }
  339. SetLastError( WSAGetLastError() );
  340. }
  341. return false;
  342. }
  343. ///////////////////////////////////////////////////////////////////////////////
  344. // CreateSocket
  345. bool CSocketHandle::CreateSocket(LPCTSTR pszHostName, LPCTSTR pszServiceName,
  346. int nFamily, int nType, UINT uOptions /* = 0 */)
  347. {
  348. // Socket is already opened
  349. if ( IsOpen() ) {
  350. SetLastError(ERROR_ACCESS_DENIED);
  351. return false;
  352. }
  353. // Create a Socket that is bound to a specific service provider
  354. // nFamily: (AF_INET, AF_INET6)
  355. // nType: (SOCK_STREAM, SOCK_DGRAM)
  356. #ifdef SOCKHANDLE_USE_OVERLAPPED
  357. SOCKET sock = WSASocket(nFamily, nType, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
  358. #else
  359. SOCKET sock = socket(nFamily, nType, IPPROTO_IP);
  360. #endif
  361. if (INVALID_SOCKET != sock)
  362. {
  363. if (uOptions & SO_REUSEADDR)
  364. {
  365. // Inform Windows Sockets provider that a bind on a socket should not be disallowed
  366. // because the desired address is already in use by another socket
  367. BOOL optval = TRUE;
  368. if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof( BOOL ) ) )
  369. {
  370. SetLastError( WSAGetLastError() );
  371. closesocket( sock );
  372. return false;
  373. }
  374. }
  375. if (nType == SOCK_DGRAM)
  376. {
  377. if ((uOptions & SO_BROADCAST) && (nFamily == AF_INET))
  378. {
  379. // Inform Windows Sockets provider that broadcast messages are allowed
  380. BOOL optval = TRUE;
  381. if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (char *) &optval, sizeof( BOOL ) ) )
  382. {
  383. SetLastError( WSAGetLastError() );
  384. closesocket( sock );
  385. return false;
  386. }
  387. }
  388. #ifdef SOCKHANDLE_CONFIGBUF
  389. // configure buffer size
  390. socklen_t rcvbuf = BUFFER_SIZE;
  391. if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbuf, sizeof( int ) ) )
  392. {
  393. SetLastError( WSAGetLastError() );
  394. closesocket( sock );
  395. return false;
  396. }
  397. #endif
  398. }
  399. // Associate a local address with the socket
  400. SockAddrIn sockAddr;
  401. sockAddr.CreateFrom(pszHostName, pszServiceName, nFamily);
  402. if ( SOCKET_ERROR == bind(sock, sockAddr, (int)sockAddr.Size()))
  403. {
  404. SetLastError( WSAGetLastError() );
  405. closesocket( sock );
  406. return false;
  407. }
  408. // Listen to the socket, only valid for connection socket (TCP)
  409. if (SOCK_STREAM == nType)
  410. {
  411. if ( SOCKET_ERROR == listen(sock, SOMAXCONN))
  412. {
  413. SetLastError( WSAGetLastError() );
  414. closesocket( sock );
  415. return false;
  416. }
  417. }
  418. // Success, now we may save this socket
  419. m_hSocket = sock;
  420. }
  421. return (INVALID_SOCKET != sock);
  422. }
  423. ///////////////////////////////////////////////////////////////////////////////
  424. // ConnectTo
  425. bool CSocketHandle::ConnectTo(LPCTSTR pszHostName, LPCTSTR pszRemote,
  426. LPCTSTR pszServiceName, int nFamily, int nType)
  427. {
  428. // Socket is already opened
  429. if ( IsOpen() ) {
  430. SetLastError(ERROR_ACCESS_DENIED);
  431. return false;
  432. }
  433. // Create a Socket that is bound to a specific service provider
  434. // nFamily: (AF_INET, AF_INET6)
  435. // nType: (SOCK_STREAM, SOCK_DGRAM)
  436. #ifdef SOCKHANDLE_USE_OVERLAPPED
  437. SOCKET sock = WSASocket(nFamily, nType, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
  438. #else
  439. SOCKET sock = socket(nFamily, nType, IPPROTO_IP);
  440. #endif
  441. if (INVALID_SOCKET != sock)
  442. {
  443. // Associate a local address with the socket but let provider assign a port number
  444. SockAddrIn sockAddr;
  445. if (false == sockAddr.CreateFrom(pszHostName, TEXT("0"), nFamily))
  446. {
  447. SetLastError( WSAGetLastError() );
  448. closesocket( sock );
  449. return false;
  450. }
  451. if ( SOCKET_ERROR == bind(sock, sockAddr, (int)sockAddr.Size()))
  452. {
  453. SetLastError( WSAGetLastError() );
  454. closesocket( sock );
  455. return false;
  456. }
  457. #ifdef SOCKHANDLE_CONFIGBUF
  458. if (nType == SOCK_DGRAM)
  459. {
  460. // configure buffer size
  461. socklen_t rcvbuf = BUFFER_SIZE;
  462. if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbuf, sizeof( int ) ) )
  463. {
  464. SetLastError( WSAGetLastError() );
  465. closesocket( sock );
  466. return false;
  467. }
  468. }
  469. #endif
  470. // Now get destination address & port
  471. sockAddr.CreateFrom( pszRemote, pszServiceName, nFamily );
  472. // try to connect - if fail, server not ready
  473. if (SOCKET_ERROR == connect( sock, sockAddr, (int)sockAddr.Size()))
  474. {
  475. SetLastError( WSAGetLastError() );
  476. closesocket( sock );
  477. return false;
  478. }
  479. // Success, now we may save this socket
  480. m_hSocket = sock;
  481. }
  482. return (INVALID_SOCKET != sock);
  483. }
  484. ///////////////////////////////////////////////////////////////////////////////
  485. // Read
  486. DWORD CSocketHandle::Read(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn,
  487. DWORD dwTimeout)
  488. {
  489. _ASSERTE( IsOpen() );
  490. _ASSERTE( lpBuffer != NULL );
  491. if (!IsOpen() || lpBuffer == NULL || dwSize < 1L)
  492. return (DWORD)-1L;
  493. fd_set fdRead = { 0 };
  494. TIMEVAL stTime;
  495. TIMEVAL *pstTime = NULL;
  496. if ( INFINITE != dwTimeout ) {
  497. stTime.tv_sec = dwTimeout/1000;
  498. stTime.tv_usec = (dwTimeout%1000)*1000;
  499. pstTime = &stTime;
  500. }
  501. SOCKET s = GetSocket();
  502. // Set Descriptor
  503. FD_SET( s, &fdRead );
  504. // Select function set read timeout
  505. DWORD dwBytesRead = 0L;
  506. int res = 1;
  507. if ( pstTime != NULL )
  508. res = select((int)s, &fdRead, NULL, NULL, pstTime );
  509. if ( res > 0)
  510. {
  511. if (lpAddrIn)
  512. {
  513. // UDP
  514. socklen_t fromlen = sizeof(SOCKADDR_STORAGE);
  515. res = recvfrom(s, reinterpret_cast<LPSTR>(lpBuffer), dwSize, 0, lpAddrIn, &fromlen);
  516. }
  517. else
  518. {
  519. // TCP
  520. res = recv(s, reinterpret_cast<LPSTR>(lpBuffer), dwSize, 0);
  521. }
  522. if ( res == 0 ) {
  523. WSASetLastError(WSAECONNRESET);
  524. res = SOCKET_ERROR;
  525. }
  526. }
  527. if ( res == SOCKET_ERROR )
  528. {
  529. SetLastError( WSAGetLastError() );
  530. }
  531. dwBytesRead = (DWORD)((res >= 0)?(res) : (-1));
  532. return dwBytesRead;
  533. }
  534. #ifdef WIN32
  535. ///////////////////////////////////////////////////////////////////////////////
  536. // ReadEx
  537. DWORD CSocketHandle::ReadEx(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn,
  538. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine)
  539. {
  540. _ASSERTE( IsOpen() );
  541. _ASSERTE( lpBuffer != NULL );
  542. if (!IsOpen() || lpBuffer == NULL || dwSize < 1L)
  543. return (DWORD)-1L;
  544. SOCKET s = GetSocket();
  545. // Send message to peer
  546. WSABUF wsabuf;
  547. wsabuf.buf = (char FAR*)lpBuffer;
  548. wsabuf.len = dwSize;
  549. // Select function set read timeout
  550. DWORD dwBytesRead = 0L;
  551. DWORD dwFlags = 0L;
  552. int res = 0;
  553. if (lpAddrIn)
  554. {
  555. // UDP
  556. socklen_t fromlen = sizeof(SOCKADDR_STORAGE);
  557. res = WSARecvFrom( s, &wsabuf, 1, &dwBytesRead, &dwFlags, lpAddrIn, &fromlen, lpOverlapped, lpCompletionRoutine);
  558. }
  559. else
  560. {
  561. // TCP
  562. res = WSARecv( s, &wsabuf, 1, &dwBytesRead, &dwFlags, lpOverlapped, lpCompletionRoutine);
  563. }
  564. if ( res == SOCKET_ERROR )
  565. {
  566. res = WSAGetLastError();
  567. if ( res != WSA_IO_PENDING )
  568. {
  569. dwBytesRead = (DWORD)-1L;
  570. SetLastError( res );
  571. }
  572. }
  573. return dwBytesRead;
  574. }
  575. #endif
  576. ///////////////////////////////////////////////////////////////////////////////
  577. // Write
  578. DWORD CSocketHandle::Write(const LPBYTE lpBuffer, DWORD dwCount,
  579. const LPSOCKADDR lpAddrIn, DWORD dwTimeout)
  580. {
  581. _ASSERTE( IsOpen() );
  582. _ASSERTE( NULL != lpBuffer );
  583. // validate params
  584. if (!IsOpen() || NULL == lpBuffer)
  585. return (DWORD)-1L;
  586. fd_set fdWrite = { 0 };
  587. TIMEVAL stTime;
  588. TIMEVAL *pstTime = NULL;
  589. if ( INFINITE != dwTimeout ) {
  590. stTime.tv_sec = dwTimeout/1000;
  591. stTime.tv_usec = (dwTimeout%1000)*1000;
  592. pstTime = &stTime;
  593. }
  594. SOCKET s = GetSocket();
  595. // Set Descriptor
  596. FD_SET( s, &fdWrite );
  597. // Select function set write timeout
  598. DWORD dwBytesWritten = 0L;
  599. int res = 1;
  600. if ( pstTime != NULL )
  601. res = select((int)s, NULL, &fdWrite, NULL, pstTime );
  602. if ( res > 0)
  603. {
  604. // Send message to peer
  605. if (lpAddrIn)
  606. {
  607. // UDP
  608. res = sendto( s, reinterpret_cast<LPCSTR>(lpBuffer), dwCount, 0, lpAddrIn, sizeof(SOCKADDR_STORAGE));
  609. }
  610. else
  611. {
  612. // TCP
  613. res = send( s, reinterpret_cast<LPCSTR>(lpBuffer), dwCount, 0);
  614. }
  615. }
  616. if ( res == SOCKET_ERROR )
  617. {
  618. SetLastError( WSAGetLastError() );
  619. }
  620. dwBytesWritten = (DWORD)((res >= 0)?(res) : (-1));
  621. return dwBytesWritten;
  622. }
  623. #ifdef WIN32
  624. ///////////////////////////////////////////////////////////////////////////////
  625. // WriteEx
  626. DWORD CSocketHandle::WriteEx(const LPBYTE lpBuffer, DWORD dwCount,
  627. const LPSOCKADDR lpAddrIn,
  628. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine)
  629. {
  630. _ASSERTE( IsOpen() );
  631. _ASSERTE( NULL != lpBuffer );
  632. // validate params
  633. if (!IsOpen() || NULL == lpBuffer)
  634. return (DWORD)-1L;
  635. SOCKET s = GetSocket();
  636. // Select function set write timeout
  637. DWORD dwBytesWritten = 0L;
  638. int res = 0;
  639. // Send message to peer
  640. WSABUF wsabuf;
  641. wsabuf.buf = (char FAR*) lpBuffer;
  642. wsabuf.len = dwCount;
  643. if (lpAddrIn)
  644. {
  645. // UDP
  646. res = WSASendTo( s, &wsabuf, 1, &dwBytesWritten, 0, lpAddrIn, sizeof(SOCKADDR_STORAGE),
  647. lpOverlapped, lpCompletionRoutine);
  648. }
  649. else // TCP
  650. res = WSASend( s, &wsabuf, 1, &dwBytesWritten, 0, lpOverlapped, lpCompletionRoutine);
  651. if ( res == SOCKET_ERROR )
  652. {
  653. res = WSAGetLastError();
  654. if ( res != WSA_IO_PENDING )
  655. {
  656. dwBytesWritten = (DWORD)-1L;
  657. SetLastError( res );
  658. }
  659. }
  660. return dwBytesWritten;
  661. }
  662. #endif
  663. #ifdef WIN32
  664. ///////////////////////////////////////////////////////////////////////////////
  665. // IOControl
  666. bool CSocketHandle::IOControl(DWORD dwIoCode, LPBYTE lpInBuffer, DWORD cbInBuffer,
  667. LPBYTE lpOutBuffer, DWORD cbOutBuffer,
  668. LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
  669. LPWSACOMPLETIONROUTINE lpCompletionRoutine)
  670. {
  671. _ASSERTE( IsOpen() );
  672. // validate params
  673. if ( !IsOpen() ) {
  674. SetLastError(ERROR_INVALID_HANDLE);
  675. return false;
  676. }
  677. int res;
  678. SOCKET s = GetSocket();
  679. res = WSAIoctl(s, dwIoCode, lpInBuffer, cbInBuffer, lpOutBuffer, cbOutBuffer,
  680. lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
  681. if ( res == SOCKET_ERROR )
  682. {
  683. SetLastError( WSAGetLastError() );
  684. }
  685. return ( res != SOCKET_ERROR );
  686. }
  687. ///////////////////////////////////////////////////////////////////////////////
  688. // GetTransferOverlappedResult
  689. bool CSocketHandle::GetTransferOverlappedResult(LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer,
  690. bool bWait /*= true*/, LPDWORD lpdwFlags /*= NULL*/)
  691. {
  692. _ASSERTE( IsOpen() );
  693. _ASSERTE( NULL != lpOverlapped );
  694. // validate params
  695. if (!IsOpen() || NULL == lpOverlapped) {
  696. SetLastError(ERROR_INVALID_HANDLE);
  697. return false;
  698. }
  699. SOCKET s = GetSocket();
  700. DWORD dwFlags = 0;
  701. if ( lpdwFlags == NULL )
  702. lpdwFlags = &dwFlags;
  703. BOOL bRet = WSAGetOverlappedResult( s, lpOverlapped, lpcbTransfer, bWait, lpdwFlags );
  704. if ( !bRet )
  705. {
  706. SetLastError( WSAGetLastError() );
  707. }
  708. return (bRet != FALSE);
  709. }
  710. #endif
  711. ///////////////////////////////////////////////////////////////////////////////
  712. // Utility functions
  713. ///////////////////////////////////////////////////////////////////////////////
  714. // InitLibrary
  715. bool CSocketHandle::InitLibrary(WORD wVersion)
  716. {
  717. #ifdef WIN32
  718. WSADATA WSAData = { 0 };
  719. return ( 0 == WSAStartup( wVersion, &WSAData ) );
  720. #else
  721. return true;
  722. #endif
  723. }
  724. ///////////////////////////////////////////////////////////////////////////////
  725. // ReleaseLibrary
  726. bool CSocketHandle::ReleaseLibrary()
  727. {
  728. #ifdef WIN32
  729. return ( 0 == WSACleanup() );
  730. #else
  731. return true;
  732. #endif
  733. }
  734. ///////////////////////////////////////////////////////////////////////////////
  735. // WaitForConnection
  736. SOCKET CSocketHandle::WaitForConnection(SOCKET sock)
  737. {
  738. return accept(sock, 0, 0);
  739. }
  740. ///////////////////////////////////////////////////////////////////////////////
  741. // ShutdownConnection
  742. bool CSocketHandle::ShutdownConnection(SOCKET sock)
  743. {
  744. shutdown(sock, SD_BOTH);
  745. return ( 0 == closesocket( sock ));
  746. }
  747. static unsigned char chMinClassA_IP [] = { 1, 0, 0, 0 } ;
  748. static unsigned char chMinClassD_IP [] = { 224, 0, 0, 0 } ;
  749. static unsigned char chMaxClassD_IP [] = { 239, 255, 255, 255 } ;
  750. ///////////////////////////////////////////////////////////////////////////////
  751. // IsUnicastIP
  752. bool CSocketHandle::IsUnicastIP( ULONG ulAddr )
  753. {
  754. return (((unsigned char *) & ulAddr) [0] >= chMinClassA_IP [0] &&
  755. ((unsigned char *) & ulAddr) [0] < chMinClassD_IP [0]) ;
  756. }
  757. ///////////////////////////////////////////////////////////////////////////////
  758. // IsMulticastIP
  759. bool CSocketHandle::IsMulticastIP( ULONG ulAddr )
  760. {
  761. return (((unsigned char *) & ulAddr) [0] >= chMinClassD_IP [0] &&
  762. ((unsigned char *) & ulAddr) [0] <= chMaxClassD_IP [0]) ;
  763. }
  764. ///////////////////////////////////////////////////////////////////////////////
  765. // FormatIP
  766. bool CSocketHandle::FormatIP(LPTSTR pszIPAddr, UINT nSize, ULONG ulAddr, bool bFmtHost)
  767. {
  768. if ( pszIPAddr && nSize > 8)
  769. {
  770. if ( bFmtHost )
  771. ulAddr = htonl( ulAddr );
  772. // Create Address string
  773. return (SUCCEEDED(StringCchPrintf(pszIPAddr, nSize, TEXT("%u.%u.%u.%u"),
  774. (UINT)(((PBYTE) &ulAddr)[0]),
  775. (UINT)(((PBYTE) &ulAddr)[1]),
  776. (UINT)(((PBYTE) &ulAddr)[2]),
  777. (UINT)(((PBYTE) &ulAddr)[3]))));
  778. }
  779. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  780. return false;
  781. }
  782. ///////////////////////////////////////////////////////////////////////////////
  783. // FormatIP
  784. bool CSocketHandle::FormatIP(LPTSTR pszIPAddr, UINT nSize, const SockAddrIn& addrIn)
  785. {
  786. if ( pszIPAddr && nSize > 8)
  787. {
  788. const void* addr;
  789. char szIPAddr[MAX_PATH] = { 0 };
  790. if (addrIn.ss_family == AF_INET) {
  791. addr = &((const sockaddr_in*)&addrIn)->sin_addr;
  792. } else {
  793. addr = &((const sockaddr_in6*)&addrIn)->sin6_addr;
  794. }
  795. if (inet_ntop(addrIn.ss_family, (PVOID)addr, szIPAddr, MAX_PATH) != NULL)
  796. {
  797. #ifdef _UNICODE
  798. return (0 != MultiByteToWideChar(CP_UTF8, 0, szIPAddr, -1, pszIPAddr, nSize ));
  799. #else
  800. ::StringCbCopyA(pszIPAddr, nSize, szIPAddr);
  801. return true;
  802. #endif
  803. }
  804. }
  805. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  806. return false;
  807. }
  808. ///////////////////////////////////////////////////////////////////////////////
  809. // GetPortNumber
  810. USHORT CSocketHandle::GetPortNumber( LPCTSTR pszServiceName )
  811. {
  812. LPSERVENT lpservent;
  813. USHORT nPort = 0;
  814. if ( _istdigit( pszServiceName[0] ) ) {
  815. nPort = (USHORT) _ttoi( pszServiceName );
  816. }
  817. else {
  818. #ifdef _UNICODE
  819. char pstrService[HOSTNAME_SIZE] = { 0 };
  820. WideCharToMultiByte(CP_UTF8, 0, pszServiceName, -1, pstrService, sizeof(pstrService), NULL, NULL );
  821. #else
  822. LPCTSTR pstrService = pszServiceName;
  823. #endif
  824. // Convert network byte order to host byte order
  825. if ( (lpservent = getservbyname( pstrService, NULL )) != NULL )
  826. nPort = ntohs( lpservent->s_port );
  827. }
  828. return nPort;
  829. }
  830. ///////////////////////////////////////////////////////////////////////////////
  831. // GetIPAddress
  832. ULONG CSocketHandle::GetIPAddress( LPCTSTR pszHostName )
  833. {
  834. LPHOSTENT lphostent;
  835. ULONG uAddr = INADDR_NONE;
  836. TCHAR szLocal[HOSTNAME_SIZE] = { 0 };
  837. // if no name specified, get local
  838. if ( NULL == pszHostName || !pszHostName[0])
  839. {
  840. GetLocalName(szLocal, HOSTNAME_SIZE);
  841. pszHostName = szLocal;
  842. }
  843. #ifdef _UNICODE
  844. char pstrHost[HOSTNAME_SIZE] = { 0 };
  845. WideCharToMultiByte(CP_UTF8, 0, pszHostName, -1, pstrHost, sizeof(pstrHost), NULL, NULL );
  846. #else
  847. LPCTSTR pstrHost = pszHostName;
  848. #endif
  849. // Check for an Internet Protocol dotted address string
  850. uAddr = inet_addr( pstrHost );
  851. if ( (INADDR_NONE == uAddr) && (strcmp( pstrHost, "255.255.255.255" )) )
  852. {
  853. // It's not an address, then try to resolve it as a hostname
  854. if ( (lphostent = gethostbyname( pstrHost )) != NULL )
  855. uAddr = *((ULONG *) lphostent->h_addr_list[0]);
  856. }
  857. return ntohl( uAddr );
  858. }
  859. ///////////////////////////////////////////////////////////////////////////////
  860. // GetLocalName
  861. bool CSocketHandle::GetLocalName(LPTSTR pszName, UINT nSize)
  862. {
  863. if (pszName != NULL && nSize > 0)
  864. {
  865. char szHost[HOSTNAME_SIZE] = { 0 };
  866. // get host name, if fail, SetLastError is set
  867. if (SOCKET_ERROR != gethostname(szHost, sizeof(szHost)))
  868. {
  869. struct hostent* hp;
  870. hp = gethostbyname(szHost);
  871. if (hp != NULL) {
  872. ::StringCbCopyA(szHost, HOSTNAME_SIZE, hp->h_name);
  873. }
  874. // check if user provide enough buffer
  875. size_t cbLength = 0;
  876. ::StringCbLengthA(szHost, HOSTNAME_SIZE, &cbLength);
  877. if ( cbLength > nSize )
  878. {
  879. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  880. return false;
  881. }
  882. // Unicode conversion
  883. #ifdef _UNICODE
  884. return (0 != MultiByteToWideChar(CP_UTF8, 0, szHost, -1, pszName, nSize ));
  885. #else
  886. ::StringCbCopyA(pszName, nSize, szHost);
  887. return true;
  888. #endif
  889. }
  890. else
  891. SetLastError( WSAGetLastError() );
  892. }
  893. else
  894. SetLastError(ERROR_INVALID_PARAMETER);
  895. return false;
  896. }
  897. ///////////////////////////////////////////////////////////////////////////////
  898. // GetLocalAddress
  899. bool CSocketHandle::GetLocalAddress(LPTSTR pszAddress, UINT nSize, int nFamily /*= AF_INET*/)
  900. {
  901. if (pszAddress != NULL && nSize > 0)
  902. {
  903. TCHAR szHost[HOSTNAME_SIZE] = { 0 };
  904. // Get computer local address
  905. // get host name, if fail, SetLastError is set
  906. if (GetLocalName(szHost, HOSTNAME_SIZE))
  907. {
  908. char szAddress[MAX_PATH] = { 0 };
  909. #ifdef _UNICODE
  910. char pstrHost[HOSTNAME_SIZE] = { 0 };
  911. WideCharToMultiByte(CP_UTF8, 0, szHost, -1, pstrHost, sizeof(pstrHost), NULL, NULL );
  912. #else
  913. LPCTSTR pstrHost = szHost;
  914. #endif
  915. // get address info
  916. sockaddr_storage addr_store = { 0 };
  917. addr_store.ss_family = static_cast<short>(nFamily);
  918. inet_pton(nFamily, pstrHost, &addr_store);
  919. const void* addr;
  920. if (addr_store.ss_family == AF_INET) {
  921. addr = &((const sockaddr_in*)&addr_store)->sin_addr;
  922. } else {
  923. addr = &((const sockaddr_in6*)&addr_store)->sin6_addr;
  924. }
  925. if (inet_ntop(addr_store.ss_family, (PVOID)addr, szAddress, MAX_PATH) != NULL)
  926. {
  927. // Unicode conversion
  928. #ifdef _UNICODE
  929. return (0 != MultiByteToWideChar(CP_UTF8, 0, szAddress, -1, pszAddress, nSize ));
  930. #else
  931. ::StringCbCopyA(pszAddress, nSize, szAddress);
  932. return true;
  933. #endif
  934. }
  935. else
  936. SetLastError( WSAGetLastError() );
  937. }
  938. }
  939. else
  940. SetLastError(ERROR_INVALID_PARAMETER);
  941. return false;
  942. }
  943. ///////////////////////////////////////////////////////////////////////////////
  944. // GetAddressInfo
  945. bool CSocketHandle::GetAddressInfo(LPCTSTR pszHostName, LPCTSTR pszServiceName,
  946. int nFamily, SockAddrIn& sockAddr)
  947. {
  948. const TCHAR szZERO[] = TEXT("0");
  949. ADDRINFO aiHints;
  950. ADDRINFO *aiList = NULL;
  951. memset(&aiHints, 0, sizeof(aiHints));
  952. //aiHints.ai_flags = AI_ADDRCONFIG;
  953. aiHints.ai_family = static_cast<short>(nFamily);
  954. TCHAR szLocal[HOSTNAME_SIZE] = { 0 };
  955. // if no name specified, get local
  956. if ( NULL == pszHostName || !pszHostName[0])
  957. {
  958. GetLocalName(szLocal, HOSTNAME_SIZE);
  959. pszHostName = szLocal;
  960. }
  961. if ( NULL == pszServiceName || !pszServiceName[0])
  962. {
  963. pszServiceName = szZERO;
  964. }
  965. #ifdef _UNICODE
  966. char pstrHost[HOSTNAME_SIZE] = { 0 };
  967. WideCharToMultiByte(CP_UTF8, 0, pszHostName, -1, pstrHost, sizeof(pstrHost), NULL, NULL );
  968. char pstrService[HOSTNAME_SIZE] = { 0 };
  969. WideCharToMultiByte(CP_UTF8, 0, pszServiceName, -1, pstrService, sizeof(pstrService), NULL, NULL );
  970. #else
  971. LPCTSTR pstrHost = pszHostName;
  972. LPCTSTR pstrService = pszServiceName;
  973. #endif
  974. if ( SOCKET_ERROR != getaddrinfo(pstrHost, pstrService, &aiHints, &aiList) && ( aiList != 0 ))
  975. {
  976. ADDRINFO ai = { 0 };
  977. ai.ai_addr = sockAddr;
  978. memcpy(ai.ai_addr, aiList->ai_addr, aiList->ai_addrlen);
  979. freeaddrinfo( aiList );
  980. return true;
  981. }
  982. SetLastError( WSAGetLastError() );
  983. return false;
  984. }
  985. ///////////////////////////////////////////////////////////////////////////////
  986. // Globals
  987. ///////////////////////////////////////////////////////////////////////////////
  988. #if !defined(PLATFORM_HAS_INETFUNC)
  989. ///////////////////////////////////////////////////////////////////////////////
  990. // inet_ntop
  991. const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
  992. {
  993. if ( dst != NULL)
  994. {
  995. dst[0] = 0;
  996. if (af == AF_INET)
  997. {
  998. sockaddr_in in;
  999. memset(&in, 0, sizeof(in));
  1000. in.sin_family = AF_INET;
  1001. memcpy(&in.sin_addr, src, sizeof(in_addr));
  1002. getnameinfo((sockaddr *)&in, sizeof(sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
  1003. return dst;
  1004. }
  1005. else if (af == AF_INET6)
  1006. {
  1007. sockaddr_in6 in;
  1008. memset(&in, 0, sizeof(in));
  1009. in.sin6_family = AF_INET6;
  1010. memcpy(&in.sin6_addr, src, sizeof(in6_addr));
  1011. getnameinfo((sockaddr *)&in, sizeof(sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
  1012. return dst;
  1013. }
  1014. }
  1015. WSASetLastError(WSA_INVALID_PARAMETER);
  1016. return dst;
  1017. }
  1018. ///////////////////////////////////////////////////////////////////////////////
  1019. // inet_pton
  1020. int inet_pton(int af, const char *src, void *dst)
  1021. {
  1022. int result = SOCKET_ERROR;
  1023. addrinfo aiHints, *aiList = NULL;
  1024. memset(&aiHints, 0, sizeof(aiHints));
  1025. aiHints.ai_family = af;
  1026. if ( SOCKET_ERROR != getaddrinfo(src, NULL, &aiHints, &aiList) && (aiList != NULL))
  1027. {
  1028. memcpy(dst, aiList->ai_addr, aiList->ai_addrlen);
  1029. freeaddrinfo(aiList);
  1030. result = 0;
  1031. }
  1032. return result;
  1033. }
  1034. #endif