SocketHandle.cpp 35 KB

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