SimpleSocket.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. /*---------------------------------------------------------------------------*/
  2. /* */
  3. /* CSimpleSocket.cpp - CSimpleSocket Implementation */
  4. /* */
  5. /* Author : Mark Carrier (mark@carrierlabs.com) */
  6. /* */
  7. /*---------------------------------------------------------------------------*/
  8. /* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * 3. The name of the author may not be used to endorse or promote products
  23. * derived from this software without specific prior written permission.
  24. *
  25. * 4. The name "CarrierLabs" must not be used to
  26. * endorse or promote products derived from this software without
  27. * prior written permission. For written permission, please contact
  28. * mark@carrierlabs.com.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
  31. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  33. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
  34. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  41. * OF THE POSSIBILITY OF SUCH DAMAGE.
  42. *----------------------------------------------------------------------------*/
  43. #include "SimpleSocket.h"
  44. CSimpleSocket::CSimpleSocket(CSocketType nType) :
  45. m_socket(INVALID_SOCKET),
  46. m_socketErrno(CSimpleSocket::SocketInvalidSocket),
  47. m_pBuffer(NULL), m_nBufferSize(0), m_nSocketDomain(AF_INET),
  48. m_nSocketType(SocketTypeInvalid), m_nBytesReceived(-1),
  49. m_nBytesSent(-1), m_nFlags(0),
  50. m_bIsBlocking(true), m_bIsMulticast(false)
  51. {
  52. SetConnectTimeout(1, 0);
  53. memset(&m_stRecvTimeout, 0, sizeof(struct timeval));
  54. memset(&m_stSendTimeout, 0, sizeof(struct timeval));
  55. memset(&m_stLinger, 0, sizeof(struct linger));
  56. switch(nType)
  57. {
  58. //----------------------------------------------------------------------
  59. // Declare socket type stream - TCP
  60. //----------------------------------------------------------------------
  61. case CSimpleSocket::SocketTypeTcp:
  62. {
  63. m_nSocketDomain = AF_INET;
  64. m_nSocketType = CSimpleSocket::SocketTypeTcp;
  65. break;
  66. }
  67. case CSimpleSocket::SocketTypeTcp6:
  68. {
  69. m_nSocketDomain = AF_INET6;
  70. m_nSocketType = CSimpleSocket::SocketTypeTcp6;
  71. break;
  72. }
  73. //----------------------------------------------------------------------
  74. // Declare socket type datagram - UDP
  75. //----------------------------------------------------------------------
  76. case CSimpleSocket::SocketTypeUdp:
  77. {
  78. m_nSocketDomain = AF_INET;
  79. m_nSocketType = CSimpleSocket::SocketTypeUdp;
  80. break;
  81. }
  82. case CSimpleSocket::SocketTypeUdp6:
  83. {
  84. m_nSocketDomain = AF_INET6;
  85. m_nSocketType = CSimpleSocket::SocketTypeUdp6;
  86. break;
  87. }
  88. //----------------------------------------------------------------------
  89. // Declare socket type raw Ethernet - Ethernet
  90. //----------------------------------------------------------------------
  91. case CSimpleSocket::SocketTypeRaw:
  92. {
  93. #if defined(_LINUX) && !defined(_DARWIN)
  94. m_nSocketDomain = AF_PACKET;
  95. m_nSocketType = CSimpleSocket::SocketTypeRaw;
  96. #endif
  97. #ifdef _WIN32
  98. m_nSocketType = CSimpleSocket::SocketTypeInvalid;
  99. #endif
  100. break;
  101. }
  102. default:
  103. m_nSocketType = CSimpleSocket::SocketTypeInvalid;
  104. break;
  105. }
  106. }
  107. CSimpleSocket::CSimpleSocket(CSimpleSocket &socket)
  108. {
  109. m_pBuffer = new uint8[socket.m_nBufferSize];
  110. m_nBufferSize = socket.m_nBufferSize;
  111. memcpy(m_pBuffer, socket.m_pBuffer, socket.m_nBufferSize);
  112. }
  113. CSimpleSocket *CSimpleSocket::operator=(CSimpleSocket &socket)
  114. {
  115. if (m_nBufferSize != socket.m_nBufferSize)
  116. {
  117. delete m_pBuffer;
  118. m_pBuffer = new uint8[socket.m_nBufferSize];
  119. m_nBufferSize = socket.m_nBufferSize;
  120. memcpy(m_pBuffer, socket.m_pBuffer, socket.m_nBufferSize);
  121. }
  122. return this;
  123. }
  124. //------------------------------------------------------------------------------
  125. //
  126. // Initialize() - Initialize socket class
  127. //
  128. //------------------------------------------------------------------------------
  129. bool CSimpleSocket::Initialize()
  130. {
  131. errno = CSimpleSocket::SocketSuccess;
  132. #ifdef WIN32
  133. //-------------------------------------------------------------------------
  134. // Data structure containing general Windows Sockets Info
  135. //-------------------------------------------------------------------------
  136. memset(&m_hWSAData, 0, sizeof(m_hWSAData));
  137. WSAStartup(MAKEWORD(2, 0), &m_hWSAData);
  138. #endif
  139. //-------------------------------------------------------------------------
  140. // Create the basic Socket Handle
  141. //-------------------------------------------------------------------------
  142. m_timer.Initialize();
  143. m_timer.SetStartTime();
  144. m_socket = socket(m_nSocketDomain, m_nSocketType, 0);
  145. m_timer.SetEndTime();
  146. TranslateSocketError();
  147. return (IsSocketValid());
  148. }
  149. //------------------------------------------------------------------------------
  150. //
  151. // BindInterface()
  152. //
  153. //------------------------------------------------------------------------------
  154. bool CSimpleSocket::BindInterface(const char *pInterface)
  155. {
  156. bool bRetVal = false;
  157. struct in_addr stInterfaceAddr;
  158. if (GetMulticast() == true)
  159. {
  160. if (pInterface)
  161. {
  162. stInterfaceAddr.s_addr= inet_addr(pInterface);
  163. if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_IF, &stInterfaceAddr, sizeof(stInterfaceAddr)) == SocketSuccess)
  164. {
  165. bRetVal = true;
  166. }
  167. }
  168. }
  169. else
  170. {
  171. SetSocketError(CSimpleSocket::SocketProtocolError);
  172. }
  173. return bRetVal;
  174. }
  175. //------------------------------------------------------------------------------
  176. //
  177. // SetMulticast()
  178. //
  179. //------------------------------------------------------------------------------
  180. bool CSimpleSocket::SetMulticast(bool bEnable, uint8 multicastTTL)
  181. {
  182. bool bRetVal = false;
  183. if (GetSocketType() == CSimpleSocket::SocketTypeUdp)
  184. {
  185. m_bIsMulticast = bEnable;
  186. if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&multicastTTL, sizeof(multicastTTL)) == SocketError)
  187. {
  188. TranslateSocketError();
  189. bRetVal = false;
  190. }
  191. else
  192. {
  193. bRetVal = true;
  194. }
  195. }
  196. else
  197. {
  198. m_socketErrno = CSimpleSocket::SocketProtocolError;
  199. }
  200. return bRetVal;
  201. }
  202. //------------------------------------------------------------------------------
  203. //
  204. // SetSocketDscp()
  205. //
  206. //------------------------------------------------------------------------------
  207. bool CSimpleSocket::SetSocketDscp(int32 nDscp)
  208. {
  209. bool bRetVal = true;
  210. int32 nTempVal = nDscp;
  211. nTempVal <<= 4;
  212. nTempVal /= 4;
  213. if (IsSocketValid())
  214. {
  215. if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, sizeof(nTempVal)) == SocketError)
  216. {
  217. TranslateSocketError();
  218. bRetVal = false;
  219. }
  220. }
  221. return bRetVal;
  222. }
  223. //------------------------------------------------------------------------------
  224. //
  225. // GetSocketDscp()
  226. //
  227. //------------------------------------------------------------------------------
  228. int32 CSimpleSocket::GetSocketDscp(void)
  229. {
  230. int32 nTempVal = 0;
  231. socklen_t nLen = 0;
  232. if (IsSocketValid())
  233. {
  234. if (GETSOCKOPT(m_socket, IPPROTO_IP, IP_TOS, &nTempVal, &nLen) == SocketError)
  235. {
  236. TranslateSocketError();
  237. }
  238. nTempVal *= 4;
  239. nTempVal >>= 4;
  240. }
  241. return nTempVal;
  242. }
  243. //------------------------------------------------------------------------------
  244. //
  245. // GetWindowSize()
  246. //
  247. //------------------------------------------------------------------------------
  248. uint32 CSimpleSocket::GetWindowSize(uint32 nOptionName)
  249. {
  250. uint32 nTcpWinSize = 0;
  251. //-------------------------------------------------------------------------
  252. // no socket given, return system default allocate our own new socket
  253. //-------------------------------------------------------------------------
  254. if (m_socket != CSimpleSocket::SocketError)
  255. {
  256. socklen_t nLen = sizeof(nTcpWinSize);
  257. //---------------------------------------------------------------------
  258. // query for buffer size
  259. //---------------------------------------------------------------------
  260. GETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nTcpWinSize, &nLen);
  261. TranslateSocketError();
  262. }
  263. else
  264. {
  265. SetSocketError(CSimpleSocket::SocketInvalidSocket);
  266. }
  267. return nTcpWinSize;
  268. }
  269. //------------------------------------------------------------------------------
  270. //
  271. // SetWindowSize()
  272. //
  273. //------------------------------------------------------------------------------
  274. uint32 CSimpleSocket::SetWindowSize(uint32 nOptionName, uint32 nWindowSize)
  275. {
  276. //-------------------------------------------------------------------------
  277. // no socket given, return system default allocate our own new socket
  278. //-------------------------------------------------------------------------
  279. if (m_socket != CSimpleSocket::SocketError)
  280. {
  281. SETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nWindowSize, sizeof(nWindowSize));
  282. TranslateSocketError();
  283. }
  284. else
  285. {
  286. SetSocketError(CSimpleSocket::SocketInvalidSocket);
  287. }
  288. return nWindowSize;
  289. }
  290. //------------------------------------------------------------------------------
  291. //
  292. // DisableNagleAlgorithm()
  293. //
  294. //------------------------------------------------------------------------------
  295. bool CSimpleSocket::DisableNagleAlgoritm()
  296. {
  297. bool bRetVal = false;
  298. int32 nTcpNoDelay = 1;
  299. //----------------------------------------------------------------------
  300. // Set TCP NoDelay flag to true
  301. //----------------------------------------------------------------------
  302. if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32)) == 0)
  303. {
  304. bRetVal = true;
  305. }
  306. TranslateSocketError();
  307. return bRetVal;
  308. }
  309. //------------------------------------------------------------------------------
  310. //
  311. // EnableNagleAlgorithm()
  312. //
  313. //------------------------------------------------------------------------------
  314. bool CSimpleSocket::EnableNagleAlgoritm()
  315. {
  316. bool bRetVal = false;
  317. int32 nTcpNoDelay = 0;
  318. //----------------------------------------------------------------------
  319. // Set TCP NoDelay flag to false
  320. //----------------------------------------------------------------------
  321. if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32)) == 0)
  322. {
  323. bRetVal = true;
  324. }
  325. TranslateSocketError();
  326. return bRetVal;
  327. }
  328. //------------------------------------------------------------------------------
  329. //
  330. // Send() - Send data on a valid socket
  331. //
  332. //------------------------------------------------------------------------------
  333. int32 CSimpleSocket::Send(const uint8 *pBuf, size_t bytesToSend)
  334. {
  335. SetSocketError(SocketSuccess);
  336. m_nBytesSent = 0;
  337. switch(m_nSocketType)
  338. {
  339. case CSimpleSocket::SocketTypeTcp:
  340. {
  341. if (IsSocketValid())
  342. {
  343. if ((bytesToSend > 0) && (pBuf != NULL))
  344. {
  345. m_timer.Initialize();
  346. m_timer.SetStartTime();
  347. //---------------------------------------------------------
  348. // Check error condition and attempt to resend if call
  349. // was interrupted by a signal.
  350. //---------------------------------------------------------
  351. do
  352. {
  353. m_nBytesSent = SEND(m_socket, pBuf, bytesToSend, 0);
  354. TranslateSocketError();
  355. } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
  356. m_timer.SetEndTime();
  357. }
  358. }
  359. break;
  360. }
  361. case CSimpleSocket::SocketTypeUdp:
  362. {
  363. if (IsSocketValid())
  364. {
  365. if ((bytesToSend > 0) && (pBuf != NULL))
  366. {
  367. m_timer.Initialize();
  368. m_timer.SetStartTime();
  369. //---------------------------------------------------------
  370. // Check error condition and attempt to resend if call
  371. // was interrupted by a signal.
  372. //---------------------------------------------------------
  373. // if (GetMulticast())
  374. // {
  375. // do
  376. // {
  377. // m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stMulticastGroup,
  378. // sizeof(m_stMulticastGroup));
  379. // TranslateSocketError();
  380. // } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
  381. // }
  382. // else
  383. {
  384. do
  385. {
  386. m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr));
  387. TranslateSocketError();
  388. } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
  389. }
  390. m_timer.SetEndTime();
  391. }
  392. }
  393. break;
  394. }
  395. default:
  396. break;
  397. }
  398. return m_nBytesSent;
  399. }
  400. //------------------------------------------------------------------------------
  401. //
  402. // Close() - Close socket and free up any memory allocated for the socket
  403. //
  404. //------------------------------------------------------------------------------
  405. bool CSimpleSocket::Close(void)
  406. {
  407. bool bRetVal = false;
  408. //--------------------------------------------------------------------------
  409. // delete internal buffer
  410. //--------------------------------------------------------------------------
  411. if (m_pBuffer != NULL)
  412. {
  413. delete [] m_pBuffer;
  414. m_pBuffer = NULL;
  415. }
  416. //--------------------------------------------------------------------------
  417. // if socket handle is currently valid, close and then invalidate
  418. //--------------------------------------------------------------------------
  419. if (IsSocketValid())
  420. {
  421. if (CLOSE(m_socket) != CSimpleSocket::SocketError)
  422. {
  423. m_socket = INVALID_SOCKET;
  424. bRetVal = true;
  425. }
  426. }
  427. TranslateSocketError();
  428. return bRetVal;
  429. }
  430. //------------------------------------------------------------------------------
  431. //
  432. // Shtudown()
  433. //
  434. //------------------------------------------------------------------------------
  435. bool CSimpleSocket::Shutdown(CShutdownMode nShutdown)
  436. {
  437. CSocketError nRetVal = SocketEunknown;
  438. nRetVal = (CSocketError)shutdown(m_socket, nShutdown);
  439. TranslateSocketError();
  440. return (nRetVal == CSimpleSocket::SocketSuccess) ? true: false;
  441. }
  442. //------------------------------------------------------------------------------
  443. //
  444. // Flush()
  445. //
  446. //------------------------------------------------------------------------------
  447. bool CSimpleSocket::Flush()
  448. {
  449. int32 nTcpNoDelay = 1;
  450. int32 nCurFlags = 0;
  451. uint8 tmpbuf = 0;
  452. bool bRetVal = false;
  453. //--------------------------------------------------------------------------
  454. // Get the current setting of the TCP_NODELAY flag.
  455. //--------------------------------------------------------------------------
  456. if (GETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nCurFlags, sizeof(int32)) == 0)
  457. {
  458. //----------------------------------------------------------------------
  459. // Set TCP NoDelay flag
  460. //----------------------------------------------------------------------
  461. if (SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nTcpNoDelay, sizeof(int32)) == 0)
  462. {
  463. //------------------------------------------------------------------
  464. // Send empty byte stream to flush the TCP send buffer
  465. //------------------------------------------------------------------
  466. if (Send(&tmpbuf, 0) != CSimpleSocket::SocketError)
  467. {
  468. bRetVal = true;
  469. }
  470. TranslateSocketError();
  471. }
  472. //----------------------------------------------------------------------
  473. // Reset the TCP_NODELAY flag to original state.
  474. //----------------------------------------------------------------------
  475. SETSOCKOPT(m_socket, IPPROTO_TCP, TCP_NODELAY, &nCurFlags, sizeof(int32));
  476. }
  477. return bRetVal;
  478. }
  479. //------------------------------------------------------------------------------
  480. //
  481. // Writev -
  482. //
  483. //------------------------------------------------------------------------------
  484. int32 CSimpleSocket::Writev(const struct iovec *pVector, size_t nCount)
  485. {
  486. int32 nBytes = 0;
  487. int32 nBytesSent = 0;
  488. int32 i = 0;
  489. //--------------------------------------------------------------------------
  490. // Send each buffer as a separate send, windows does not support this
  491. // function call.
  492. //--------------------------------------------------------------------------
  493. for (i = 0; i < (int32)nCount; i++)
  494. {
  495. if ((nBytes = Send((uint8 *)pVector[i].iov_base, pVector[i].iov_len)) == CSimpleSocket::SocketError)
  496. {
  497. break;
  498. }
  499. nBytesSent += nBytes;
  500. }
  501. if (i > 0)
  502. {
  503. Flush();
  504. }
  505. return nBytesSent;
  506. }
  507. //------------------------------------------------------------------------------
  508. //
  509. // Send() - Send data on a valid socket via a vector of buffers.
  510. //
  511. //------------------------------------------------------------------------------
  512. int32 CSimpleSocket::Send(const struct iovec *sendVector, int32 nNumItems)
  513. {
  514. SetSocketError(SocketSuccess);
  515. m_nBytesSent = 0;
  516. if ((m_nBytesSent = WRITEV(m_socket, sendVector, nNumItems)) == CSimpleSocket::SocketError)
  517. {
  518. TranslateSocketError();
  519. }
  520. return m_nBytesSent;
  521. }
  522. //------------------------------------------------------------------------------
  523. //
  524. // SetReceiveTimeout()
  525. //
  526. //------------------------------------------------------------------------------
  527. bool CSimpleSocket::SetReceiveTimeout(int32 nRecvTimeoutSec, int32 nRecvTimeoutUsec)
  528. {
  529. bool bRetVal = true;
  530. memset(&m_stRecvTimeout, 0, sizeof(struct timeval));
  531. m_stRecvTimeout.tv_sec = nRecvTimeoutSec;
  532. m_stRecvTimeout.tv_usec = nRecvTimeoutUsec;
  533. //--------------------------------------------------------------------------
  534. // Sanity check to make sure the options are supported!
  535. //--------------------------------------------------------------------------
  536. if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_RCVTIMEO, &m_stRecvTimeout,
  537. sizeof(struct timeval)) == CSimpleSocket::SocketError)
  538. {
  539. bRetVal = false;
  540. TranslateSocketError();
  541. }
  542. return bRetVal;
  543. }
  544. //------------------------------------------------------------------------------
  545. //
  546. // SetSendTimeout()
  547. //
  548. //------------------------------------------------------------------------------
  549. bool CSimpleSocket::SetSendTimeout(int32 nSendTimeoutSec, int32 nSendTimeoutUsec)
  550. {
  551. bool bRetVal = true;
  552. memset(&m_stSendTimeout, 0, sizeof(struct timeval));
  553. m_stSendTimeout.tv_sec = nSendTimeoutSec;
  554. m_stSendTimeout.tv_usec = nSendTimeoutUsec;
  555. //--------------------------------------------------------------------------
  556. // Sanity check to make sure the options are supported!
  557. //--------------------------------------------------------------------------
  558. if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_SNDTIMEO, &m_stSendTimeout,
  559. sizeof(struct timeval)) == CSimpleSocket::SocketError)
  560. {
  561. bRetVal = false;
  562. TranslateSocketError();
  563. }
  564. return bRetVal;
  565. }
  566. //------------------------------------------------------------------------------
  567. //
  568. // SetOptionReuseAddr()
  569. //
  570. //------------------------------------------------------------------------------
  571. bool CSimpleSocket::SetOptionReuseAddr()
  572. {
  573. bool bRetVal = false;
  574. int32 nReuse = IPTOS_LOWDELAY;
  575. if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32)) == 0)
  576. {
  577. bRetVal = true;
  578. }
  579. TranslateSocketError();
  580. return bRetVal;
  581. }
  582. //------------------------------------------------------------------------------
  583. //
  584. // SetOptionLinger()
  585. //
  586. //------------------------------------------------------------------------------
  587. bool CSimpleSocket::SetOptionLinger(bool bEnable, uint16 nTime)
  588. {
  589. bool bRetVal = false;
  590. m_stLinger.l_onoff = (bEnable == true) ? 1: 0;
  591. m_stLinger.l_linger = nTime;
  592. if (SETSOCKOPT(m_socket, SOL_SOCKET, SO_LINGER, &m_stLinger, sizeof(m_stLinger)) == 0)
  593. {
  594. bRetVal = true;
  595. }
  596. TranslateSocketError();
  597. return bRetVal;
  598. }
  599. //------------------------------------------------------------------------------
  600. //
  601. // Receive() - Attempts to receive a block of data on an established
  602. // connection. Data is received in an internal buffer managed
  603. // by the class. This buffer is only valid until the next call
  604. // to Receive(), a call to Close(), or until the object goes out
  605. // of scope.
  606. //
  607. //------------------------------------------------------------------------------
  608. int32 CSimpleSocket::Receive(int32 nMaxBytes, uint8 * pBuffer )
  609. {
  610. m_nBytesReceived = 0;
  611. //--------------------------------------------------------------------------
  612. // If the socket is invalid then return false.
  613. //--------------------------------------------------------------------------
  614. if (IsSocketValid() == false)
  615. {
  616. return m_nBytesReceived;
  617. }
  618. uint8 * pWorkBuffer = pBuffer;
  619. if ( pBuffer == NULL )
  620. {
  621. //--------------------------------------------------------------------------
  622. // Free existing buffer and allocate a new buffer the size of
  623. // nMaxBytes.
  624. //--------------------------------------------------------------------------
  625. if ((m_pBuffer != NULL) && (nMaxBytes != m_nBufferSize))
  626. {
  627. delete [] m_pBuffer;
  628. m_pBuffer = NULL;
  629. }
  630. //--------------------------------------------------------------------------
  631. // Allocate a new internal buffer to receive data.
  632. //--------------------------------------------------------------------------
  633. if (m_pBuffer == NULL)
  634. {
  635. m_nBufferSize = nMaxBytes;
  636. m_pBuffer = new uint8[nMaxBytes];
  637. }
  638. pWorkBuffer = m_pBuffer;
  639. }
  640. SetSocketError(SocketSuccess);
  641. m_timer.Initialize();
  642. m_timer.SetStartTime();
  643. switch (m_nSocketType)
  644. {
  645. //----------------------------------------------------------------------
  646. // If zero bytes are received, then return. If SocketERROR is
  647. // received, free buffer and return CSocket::SocketError (-1) to caller.
  648. //----------------------------------------------------------------------
  649. case CSimpleSocket::SocketTypeTcp:
  650. {
  651. do
  652. {
  653. m_nBytesReceived = RECV(m_socket, (pWorkBuffer + m_nBytesReceived),
  654. nMaxBytes, m_nFlags);
  655. TranslateSocketError();
  656. } while ((GetSocketError() == CSimpleSocket::SocketInterrupted));
  657. break;
  658. }
  659. case CSimpleSocket::SocketTypeUdp:
  660. {
  661. uint32 srcSize;
  662. srcSize = sizeof(struct sockaddr_in);
  663. if (GetMulticast() == true)
  664. {
  665. do
  666. {
  667. m_nBytesReceived = RECVFROM(m_socket, pWorkBuffer, nMaxBytes, 0,
  668. &m_stMulticastGroup, &srcSize);
  669. TranslateSocketError();
  670. } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
  671. }
  672. else
  673. {
  674. do
  675. {
  676. m_nBytesReceived = RECVFROM(m_socket, pWorkBuffer, nMaxBytes, 0,
  677. &m_stClientSockaddr, &srcSize);
  678. TranslateSocketError();
  679. } while (GetSocketError() == CSimpleSocket::SocketInterrupted);
  680. }
  681. break;
  682. }
  683. default:
  684. break;
  685. }
  686. m_timer.SetEndTime();
  687. TranslateSocketError();
  688. //--------------------------------------------------------------------------
  689. // If we encounter an error translate the error code and return. One
  690. // possible error code could be EAGAIN (EWOULDBLOCK) if the socket is
  691. // non-blocking. This does not mean there is an error, but no data is
  692. // yet available on the socket.
  693. //--------------------------------------------------------------------------
  694. if (m_nBytesReceived == CSimpleSocket::SocketError)
  695. {
  696. if (m_pBuffer != NULL)
  697. {
  698. delete [] m_pBuffer;
  699. m_pBuffer = NULL;
  700. }
  701. }
  702. return m_nBytesReceived;
  703. }
  704. //------------------------------------------------------------------------------
  705. //
  706. // SetNonblocking()
  707. //
  708. //------------------------------------------------------------------------------
  709. bool CSimpleSocket::SetNonblocking(void)
  710. {
  711. int32 nCurFlags;
  712. #if WIN32
  713. nCurFlags = 1;
  714. if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0)
  715. {
  716. TranslateSocketError();
  717. return false;
  718. }
  719. #else
  720. if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0)
  721. {
  722. TranslateSocketError();
  723. return false;
  724. }
  725. nCurFlags |= O_NONBLOCK;
  726. if (fcntl(m_socket, F_SETFL, nCurFlags) != 0)
  727. {
  728. TranslateSocketError();
  729. return false;
  730. }
  731. #endif
  732. m_bIsBlocking = false;
  733. return true;
  734. }
  735. //------------------------------------------------------------------------------
  736. //
  737. // SetBlocking()
  738. //
  739. //------------------------------------------------------------------------------
  740. bool CSimpleSocket::SetBlocking(void)
  741. {
  742. int32 nCurFlags;
  743. #if WIN32
  744. nCurFlags = 0;
  745. if (ioctlsocket(m_socket, FIONBIO, (ULONG *)&nCurFlags) != 0)
  746. {
  747. return false;
  748. }
  749. #else
  750. if ((nCurFlags = fcntl(m_socket, F_GETFL)) < 0)
  751. {
  752. TranslateSocketError();
  753. return false;
  754. }
  755. nCurFlags &= (~O_NONBLOCK);
  756. if (fcntl(m_socket, F_SETFL, nCurFlags) != 0)
  757. {
  758. TranslateSocketError();
  759. return false;
  760. }
  761. #endif
  762. m_bIsBlocking = true;
  763. return true;
  764. }
  765. //------------------------------------------------------------------------------
  766. //
  767. // SendFile() - stands-in for system provided sendfile
  768. //
  769. //------------------------------------------------------------------------------
  770. int32 CSimpleSocket::SendFile(int32 nOutFd, int32 nInFd, off_t *pOffset, int32 nCount)
  771. {
  772. int32 nOutCount = CSimpleSocket::SocketError;
  773. static char szData[SOCKET_SENDFILE_BLOCKSIZE];
  774. int32 nInCount = 0;
  775. if (lseek(nInFd, *pOffset, SEEK_SET) == -1)
  776. {
  777. return -1;
  778. }
  779. while (nOutCount < nCount)
  780. {
  781. nInCount = (nCount - nOutCount) < SOCKET_SENDFILE_BLOCKSIZE ? (nCount - nOutCount) : SOCKET_SENDFILE_BLOCKSIZE;
  782. if ((read(nInFd, szData, nInCount)) != (int32)nInCount)
  783. {
  784. return -1;
  785. }
  786. if ((SEND(nOutFd, szData, nInCount, 0)) != (int32)nInCount)
  787. {
  788. return -1;
  789. }
  790. nOutCount += nInCount;
  791. }
  792. *pOffset += nOutCount;
  793. TranslateSocketError();
  794. return nOutCount;
  795. }
  796. //------------------------------------------------------------------------------
  797. //
  798. // TranslateSocketError() -
  799. //
  800. //------------------------------------------------------------------------------
  801. void CSimpleSocket::TranslateSocketError(void)
  802. {
  803. #if defined(_LINUX) || defined(_DARWIN)
  804. switch (errno)
  805. {
  806. case EXIT_SUCCESS:
  807. SetSocketError(CSimpleSocket::SocketSuccess);
  808. break;
  809. case ENOTCONN:
  810. SetSocketError(CSimpleSocket::SocketNotconnected);
  811. break;
  812. case ENOTSOCK:
  813. case EBADF:
  814. case EACCES:
  815. case EAFNOSUPPORT:
  816. case EMFILE:
  817. case ENFILE:
  818. case ENOBUFS:
  819. case ENOMEM:
  820. case EPROTONOSUPPORT:
  821. case EPIPE:
  822. case EOPNOTSUPP:
  823. SetSocketError(CSimpleSocket::SocketInvalidSocket);
  824. break;
  825. case ECONNREFUSED :
  826. SetSocketError(CSimpleSocket::SocketConnectionRefused);
  827. break;
  828. case ETIMEDOUT:
  829. SetSocketError(CSimpleSocket::SocketTimedout);
  830. break;
  831. case EINPROGRESS:
  832. SetSocketError(CSimpleSocket::SocketEinprogress);
  833. break;
  834. case EWOULDBLOCK:
  835. // case EAGAIN:
  836. SetSocketError(CSimpleSocket::SocketEwouldblock);
  837. break;
  838. case EINTR:
  839. SetSocketError(CSimpleSocket::SocketInterrupted);
  840. break;
  841. case ECONNABORTED:
  842. SetSocketError(CSimpleSocket::SocketConnectionAborted);
  843. break;
  844. case EINVAL:
  845. case EPROTO:
  846. SetSocketError(CSimpleSocket::SocketProtocolError);
  847. break;
  848. case EPERM:
  849. SetSocketError(CSimpleSocket::SocketFirewallError);
  850. break;
  851. case EFAULT:
  852. SetSocketError(CSimpleSocket::SocketInvalidSocketBuffer);
  853. break;
  854. case ECONNRESET:
  855. case ENOPROTOOPT:
  856. SetSocketError(CSimpleSocket::SocketConnectionReset);
  857. break;
  858. case EADDRINUSE:
  859. SetSocketError(CSimpleSocket::SocketAddressInUse);
  860. break;
  861. default:
  862. SetSocketError(CSimpleSocket::SocketEunknown);
  863. break;
  864. }
  865. #endif
  866. #ifdef WIN32
  867. int32 nError = WSAGetLastError();
  868. switch (nError)
  869. {
  870. case EXIT_SUCCESS:
  871. SetSocketError(CSimpleSocket::SocketSuccess);
  872. break;
  873. case WSAEBADF:
  874. case WSAENOTCONN:
  875. SetSocketError(CSimpleSocket::SocketNotconnected);
  876. break;
  877. case WSAEINTR:
  878. SetSocketError(CSimpleSocket::SocketInterrupted);
  879. break;
  880. case WSAEACCES:
  881. case WSAEAFNOSUPPORT:
  882. case WSAEINVAL:
  883. case WSAEMFILE:
  884. case WSAENOBUFS:
  885. case WSAEPROTONOSUPPORT:
  886. SetSocketError(CSimpleSocket::SocketInvalidSocket);
  887. break;
  888. case WSAECONNREFUSED :
  889. SetSocketError(CSimpleSocket::SocketConnectionRefused);
  890. break;
  891. case WSAETIMEDOUT:
  892. SetSocketError(CSimpleSocket::SocketTimedout);
  893. break;
  894. case WSAEINPROGRESS:
  895. SetSocketError(CSimpleSocket::SocketEinprogress);
  896. break;
  897. case WSAECONNABORTED:
  898. SetSocketError(CSimpleSocket::SocketConnectionAborted);
  899. break;
  900. case WSAEWOULDBLOCK:
  901. SetSocketError(CSimpleSocket::SocketEwouldblock);
  902. break;
  903. case WSAENOTSOCK:
  904. SetSocketError(CSimpleSocket::SocketInvalidSocket);
  905. break;
  906. case WSAECONNRESET:
  907. SetSocketError(CSimpleSocket::SocketConnectionReset);
  908. break;
  909. case WSANO_DATA:
  910. SetSocketError(CSimpleSocket::SocketInvalidAddress);
  911. break;
  912. case WSAEADDRINUSE:
  913. SetSocketError(CSimpleSocket::SocketAddressInUse);
  914. break;
  915. case WSAEFAULT:
  916. SetSocketError(CSimpleSocket::SocketInvalidPointer);
  917. break;
  918. default:
  919. SetSocketError(CSimpleSocket::SocketEunknown);
  920. break;
  921. }
  922. #endif
  923. }
  924. //------------------------------------------------------------------------------
  925. //
  926. // DescribeError()
  927. //
  928. //------------------------------------------------------------------------------
  929. const char *CSimpleSocket::DescribeError(CSocketError err)
  930. {
  931. switch (err) {
  932. case CSimpleSocket::SocketError:
  933. return "Generic socket error translates to error below.";
  934. case CSimpleSocket::SocketSuccess:
  935. return "No socket error.";
  936. case CSimpleSocket::SocketInvalidSocket:
  937. return "Invalid socket handle.";
  938. case CSimpleSocket::SocketInvalidAddress:
  939. return "Invalid destination address specified.";
  940. case CSimpleSocket::SocketInvalidPort:
  941. return "Invalid destination port specified.";
  942. case CSimpleSocket::SocketConnectionRefused:
  943. return "No server is listening at remote address.";
  944. case CSimpleSocket::SocketTimedout:
  945. return "Timed out while attempting operation.";
  946. case CSimpleSocket::SocketEwouldblock:
  947. return "Operation would block if socket were blocking.";
  948. case CSimpleSocket::SocketNotconnected:
  949. return "Currently not connected.";
  950. case CSimpleSocket::SocketEinprogress:
  951. return "Socket is non-blocking and the connection cannot be completed immediately";
  952. case CSimpleSocket::SocketInterrupted:
  953. return "Call was interrupted by a signal that was caught before a valid connection arrived.";
  954. case CSimpleSocket::SocketConnectionAborted:
  955. return "The connection has been aborted.";
  956. case CSimpleSocket::SocketProtocolError:
  957. return "Invalid protocol for operation.";
  958. case CSimpleSocket::SocketFirewallError:
  959. return "Firewall rules forbid connection.";
  960. case CSimpleSocket::SocketInvalidSocketBuffer:
  961. return "The receive buffer point outside the process's address space.";
  962. case CSimpleSocket::SocketConnectionReset:
  963. return "Connection was forcibly closed by the remote host.";
  964. case CSimpleSocket::SocketAddressInUse:
  965. return "Address already in use.";
  966. case CSimpleSocket::SocketInvalidPointer:
  967. return "Pointer type supplied as argument is invalid.";
  968. case CSimpleSocket::SocketEunknown:
  969. return "Unknown error";
  970. default:
  971. return "No such CSimpleSocket error";
  972. }
  973. }
  974. //------------------------------------------------------------------------------
  975. //
  976. // Select()
  977. //
  978. //------------------------------------------------------------------------------
  979. bool CSimpleSocket::Select(int32 nTimeoutSec, int32 nTimeoutUSec)
  980. {
  981. bool bRetVal = false;
  982. struct timeval *pTimeout = NULL;
  983. struct timeval timeout;
  984. int32 nNumDescriptors = -1;
  985. int32 nError = 0;
  986. FD_ZERO(&m_errorFds);
  987. FD_ZERO(&m_readFds);
  988. FD_ZERO(&m_writeFds);
  989. FD_SET(m_socket, &m_errorFds);
  990. FD_SET(m_socket, &m_readFds);
  991. FD_SET(m_socket, &m_writeFds);
  992. //---------------------------------------------------------------------
  993. // If timeout has been specified then set value, otherwise set timeout
  994. // to NULL which will block until a descriptor is ready for read/write
  995. // or an error has occurred.
  996. //---------------------------------------------------------------------
  997. if ((nTimeoutSec > 0) || (nTimeoutUSec > 0))
  998. {
  999. timeout.tv_sec = nTimeoutSec;
  1000. timeout.tv_usec = nTimeoutUSec;
  1001. pTimeout = &timeout;
  1002. }
  1003. nNumDescriptors = SELECT(m_socket+1, &m_readFds, &m_writeFds, &m_errorFds, pTimeout);
  1004. // nNumDescriptors = SELECT(m_socket+1, &m_readFds, NULL, NULL, pTimeout);
  1005. //----------------------------------------------------------------------
  1006. // Handle timeout
  1007. //----------------------------------------------------------------------
  1008. if (nNumDescriptors == 0)
  1009. {
  1010. SetSocketError(CSimpleSocket::SocketTimedout);
  1011. }
  1012. //----------------------------------------------------------------------
  1013. // If a file descriptor (read/write) is set then check the
  1014. // socket error (SO_ERROR) to see if there is a pending error.
  1015. //----------------------------------------------------------------------
  1016. else if ((FD_ISSET(m_socket, &m_readFds)) || (FD_ISSET(m_socket, &m_writeFds)))
  1017. {
  1018. int32 nLen = sizeof(nError);
  1019. if (GETSOCKOPT(m_socket, SOL_SOCKET, SO_ERROR, &nError, &nLen) == 0)
  1020. {
  1021. errno = nError;
  1022. if (nError == 0)
  1023. {
  1024. bRetVal = true;
  1025. }
  1026. }
  1027. TranslateSocketError();
  1028. }
  1029. return bRetVal;
  1030. }