SocketHandle.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  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. #include "Wspiapi.h"
  32. #include "Ws2tcpip.h"
  33. #ifndef BUFFER_SIZE
  34. #define BUFFER_SIZE 64*1024
  35. #endif
  36. #ifndef SOCKHANDLE_TTL
  37. #define SOCKHANDLE_TTL 5
  38. #endif
  39. #ifndef SOCKHANDLE_HOPS
  40. #define SOCKHANDLE_HOPS 10
  41. #endif
  42. #define HOSTNAME_SIZE MAX_PATH
  43. #define STRING_LENGTH 40
  44. #if !defined(PLATFORM_HAS_INETFUNC)
  45. const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
  46. int inet_pton(int af, const char *src, void *dst);
  47. #endif
  48. #ifdef WIN32
  49. #ifndef UNDER_CE
  50. #pragma comment(lib, "ws2_32.lib")
  51. #else
  52. #pragma comment(lib, "Ws2.lib")
  53. #endif
  54. #endif
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // SockAddrIn Struct
  57. SockAddrIn SockAddrIn::NULLAddr;
  58. ///////////////////////////////////////////////////////////////////////////////
  59. // Constructs
  60. SockAddrIn::SockAddrIn()
  61. {
  62. Clear();
  63. }
  64. SockAddrIn::SockAddrIn(const SockAddrIn& sin)
  65. {
  66. Copy( sin );
  67. }
  68. SockAddrIn::~SockAddrIn()
  69. {
  70. }
  71. ///////////////////////////////////////////////////////////////////////////////
  72. // Clear
  73. void SockAddrIn::Clear()
  74. {
  75. memset(this, 0, sizeof(sockaddr_storage));
  76. }
  77. ///////////////////////////////////////////////////////////////////////////////
  78. // Copy
  79. SockAddrIn& SockAddrIn::Copy(const SockAddrIn& sin)
  80. {
  81. ss_family = sin.ss_family;
  82. memcpy(this, &sin, Size());
  83. return *this;
  84. }
  85. ///////////////////////////////////////////////////////////////////////////////
  86. // IsEqual
  87. bool SockAddrIn::IsEqual(const SockAddrIn& sin) const
  88. {
  89. // Is it Equal? - ignore 'sin_zero'
  90. if ( ss_family == AF_INET ) {
  91. return (memcmp(this, &sin, Size()-8) == 0);
  92. }
  93. return (memcmp(this, &sin, Size()) == 0);
  94. }
  95. ///////////////////////////////////////////////////////////////////////////////
  96. // CreateFrom
  97. bool SockAddrIn::CreateFrom(LPCTSTR pszAddr, LPCTSTR pszService, int nFamily /*=AF_INET*/)
  98. {
  99. Clear();
  100. CSocketHandle::GetAddressInfo(pszAddr, pszService, nFamily, *this);
  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. {
  431. LOG4C((LOG_NOTICE, "Á¬½Óʧ°Ü£¬Ô­Òò£ºCSocketHandle : IsOpen() "));
  432. SetLastError(ERROR_ACCESS_DENIED);
  433. return false;
  434. }
  435. // Create a Socket that is bound to a specific service provider
  436. // nFamily: (AF_INET, AF_INET6)
  437. // nType: (SOCK_STREAM, SOCK_DGRAM)
  438. #ifdef SOCKHANDLE_USE_OVERLAPPED
  439. SOCKET sock = WSASocket(nFamily, nType, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
  440. #else
  441. SOCKET sock = socket(nFamily, nType, IPPROTO_IP);
  442. #endif
  443. if (INVALID_SOCKET != sock)
  444. {
  445. // Associate a local address with the socket but let provider assign a port number
  446. SockAddrIn sockAddr;
  447. if (false == sockAddr.CreateFrom(pszHostName, TEXT("0"), nFamily))
  448. {
  449. SetLastError( WSAGetLastError() );
  450. closesocket( sock );
  451. return false;
  452. }
  453. if ( SOCKET_ERROR == bind(sock, sockAddr, (int)sockAddr.Size()))
  454. {
  455. SetLastError( WSAGetLastError() );
  456. closesocket( sock );
  457. return false;
  458. }
  459. #ifdef SOCKHANDLE_CONFIGBUF
  460. if (nType == SOCK_DGRAM)
  461. {
  462. // configure buffer size
  463. socklen_t rcvbuf = BUFFER_SIZE;
  464. if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbuf, sizeof( int ) ) )
  465. {
  466. SetLastError( WSAGetLastError() );
  467. closesocket( sock );
  468. return false;
  469. }
  470. }
  471. #endif
  472. // Now get destination address & port
  473. sockAddr.CreateFrom( pszRemote, pszServiceName, nFamily );
  474. // try to connect - if fail, server not ready
  475. if (SOCKET_ERROR == connect( sock, sockAddr, (int)sockAddr.Size()))
  476. {
  477. //int i = WSAGetLastError();
  478. SetLastError( WSAGetLastError() );
  479. closesocket( sock );
  480. return false;
  481. }
  482. // Success, now we may save this socket
  483. m_hSocket = sock;
  484. }
  485. return (INVALID_SOCKET != sock);
  486. }
  487. ///////////////////////////////////////////////////////////////////////////////
  488. // Read
  489. DWORD CSocketHandle::Read(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn,
  490. DWORD dwTimeout)
  491. {
  492. _ASSERTE( IsOpen() );
  493. _ASSERTE( lpBuffer != NULL );
  494. if (!IsOpen() || lpBuffer == NULL || dwSize < 1L)
  495. return (DWORD)-1L;
  496. fd_set fdRead = { 0 };
  497. TIMEVAL stTime;
  498. TIMEVAL *pstTime = NULL;
  499. if ( INFINITE != dwTimeout ) {
  500. stTime.tv_sec = dwTimeout/1000;
  501. stTime.tv_usec = (dwTimeout%1000)*1000;
  502. pstTime = &stTime;
  503. }
  504. SOCKET s = GetSocket();
  505. // Set Descriptor
  506. FD_SET( s, &fdRead );
  507. // Select function set read timeout
  508. DWORD dwBytesRead = 0L;
  509. int res = 1;
  510. if ( pstTime != NULL )
  511. res = select((int)s, &fdRead, NULL, NULL, pstTime );
  512. if ( res > 0)
  513. {
  514. if (lpAddrIn)
  515. {
  516. // UDP
  517. socklen_t fromlen = sizeof(SOCKADDR_STORAGE);
  518. res = recvfrom(s, reinterpret_cast<LPSTR>(lpBuffer), dwSize, 0, lpAddrIn, &fromlen);
  519. }
  520. else
  521. {
  522. // TCP
  523. res = recv(s, reinterpret_cast<LPSTR>(lpBuffer), dwSize, 0);
  524. }
  525. if ( res == 0 ) {
  526. WSASetLastError(WSAECONNRESET);
  527. res = SOCKET_ERROR;
  528. }
  529. }
  530. if ( res == SOCKET_ERROR )
  531. {
  532. SetLastError( WSAGetLastError() );
  533. }
  534. dwBytesRead = (DWORD)((res >= 0)?(res) : (-1));
  535. return dwBytesRead;
  536. }
  537. #ifdef WIN32
  538. ///////////////////////////////////////////////////////////////////////////////
  539. // ReadEx
  540. DWORD CSocketHandle::ReadEx(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn,
  541. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine)
  542. {
  543. _ASSERTE( IsOpen() );
  544. _ASSERTE( lpBuffer != NULL );
  545. if (!IsOpen() || lpBuffer == NULL || dwSize < 1L)
  546. return (DWORD)-1L;
  547. SOCKET s = GetSocket();
  548. // Send message to peer
  549. WSABUF wsabuf;
  550. wsabuf.buf = (char FAR*)lpBuffer;
  551. wsabuf.len = dwSize;
  552. // Select function set read timeout
  553. DWORD dwBytesRead = 0L;
  554. DWORD dwFlags = 0L;
  555. int res = 0;
  556. if (lpAddrIn)
  557. {
  558. // UDP
  559. socklen_t fromlen = sizeof(SOCKADDR_STORAGE);
  560. res = WSARecvFrom( s, &wsabuf, 1, &dwBytesRead, &dwFlags, lpAddrIn, &fromlen, lpOverlapped, lpCompletionRoutine);
  561. }
  562. else
  563. {
  564. // TCP
  565. res = WSARecv( s, &wsabuf, 1, &dwBytesRead, &dwFlags, lpOverlapped, lpCompletionRoutine);
  566. }
  567. if ( res == SOCKET_ERROR )
  568. {
  569. res = WSAGetLastError();
  570. if ( res != WSA_IO_PENDING )
  571. {
  572. dwBytesRead = (DWORD)-1L;
  573. SetLastError( res );
  574. }
  575. }
  576. return dwBytesRead;
  577. }
  578. #endif
  579. ///////////////////////////////////////////////////////////////////////////////
  580. // Write
  581. DWORD CSocketHandle::Write(const LPBYTE lpBuffer, DWORD dwCount,
  582. const LPSOCKADDR lpAddrIn, DWORD dwTimeout)
  583. {
  584. _ASSERTE( IsOpen() );
  585. _ASSERTE( NULL != lpBuffer );
  586. // validate params
  587. if (!IsOpen() || NULL == lpBuffer)
  588. return (DWORD)-1L;
  589. fd_set fdWrite = { 0 };
  590. TIMEVAL stTime;
  591. TIMEVAL *pstTime = NULL;
  592. if ( INFINITE != dwTimeout ) {
  593. stTime.tv_sec = dwTimeout/1000;
  594. stTime.tv_usec = (dwTimeout%1000)*1000;
  595. pstTime = &stTime;
  596. }
  597. SOCKET s = GetSocket();
  598. // Set Descriptor
  599. FD_SET( s, &fdWrite );
  600. // Select function set write timeout
  601. DWORD dwBytesWritten = 0L;
  602. int res = 1;
  603. if ( pstTime != NULL )
  604. res = select((int)s, NULL, &fdWrite, NULL, pstTime );
  605. if ( res > 0)
  606. {
  607. // Send message to peer
  608. if (lpAddrIn)
  609. {
  610. // UDP
  611. res = sendto( s, reinterpret_cast<LPCSTR>(lpBuffer), dwCount, 0, lpAddrIn, sizeof(SOCKADDR_STORAGE));
  612. }
  613. else
  614. {
  615. // TCP
  616. res = send( s, reinterpret_cast<LPCSTR>(lpBuffer), dwCount, 0);
  617. }
  618. }
  619. if ( res == SOCKET_ERROR )
  620. {
  621. SetLastError( WSAGetLastError() );
  622. }
  623. dwBytesWritten = (DWORD)((res >= 0)?(res) : (-1));
  624. return dwBytesWritten;
  625. }
  626. #ifdef WIN32
  627. ///////////////////////////////////////////////////////////////////////////////
  628. // WriteEx
  629. DWORD CSocketHandle::WriteEx(const LPBYTE lpBuffer, DWORD dwCount,
  630. const LPSOCKADDR lpAddrIn,
  631. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine)
  632. {
  633. _ASSERTE( IsOpen() );
  634. _ASSERTE( NULL != lpBuffer );
  635. // validate params
  636. if (!IsOpen() || NULL == lpBuffer)
  637. return (DWORD)-1L;
  638. SOCKET s = GetSocket();
  639. // Select function set write timeout
  640. DWORD dwBytesWritten = 0L;
  641. int res = 0;
  642. // Send message to peer
  643. WSABUF wsabuf;
  644. wsabuf.buf = (char FAR*) lpBuffer;
  645. wsabuf.len = dwCount;
  646. if (lpAddrIn)
  647. {
  648. // UDP
  649. res = WSASendTo( s, &wsabuf, 1, &dwBytesWritten, 0, lpAddrIn, sizeof(SOCKADDR_STORAGE),
  650. lpOverlapped, lpCompletionRoutine);
  651. }
  652. else // TCP
  653. res = WSASend( s, &wsabuf, 1, &dwBytesWritten, 0, lpOverlapped, lpCompletionRoutine);
  654. if ( res == SOCKET_ERROR )
  655. {
  656. res = WSAGetLastError();
  657. if ( res != WSA_IO_PENDING )
  658. {
  659. dwBytesWritten = (DWORD)-1L;
  660. SetLastError( res );
  661. }
  662. }
  663. return dwBytesWritten;
  664. }
  665. #endif
  666. #ifdef WIN32
  667. ///////////////////////////////////////////////////////////////////////////////
  668. // IOControl
  669. bool CSocketHandle::IOControl(DWORD dwIoCode, LPBYTE lpInBuffer, DWORD cbInBuffer,
  670. LPBYTE lpOutBuffer, DWORD cbOutBuffer,
  671. LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
  672. LPWSACOMPLETIONROUTINE lpCompletionRoutine)
  673. {
  674. _ASSERTE( IsOpen() );
  675. // validate params
  676. if ( !IsOpen() ) {
  677. SetLastError(ERROR_INVALID_HANDLE);
  678. return false;
  679. }
  680. int res;
  681. SOCKET s = GetSocket();
  682. res = WSAIoctl(s, dwIoCode, lpInBuffer, cbInBuffer, lpOutBuffer, cbOutBuffer,
  683. lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
  684. if ( res == SOCKET_ERROR )
  685. {
  686. SetLastError( WSAGetLastError() );
  687. }
  688. return ( res != SOCKET_ERROR );
  689. }
  690. ///////////////////////////////////////////////////////////////////////////////
  691. // GetTransferOverlappedResult
  692. bool CSocketHandle::GetTransferOverlappedResult(LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer,
  693. bool bWait /*= true*/, LPDWORD lpdwFlags /*= NULL*/)
  694. {
  695. _ASSERTE( IsOpen() );
  696. _ASSERTE( NULL != lpOverlapped );
  697. // validate params
  698. if (!IsOpen() || NULL == lpOverlapped) {
  699. SetLastError(ERROR_INVALID_HANDLE);
  700. return false;
  701. }
  702. SOCKET s = GetSocket();
  703. DWORD dwFlags = 0;
  704. if ( lpdwFlags == NULL )
  705. lpdwFlags = &dwFlags;
  706. BOOL bRet = WSAGetOverlappedResult( s, lpOverlapped, lpcbTransfer, bWait, lpdwFlags );
  707. if ( !bRet )
  708. {
  709. SetLastError( WSAGetLastError() );
  710. }
  711. return (bRet != FALSE);
  712. }
  713. #endif
  714. ///////////////////////////////////////////////////////////////////////////////
  715. // Utility functions
  716. ///////////////////////////////////////////////////////////////////////////////
  717. // InitLibrary
  718. bool CSocketHandle::InitLibrary(WORD wVersion)
  719. {
  720. #ifdef WIN32
  721. WSADATA WSAData = { 0 };
  722. return ( 0 == WSAStartup( wVersion, &WSAData ) );
  723. #else
  724. return true;
  725. #endif
  726. }
  727. ///////////////////////////////////////////////////////////////////////////////
  728. // ReleaseLibrary
  729. bool CSocketHandle::ReleaseLibrary()
  730. {
  731. #ifdef WIN32
  732. return ( 0 == WSACleanup() );
  733. #else
  734. return true;
  735. #endif
  736. }
  737. ///////////////////////////////////////////////////////////////////////////////
  738. // WaitForConnection
  739. SOCKET CSocketHandle::WaitForConnection(SOCKET sock)
  740. {
  741. return accept(sock, 0, 0);
  742. }
  743. ///////////////////////////////////////////////////////////////////////////////
  744. // ShutdownConnection
  745. bool CSocketHandle::ShutdownConnection(SOCKET sock)
  746. {
  747. shutdown(sock, SD_BOTH);
  748. return ( 0 == closesocket( sock ));
  749. }
  750. static unsigned char chMinClassA_IP [] = { 1, 0, 0, 0 } ;
  751. static unsigned char chMinClassD_IP [] = { 224, 0, 0, 0 } ;
  752. static unsigned char chMaxClassD_IP [] = { 239, 255, 255, 255 } ;
  753. ///////////////////////////////////////////////////////////////////////////////
  754. // IsUnicastIP
  755. bool CSocketHandle::IsUnicastIP( ULONG ulAddr )
  756. {
  757. return (((unsigned char *) & ulAddr) [0] >= chMinClassA_IP [0] &&
  758. ((unsigned char *) & ulAddr) [0] < chMinClassD_IP [0]) ;
  759. }
  760. ///////////////////////////////////////////////////////////////////////////////
  761. // IsMulticastIP
  762. bool CSocketHandle::IsMulticastIP( ULONG ulAddr )
  763. {
  764. return (((unsigned char *) & ulAddr) [0] >= chMinClassD_IP [0] &&
  765. ((unsigned char *) & ulAddr) [0] <= chMaxClassD_IP [0]) ;
  766. }
  767. ///////////////////////////////////////////////////////////////////////////////
  768. // FormatIP
  769. bool CSocketHandle::FormatIP(LPTSTR pszIPAddr, UINT nSize, ULONG ulAddr, bool bFmtHost)
  770. {
  771. if ( pszIPAddr && nSize > 8)
  772. {
  773. if ( bFmtHost )
  774. ulAddr = htonl( ulAddr );
  775. // Create Address string
  776. return (SUCCEEDED(StringCchPrintf(pszIPAddr, nSize, TEXT("%u.%u.%u.%u"),
  777. (UINT)(((PBYTE) &ulAddr)[0]),
  778. (UINT)(((PBYTE) &ulAddr)[1]),
  779. (UINT)(((PBYTE) &ulAddr)[2]),
  780. (UINT)(((PBYTE) &ulAddr)[3]))));
  781. }
  782. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  783. return false;
  784. }
  785. ///////////////////////////////////////////////////////////////////////////////
  786. // FormatIP
  787. bool CSocketHandle::FormatIP(LPTSTR pszIPAddr, UINT nSize, const SockAddrIn& addrIn)
  788. {
  789. if ( pszIPAddr && nSize > 8)
  790. {
  791. const void* addr;
  792. char szIPAddr[MAX_PATH] = { 0 };
  793. if (addrIn.ss_family == AF_INET) {
  794. addr = &((const sockaddr_in*)&addrIn)->sin_addr;
  795. } else {
  796. addr = &((const sockaddr_in6*)&addrIn)->sin6_addr;
  797. }
  798. if (inet_ntop(addrIn.ss_family, (PVOID)addr, szIPAddr, MAX_PATH) != NULL)
  799. {
  800. #ifdef _UNICODE
  801. return (0 != MultiByteToWideChar(CP_UTF8, 0, szIPAddr, -1, pszIPAddr, nSize ));
  802. #else
  803. ::StringCbCopyA(pszIPAddr, nSize, szIPAddr);
  804. return true;
  805. #endif
  806. }
  807. }
  808. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  809. return false;
  810. }
  811. ///////////////////////////////////////////////////////////////////////////////
  812. // GetPortNumber
  813. USHORT CSocketHandle::GetPortNumber( LPCTSTR pszServiceName )
  814. {
  815. LPSERVENT lpservent;
  816. USHORT nPort = 0;
  817. if ( _istdigit( pszServiceName[0] ) ) {
  818. nPort = (USHORT) _ttoi( pszServiceName );
  819. }
  820. else {
  821. #ifdef _UNICODE
  822. char pstrService[HOSTNAME_SIZE] = { 0 };
  823. WideCharToMultiByte(CP_UTF8, 0, pszServiceName, -1, pstrService, sizeof(pstrService), NULL, NULL );
  824. #else
  825. LPCTSTR pstrService = pszServiceName;
  826. #endif
  827. // Convert network byte order to host byte order
  828. if ( (lpservent = getservbyname( pstrService, NULL )) != NULL )
  829. nPort = ntohs( lpservent->s_port );
  830. }
  831. return nPort;
  832. }
  833. ///////////////////////////////////////////////////////////////////////////////
  834. // GetIPAddress
  835. ULONG CSocketHandle::GetIPAddress( LPCTSTR pszHostName )
  836. {
  837. LPHOSTENT lphostent;
  838. ULONG uAddr = INADDR_NONE;
  839. TCHAR szLocal[HOSTNAME_SIZE] = { 0 };
  840. // if no name specified, get local
  841. if ( NULL == pszHostName || !pszHostName[0])
  842. {
  843. GetLocalName(szLocal, HOSTNAME_SIZE);
  844. pszHostName = szLocal;
  845. }
  846. #ifdef _UNICODE
  847. char pstrHost[HOSTNAME_SIZE] = { 0 };
  848. WideCharToMultiByte(CP_UTF8, 0, pszHostName, -1, pstrHost, sizeof(pstrHost), NULL, NULL );
  849. #else
  850. LPCTSTR pstrHost = pszHostName;
  851. #endif
  852. // Check for an Internet Protocol dotted address string
  853. uAddr = inet_addr( pstrHost );
  854. if ( (INADDR_NONE == uAddr) && (strcmp( pstrHost, "255.255.255.255" )) )
  855. {
  856. // It's not an address, then try to resolve it as a hostname
  857. if ( (lphostent = gethostbyname( pstrHost )) != NULL )
  858. uAddr = *((ULONG *) lphostent->h_addr_list[0]);
  859. }
  860. return ntohl( uAddr );
  861. }
  862. ///////////////////////////////////////////////////////////////////////////////
  863. // GetLocalName
  864. bool CSocketHandle::GetLocalName(LPTSTR pszName, UINT nSize)
  865. {
  866. if (pszName != NULL && nSize > 0)
  867. {
  868. char szHost[HOSTNAME_SIZE] = { 0 };
  869. // get host name, if fail, SetLastError is set
  870. if (SOCKET_ERROR != gethostname(szHost, sizeof(szHost)))
  871. {
  872. struct hostent* hp;
  873. hp = gethostbyname(szHost);
  874. if (hp != NULL) {
  875. ::StringCbCopyA(szHost, HOSTNAME_SIZE, hp->h_name);
  876. }
  877. // check if user provide enough buffer
  878. size_t cbLength = 0;
  879. ::StringCbLengthA(szHost, HOSTNAME_SIZE, &cbLength);
  880. if ( cbLength > nSize )
  881. {
  882. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  883. return false;
  884. }
  885. // Unicode conversion
  886. #ifdef _UNICODE
  887. return (0 != MultiByteToWideChar(CP_UTF8, 0, szHost, -1, pszName, nSize ));
  888. #else
  889. ::StringCbCopyA(pszName, nSize, szHost);
  890. return true;
  891. #endif
  892. }
  893. else
  894. SetLastError( WSAGetLastError() );
  895. }
  896. else
  897. SetLastError(ERROR_INVALID_PARAMETER);
  898. return false;
  899. }
  900. ///////////////////////////////////////////////////////////////////////////////
  901. // GetLocalAddress
  902. bool CSocketHandle::GetLocalAddress(LPTSTR pszAddress, UINT nSize, int nFamily /*= AF_INET*/)
  903. {
  904. if (pszAddress != NULL && nSize > 0)
  905. {
  906. TCHAR szHost[HOSTNAME_SIZE] = { 0 };
  907. // Get computer local address
  908. // get host name, if fail, SetLastError is set
  909. if (GetLocalName(szHost, HOSTNAME_SIZE))
  910. {
  911. char szAddress[MAX_PATH] = { 0 };
  912. #ifdef _UNICODE
  913. char pstrHost[HOSTNAME_SIZE] = { 0 };
  914. WideCharToMultiByte(CP_UTF8, 0, szHost, -1, pstrHost, sizeof(pstrHost), NULL, NULL );
  915. #else
  916. LPCTSTR pstrHost = szHost;
  917. #endif
  918. // get address info
  919. sockaddr_storage addr_store = { 0 };
  920. addr_store.ss_family = static_cast<short>(nFamily);
  921. inet_pton(nFamily, pstrHost, &addr_store);
  922. const void* addr;
  923. if (addr_store.ss_family == AF_INET) {
  924. addr = &((const sockaddr_in*)&addr_store)->sin_addr;
  925. } else {
  926. addr = &((const sockaddr_in6*)&addr_store)->sin6_addr;
  927. }
  928. if (inet_ntop(addr_store.ss_family, (PVOID)addr, szAddress, MAX_PATH) != NULL)
  929. {
  930. // Unicode conversion
  931. #ifdef _UNICODE
  932. return (0 != MultiByteToWideChar(CP_UTF8, 0, szAddress, -1, pszAddress, nSize ));
  933. #else
  934. ::StringCbCopyA(pszAddress, nSize, szAddress);
  935. return true;
  936. #endif
  937. }
  938. else
  939. SetLastError( WSAGetLastError() );
  940. }
  941. }
  942. else
  943. SetLastError(ERROR_INVALID_PARAMETER);
  944. return false;
  945. }
  946. ///////////////////////////////////////////////////////////////////////////////
  947. // GetAddressInfo
  948. bool CSocketHandle::GetAddressInfo(LPCTSTR pszHostName, LPCTSTR pszServiceName,
  949. int nFamily, SockAddrIn& sockAddr)
  950. {
  951. const TCHAR szZERO[] = TEXT("0");
  952. ADDRINFO aiHints;
  953. ADDRINFO *aiList = NULL;
  954. memset(&aiHints, 0, sizeof(aiHints));
  955. // aiHints.ai_flags = AI_ADDRCONFIG;
  956. aiHints.ai_family = static_cast<short>(nFamily);
  957. TCHAR szLocal[HOSTNAME_SIZE] = { 0 };
  958. // if no name specified, get local
  959. if ( NULL == pszHostName || !pszHostName[0])
  960. {
  961. GetLocalName(szLocal, HOSTNAME_SIZE);
  962. pszHostName = szLocal;
  963. }
  964. if ( NULL == pszServiceName || !pszServiceName[0])
  965. {
  966. pszServiceName = szZERO;
  967. }
  968. #ifdef _UNICODE
  969. char pstrHost[HOSTNAME_SIZE] = { 0 };
  970. WideCharToMultiByte(CP_UTF8, 0, pszHostName, -1, pstrHost, sizeof(pstrHost), NULL, NULL );
  971. char pstrService[HOSTNAME_SIZE] = { 0 };
  972. WideCharToMultiByte(CP_UTF8, 0, pszServiceName, -1, pstrService, sizeof(pstrService), NULL, NULL );
  973. #else
  974. LPCTSTR pstrHost = pszHostName;
  975. LPCTSTR pstrService = pszServiceName;
  976. #endif
  977. if ( SOCKET_ERROR != getaddrinfo(pstrHost, pstrService, &aiHints, &aiList) && ( aiList != 0 ))
  978. {
  979. ADDRINFO ai = { 0 };
  980. ai.ai_addr = sockAddr;
  981. memcpy(ai.ai_addr, aiList->ai_addr, aiList->ai_addrlen);
  982. freeaddrinfo( aiList );
  983. return true;
  984. }
  985. SetLastError( WSAGetLastError() );
  986. return false;
  987. }
  988. ///////////////////////////////////////////////////////////////////////////////
  989. // Globals
  990. ///////////////////////////////////////////////////////////////////////////////
  991. #if !defined(PLATFORM_HAS_INETFUNC)
  992. ///////////////////////////////////////////////////////////////////////////////
  993. // inet_ntop
  994. const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
  995. {
  996. if ( dst != NULL)
  997. {
  998. dst[0] = 0;
  999. if (af == AF_INET)
  1000. {
  1001. sockaddr_in in;
  1002. memset(&in, 0, sizeof(in));
  1003. in.sin_family = AF_INET;
  1004. memcpy(&in.sin_addr, src, sizeof(in_addr));
  1005. getnameinfo((sockaddr *)&in, sizeof(sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
  1006. return dst;
  1007. }
  1008. else if (af == AF_INET6)
  1009. {
  1010. sockaddr_in6 in;
  1011. memset(&in, 0, sizeof(in));
  1012. in.sin6_family = AF_INET6;
  1013. memcpy(&in.sin6_addr, src, sizeof(in6_addr));
  1014. getnameinfo((sockaddr *)&in, sizeof(sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
  1015. return dst;
  1016. }
  1017. }
  1018. WSASetLastError(WSA_INVALID_PARAMETER);
  1019. return dst;
  1020. }
  1021. ///////////////////////////////////////////////////////////////////////////////
  1022. // inet_pton
  1023. int inet_pton(int af, const char *src, void *dst)
  1024. {
  1025. int result = SOCKET_ERROR;
  1026. addrinfo aiHints, *aiList = NULL;
  1027. memset(&aiHints, 0, sizeof(aiHints));
  1028. aiHints.ai_family = af;
  1029. if ( SOCKET_ERROR != getaddrinfo(src, NULL, &aiHints, &aiList) && (aiList != NULL))
  1030. {
  1031. memcpy(dst, aiList->ai_addr, aiList->ai_addrlen);
  1032. freeaddrinfo(aiList);
  1033. result = 0;
  1034. }
  1035. return result;
  1036. }
  1037. #endif