SocketHandle.cpp 34 KB

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