PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Socket.cpp

https://bitbucket.org/clb/knet
C++ | 963 lines | 779 code | 122 blank | 62 comment | 207 complexity | 5607d99b31c8266f774c21de089a2bed MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright The kNet Project.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. /** @file Socket.cpp
  12. @brief */
  13. #include <string>
  14. #include <cassert>
  15. #include <utility>
  16. #include <sstream>
  17. #ifdef KNET_USE_BOOST
  18. #include <boost/thread/thread.hpp>
  19. #endif
  20. #include "kNet/DebugMemoryLeakCheck.h"
  21. #include "kNet/Network.h"
  22. #include "kNet/Socket.h"
  23. #include "kNet/NetworkLogging.h"
  24. #include "kNet/EventArray.h"
  25. using namespace std;
  26. #if defined(UNIX) || defined(ANDROID)
  27. #include <fcntl.h>
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <netinet/tcp.h>
  31. #endif
  32. #ifdef WIN32
  33. const int numConcurrentReceiveBuffers = 4;
  34. const int numConcurrentSendBuffers = 4;
  35. #endif
  36. namespace kNet
  37. {
  38. std::string SocketTransportLayerToString(SocketTransportLayer transport)
  39. {
  40. switch(transport)
  41. {
  42. case SocketOverUDP: return "UDP";
  43. case SocketOverTCP: return "TCP";
  44. default:
  45. {
  46. std::stringstream ss;
  47. ss << "Invalid SocketTransportLayer (" << (int)transport << ")!";
  48. return ss.str();
  49. }
  50. }
  51. }
  52. SocketTransportLayer StringToSocketTransportLayer(const char *str)
  53. {
  54. if (!str)
  55. return InvalidTransportLayer;
  56. if (!_stricmp(str, "tcp") || !_stricmp(str, "SocketOverTCP"))
  57. return SocketOverTCP;
  58. if (!_stricmp(str, "udp") || !_stricmp(str, "SocketOverUDP"))
  59. return SocketOverUDP;
  60. return InvalidTransportLayer;
  61. }
  62. std::string SocketTypeToString(SocketType type)
  63. {
  64. switch(type)
  65. {
  66. case ServerListenSocket: return "Server listen socket";
  67. case ServerClientSocket: return "Server client socket";
  68. case ClientSocket: return "Client socket";
  69. default:
  70. {
  71. std::stringstream ss;
  72. ss << "Invalid SocketType (" << (int)type << ")!";
  73. return ss.str();
  74. }
  75. }
  76. }
  77. Socket::Socket()
  78. :connectSocket(INVALID_SOCKET),
  79. writeOpen(false),
  80. readOpen(false),
  81. transport(InvalidTransportLayer),
  82. type(InvalidSocketType)
  83. #ifdef WIN32
  84. ,queuedReceiveBuffers(numConcurrentReceiveBuffers)
  85. ,queuedSendBuffers(numConcurrentSendBuffers)
  86. #endif
  87. {
  88. localEndPoint.Reset();
  89. remoteEndPoint.Reset();
  90. }
  91. Socket::~Socket()
  92. {
  93. // We cannot Close() the socket here, since the same underlying BSD SOCKET handle can be shared
  94. // between multiple Socket objects. We rely instead to non-RAII behavior and manually remembering to
  95. // Close().
  96. #ifdef WIN32
  97. FreeOverlappedTransferBuffers();
  98. #endif
  99. }
  100. Socket::Socket(SOCKET connection, const EndPoint &localEndPoint_, const char *localHostName_,
  101. const EndPoint &remoteEndPoint_, const char *remoteHostName_,
  102. SocketTransportLayer transport_, SocketType type_, size_t maxSendSize_)
  103. :connectSocket(connection), localEndPoint(localEndPoint_), localHostName(localHostName_),
  104. remoteEndPoint(remoteEndPoint_), remoteHostName(remoteHostName_),
  105. transport(transport_), type(type_), maxSendSize(maxSendSize_),
  106. writeOpen(true), readOpen(true)
  107. #ifdef WIN32
  108. ,queuedReceiveBuffers(numConcurrentReceiveBuffers)
  109. ,queuedSendBuffers(numConcurrentSendBuffers)
  110. #endif
  111. {
  112. SetSendBufferSize(512 * 1024);
  113. SetReceiveBufferSize(512 * 1024);
  114. udpPeerAddress = remoteEndPoint.ToSockAddrIn();
  115. }
  116. Socket::Socket(const Socket &rhs)
  117. #ifdef WIN32
  118. :queuedReceiveBuffers(numConcurrentReceiveBuffers)
  119. ,queuedSendBuffers(numConcurrentSendBuffers)
  120. #endif
  121. {
  122. *this = rhs;
  123. }
  124. Socket &Socket::operator=(const Socket &rhs)
  125. {
  126. #ifdef WIN32
  127. // We would be losing data if Socket is copied from old to new when data is present in the receive buffers,
  128. // since the receive buffers are not moved or copied to the new Socket.
  129. assert(queuedReceiveBuffers.Size() == 0);
  130. #endif
  131. if (this == &rhs)
  132. return *this;
  133. connectSocket = rhs.connectSocket;
  134. localEndPoint = rhs.localEndPoint;
  135. localHostName = rhs.localHostName;
  136. remoteEndPoint = rhs.remoteEndPoint;
  137. remoteHostName = rhs.remoteHostName;
  138. transport = rhs.transport;
  139. type = rhs.type;
  140. maxSendSize = rhs.maxSendSize;
  141. writeOpen = rhs.writeOpen;
  142. readOpen = rhs.readOpen;
  143. udpPeerAddress = rhs.udpPeerAddress;
  144. return *this;
  145. }
  146. bool Socket::Connected() const
  147. {
  148. return connectSocket != INVALID_SOCKET;
  149. }
  150. OverlappedTransferBuffer *AllocateOverlappedTransferBuffer(int bytes)
  151. {
  152. OverlappedTransferBuffer *buffer = new OverlappedTransferBuffer;
  153. memset(buffer, 0, sizeof(OverlappedTransferBuffer));
  154. buffer->buffer.buf = new char[bytes];
  155. buffer->buffer.len = bytes;
  156. #ifdef WIN32
  157. buffer->overlapped.hEvent = WSACreateEvent();
  158. if (buffer->overlapped.hEvent == WSA_INVALID_EVENT)
  159. {
  160. LOG(LogError, "Socket.cpp:AllocateOverlappedTransferBuffer: WSACreateEvent failed!");
  161. delete[] buffer->buffer.buf;
  162. delete buffer;
  163. return 0;
  164. }
  165. #endif
  166. return buffer;
  167. }
  168. void DeleteOverlappedTransferBuffer(OverlappedTransferBuffer *buffer)
  169. {
  170. if (!buffer)
  171. return;
  172. delete[] buffer->buffer.buf;
  173. #ifdef WIN32
  174. BOOL success = WSACloseEvent(buffer->overlapped.hEvent);
  175. if (success == FALSE)
  176. LOG(LogError, "Socket.cpp:DeleteOverlappedTransferBuffer: WSACloseEvent failed!");
  177. buffer->overlapped.hEvent = WSA_INVALID_EVENT;
  178. #endif
  179. delete buffer;
  180. }
  181. void Socket::SetSendBufferSize(int bytes)
  182. {
  183. socklen_t len = sizeof(bytes);
  184. if (setsockopt(connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bytes, len))
  185. LOG(LogError, "Socket::SetSendBufferSize: setsockopt failed with error %s!", Network::GetLastErrorString().c_str());
  186. }
  187. void Socket::SetReceiveBufferSize(int bytes)
  188. {
  189. socklen_t len = sizeof(bytes);
  190. if (setsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bytes, len))
  191. LOG(LogError, "Socket::SetReceiveBufferSize: setsockopt failed with error %s!", Network::GetLastErrorString().c_str());
  192. }
  193. int Socket::SendBufferSize() const
  194. {
  195. int bytes = 0;
  196. socklen_t len = sizeof(bytes);
  197. if (getsockopt(connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bytes, &len))
  198. {
  199. LOG(LogError, "Socket::SendBufferSize: getsockopt failed with error %s!", Network::GetLastErrorString().c_str());
  200. return 0;
  201. }
  202. return bytes;
  203. }
  204. int Socket::ReceiveBufferSize() const
  205. {
  206. int bytes = 0;
  207. socklen_t len = sizeof(bytes);
  208. if (getsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bytes, &len))
  209. {
  210. LOG(LogError, "Socket::ReceiveBufferSize: getsockopt failed with error %s!", Network::GetLastErrorString().c_str());
  211. return 0;
  212. }
  213. return bytes;
  214. }
  215. #ifdef WIN32
  216. void Socket::EnqueueNewReceiveBuffer(OverlappedTransferBuffer *buffer)
  217. {
  218. if (!readOpen || queuedReceiveBuffers.CapacityLeft() == 0 || IsUDPSlaveSocket())
  219. {
  220. DeleteOverlappedTransferBuffer(buffer); // buffer may be a zero pointer, but that is alright.
  221. return;
  222. }
  223. if (!buffer)
  224. {
  225. const int receiveBufferSize = 16384; // This is best to be at least 9K (the largest size of jumbo datagrams commonly supported)
  226. buffer = AllocateOverlappedTransferBuffer(receiveBufferSize);
  227. if (!buffer)
  228. {
  229. LOG(LogError, "Socket::EnqueueNewReceiveBuffer: Call to AllocateOverlappedTransferBuffer failed!");
  230. return;
  231. }
  232. }
  233. if (WSAResetEvent(buffer->overlapped.hEvent) != TRUE)
  234. LOG(LogError, "Socket::EnqueueNewReceiveBuffer: WSAResetEvent failed!");
  235. unsigned long flags = 0;
  236. int ret;
  237. if (IsUDPServerSocket())
  238. {
  239. buffer->fromLen = sizeof(buffer->from);
  240. ret = WSARecvFrom(connectSocket, &buffer->buffer, 1, (LPDWORD)&buffer->bytesContains, &flags, (sockaddr*)&buffer->from, &buffer->fromLen, &buffer->overlapped, 0);
  241. }
  242. else
  243. {
  244. ret = WSARecv(connectSocket, &buffer->buffer, 1, (LPDWORD)&buffer->bytesContains, &flags, &buffer->overlapped, 0);
  245. }
  246. int error = (ret == 0) ? 0 : Network::GetLastError();
  247. if (ret == 0 || (ret == SOCKET_ERROR && error == WSA_IO_PENDING)) // If ret is not 0, ret == SOCKET_ERROR according to MSDN. http://msdn.microsoft.com/en-us/library/ms741688(VS.85).aspx
  248. {
  249. if (ret == 0 && buffer->bytesContains == 0)
  250. {
  251. if (IsUDPServerSocket())
  252. LOG(LogError, "Unexpected: Received a message of 0 bytes on a UDP server socket!");
  253. LOG(LogInfo, "Socket::EnqueueNewReceiveBuffer: Received 0 bytes from the network. Read connection closed in socket %s.", ToString().c_str());
  254. readOpen = false;
  255. DeleteOverlappedTransferBuffer(buffer);
  256. return;
  257. }
  258. // Return value 0: The operation completed and we have received new data. Push it to a queue for the user to receive.
  259. // WSA_IO_PENDING: The operation was successfully enqueued.
  260. bool success = queuedReceiveBuffers.Insert(buffer);
  261. if (!success)
  262. {
  263. LOG(LogError, "Socket::EnqueueNewReceiveBuffer: queuedReceiveBuffers.Insert(buffer); failed!");
  264. DeleteOverlappedTransferBuffer(buffer);
  265. }
  266. }
  267. else if (error == WSAEDISCON)
  268. {
  269. if (IsUDPServerSocket())
  270. LOG(LogError, "Unexpected: Received WSAEDISCON on a UDP server socket!");
  271. LOG(LogError, "Socket::EnqueueNewReceivebuffer: WSAEDISCON. Connection closed in socket %s.", ToString().c_str());
  272. readOpen = false;
  273. ///\todo Should do writeOpen = false; here as well?
  274. DeleteOverlappedTransferBuffer(buffer);
  275. return;
  276. }
  277. else
  278. {
  279. if (error != WSAEWOULDBLOCK && error != 0)
  280. {
  281. LOG(LogError, "Socket::EnqueueNewReceiveBuffer: %s for overlapped socket %s failed! Error: %s.", IsUDPServerSocket() ? "WSARecvFrom" : "WSARecv", ToString().c_str(), Network::GetErrorString(error).c_str());
  282. // We never close the server socket as a reaction on any error, since an error on one client could shut down
  283. // the whole server for all clients. This check is mainly here to ignore the 10054 error (WSAECONNRESET) which
  284. // is returned when UDP clients give back a ICMP Host Unreachable message, but since there may be other
  285. // client-specific errors, we don't explicitly check for the 10054 case only.
  286. if (!IsUDPServerSocket())
  287. {
  288. LOG(LogError, "Socket::EnqueueNewReceiveBuffer: Closing down socket.", Network::GetErrorString(error).c_str());
  289. readOpen = false;
  290. writeOpen = false;
  291. Close();
  292. }
  293. }
  294. DeleteOverlappedTransferBuffer(buffer); // We failed to queue the buffer, free it up immediately to avoid leaking memory.
  295. return;
  296. }
  297. }
  298. #endif
  299. void DumpBuffer(const char *description, const char *data, int size)
  300. {
  301. printf("%s (%d bytes): ", description, size);
  302. for(int i = 0; i < min(size, 50); ++i)
  303. printf("%02X ", (unsigned int)(unsigned char)data[i]);
  304. printf("\n");
  305. }
  306. size_t Socket::Receive(char *dst, size_t maxBytes, EndPoint *endPoint)
  307. {
  308. assert(dst);
  309. assert(maxBytes > 0);
  310. if (maxBytes == 0)
  311. return 0;
  312. if (connectSocket == INVALID_SOCKET)
  313. return 0;
  314. if (!readOpen)
  315. return 0;
  316. if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. Instead the UDP server socket reads all client data.
  317. return 0; // So, if we accidentally come here to read a UDP slave socket, act as if it never received any data.
  318. if (IsUDPServerSocket())
  319. {
  320. sockaddr_in from;
  321. socklen_t fromLen = sizeof(from);
  322. int numBytesRead = recvfrom(connectSocket, dst, maxBytes, 0, (sockaddr*)&from, &fromLen);
  323. if (numBytesRead == KNET_SOCKET_ERROR)
  324. {
  325. int error = Network::GetLastError();
  326. if (error != KNET_EWOULDBLOCK && error != 0)
  327. LOG(LogError, "Socket::Receive: recvfrom failed: %s in socket %s", Network::GetErrorString(error).c_str(), ToString().c_str());
  328. return 0;
  329. }
  330. if (numBytesRead > 0)
  331. LOG(LogData, "recvfrom (%d) in socket %s", numBytesRead, ToString().c_str());
  332. if (endPoint)
  333. *endPoint = EndPoint::FromSockAddrIn(from);
  334. return numBytesRead;
  335. }
  336. // If we reach here, this socket is a tcp connection socket (server->client or client->server), or a udp client->server socket.
  337. int ret = recv(connectSocket, dst, maxBytes, 0);
  338. if (ret > 0)
  339. {
  340. LOG(LogData, "Received %d bytes of data from socket 0x%X.", ret, (unsigned int)connectSocket);
  341. return (size_t)ret;
  342. }
  343. else if (ret == 0)
  344. {
  345. LOG(LogInfo, "Socket::Receive: Received 0 bytes from network. Read-connection closed to socket %s.", ToString().c_str());
  346. readOpen = false;
  347. return 0;
  348. }
  349. else
  350. {
  351. int error = Network::GetLastError();
  352. if (error != KNET_EWOULDBLOCK && error != 0)
  353. {
  354. LOG(LogError, "Socket::Receive: recv failed in socket %s. Error %s", ToString().c_str(), Network::GetErrorString(error).c_str());
  355. // We never close the server socket as a reaction on any error, since an error on one client could shut down
  356. // the whole server for all clients. This check is mainly here to ignore the 10054 error (WSAECONNRESET) which
  357. // is returned when UDP clients give back a ICMP Host Unreachable message, but since there may be other
  358. // client-specific errors, we don't explicitly check for the 10054 case only.
  359. if (!IsUDPServerSocket())
  360. {
  361. readOpen = false;
  362. writeOpen = false;
  363. Close();
  364. }
  365. }
  366. return 0;
  367. }
  368. }
  369. bool Socket::IsOverlappedReceiveReady() const
  370. {
  371. if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. For these sockets, act as if they're never ready for reads.
  372. return false;
  373. #ifdef WIN32
  374. if (queuedReceiveBuffers.Size() == 0)
  375. return false;
  376. return Event((*queuedReceiveBuffers.Front())->overlapped.hEvent, EventWaitRead).Test();
  377. #else
  378. if (!readOpen)
  379. return false;
  380. EventArray ea;
  381. ea.AddEvent(Event(connectSocket, EventWaitRead));
  382. return ea.Wait(0) == 0;
  383. #endif
  384. }
  385. Event Socket::GetOverlappedReceiveEvent()
  386. {
  387. if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. For these sockets, return a null event that never fires.
  388. return Event();
  389. #ifdef WIN32
  390. if (readOpen)
  391. {
  392. /// Prime the receive buffers to the full capacity if they weren't so yet.
  393. const int capacityLeft = queuedReceiveBuffers.CapacityLeft();
  394. for(int i = 0; i < capacityLeft; ++i)
  395. EnqueueNewReceiveBuffer();
  396. }
  397. if (queuedReceiveBuffers.Size() == 0)
  398. return Event();
  399. OverlappedTransferBuffer *receivedData = *queuedReceiveBuffers.Front();
  400. assert(receivedData);
  401. return Event(receivedData->overlapped.hEvent, EventWaitRead);
  402. #else
  403. return Event(connectSocket, EventWaitRead);
  404. #endif
  405. }
  406. Event Socket::GetOverlappedSendEvent()
  407. {
  408. if (!writeOpen)
  409. return Event();
  410. #ifdef WIN32
  411. if (queuedSendBuffers.Size() == 0)
  412. return Event();
  413. OverlappedTransferBuffer *sentData = *queuedSendBuffers.Front();
  414. assert(sentData);
  415. return Event(sentData->overlapped.hEvent, EventWaitWrite);
  416. #else
  417. return Event(connectSocket, EventWaitWrite);
  418. #endif
  419. }
  420. OverlappedTransferBuffer *Socket::BeginReceive()
  421. {
  422. // UDP 'slave socket' is a socket descriptor on the server side that is a copy of the single UDP server listen socket.
  423. // The slave sockets don't receive data directly, but the server socket is used instead to receive data for them.
  424. if (IsUDPSlaveSocket())
  425. {
  426. #ifdef WIN32
  427. assert(queuedReceiveBuffers.Size() == 0); // We shouldn't ever have queued a single receive buffer for this Socket.
  428. #endif
  429. return 0; // If we happen to come here, act as if the socket never received any data.
  430. }
  431. #ifdef WIN32
  432. if (readOpen)
  433. {
  434. // Insert new empty receive buffers to the Overlapped Transfer receive queue until we have a full capacity queue primed.
  435. const int capacityLeft = queuedReceiveBuffers.CapacityLeft();
  436. for(int i = 0; i < capacityLeft; ++i)
  437. EnqueueNewReceiveBuffer();
  438. }
  439. if (queuedReceiveBuffers.Size() == 0)
  440. return 0;
  441. OverlappedTransferBuffer *receivedData = *queuedReceiveBuffers.Front();
  442. DWORD flags = 0;
  443. BOOL ret = WSAGetOverlappedResult(connectSocket, &receivedData->overlapped, (LPDWORD)&receivedData->bytesContains, FALSE, &flags);
  444. int error = (ret == TRUE) ? 0 : Network::GetLastError();
  445. if (ret == TRUE)
  446. {
  447. queuedReceiveBuffers.PopFront();
  448. // Successfully receiving zero bytes with overlapped sockets means the same as recv() of 0 bytes,
  449. // peer has closed the write connection (but can still recv() until we also close the write connection).
  450. if (receivedData->bytesContains == 0)
  451. {
  452. DeleteOverlappedTransferBuffer(receivedData);
  453. if (readOpen)
  454. LOG(LogInfo, "Socket::BeginReceive: Received 0 bytes from the network. Read connection closed in socket %s.", ToString().c_str());
  455. readOpen = false;
  456. if (IsUDPServerSocket())
  457. LOG(LogError, "Socket::BeginReceive: UDP server socket transitioned to readOpen==false!");
  458. return 0;
  459. }
  460. return receivedData;
  461. }
  462. else if (error == WSAEDISCON)
  463. {
  464. queuedReceiveBuffers.PopFront();
  465. DeleteOverlappedTransferBuffer(receivedData);
  466. if (readOpen || writeOpen)
  467. LOG(LogError, "Socket::BeginReceive: WSAEDISCON. Bidirectionally closing connection in socket %s.", ToString().c_str());
  468. if (IsUDPServerSocket())
  469. LOG(LogError, "Socket::BeginReceive: Unexpected: Received WSAEDISCON on UDP server socket!");
  470. Close();
  471. return 0;
  472. }
  473. else if (error != WSA_IO_INCOMPLETE)
  474. {
  475. queuedReceiveBuffers.PopFront();
  476. if (readOpen || writeOpen)
  477. if (!(IsUDPServerSocket() && error == 10054)) // If we are running both UDP server and client on localhost, we can receive 10054 (Peer closed connection) on the server side, in which case, we ignore this error print.
  478. LOG(LogError, "Socket::BeginReceive: WSAGetOverlappedResult failed with code %d when reading from an overlapped socket! Reason: %s.", error, Network::GetErrorString(error).c_str());
  479. DeleteOverlappedTransferBuffer(receivedData);
  480. // Mark this socket closed, unless the read error was on a UDP server socket, in which case we must ignore
  481. // the read error on this buffer (an error on a single client connection cannot shut down the whole server!)
  482. if (!IsUDPServerSocket() && (readOpen || writeOpen))
  483. {
  484. LOG(LogError, "Socket::BeginReceive: Closing socket due to read error!");
  485. Close();
  486. }
  487. }
  488. return 0;
  489. #else
  490. if (!readOpen)
  491. return 0;
  492. const int receiveBufferSize = 4096;
  493. OverlappedTransferBuffer *buffer = AllocateOverlappedTransferBuffer(receiveBufferSize);
  494. EndPoint source;
  495. buffer->bytesContains = Receive(buffer->buffer.buf, buffer->buffer.len, &source);
  496. if (buffer->bytesContains > 0)
  497. {
  498. buffer->fromLen = sizeof(buffer->from);
  499. buffer->from = source.ToSockAddrIn();
  500. return buffer;
  501. }
  502. else
  503. {
  504. // Did not get any data. Delete the buffer immediately.
  505. DeleteOverlappedTransferBuffer(buffer);
  506. return 0;
  507. }
  508. #endif
  509. }
  510. void Socket::EndReceive(OverlappedTransferBuffer *buffer)
  511. {
  512. #ifdef WIN32
  513. if (readOpen)
  514. {
  515. EnqueueNewReceiveBuffer(buffer);
  516. return;
  517. }
  518. #endif
  519. DeleteOverlappedTransferBuffer(buffer);
  520. }
  521. void Socket::Disconnect()
  522. {
  523. if (connectSocket == INVALID_SOCKET)
  524. return;
  525. LOG(LogVerbose, "Socket::Disconnect(), this: %p.", this);
  526. if (transport == SocketOverTCP)
  527. {
  528. int result = shutdown(connectSocket, SD_SEND);
  529. if (result == KNET_SOCKET_ERROR)
  530. LOG(LogError, "Socket::Disconnect(): TCP socket shutdown(SD_SEND) failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
  531. else
  532. LOG(LogInfo, "Socket::Disconnect(): TCP socket shutdown(SD_SEND) succeeded on socket %s.", ToString().c_str());
  533. }
  534. writeOpen = false;
  535. }
  536. void Socket::Close()
  537. {
  538. if (connectSocket == INVALID_SOCKET)
  539. {
  540. assert(!readOpen && !writeOpen);
  541. return;
  542. }
  543. LOG(LogInfo, "Socket::Close(): Closing socket %s.", ToString().c_str());
  544. if (!IsUDPSlaveSocket())
  545. {
  546. // For UDP client sockets on the server side, the same SOCKET object is shared by
  547. // all other client sockets and the UDP server socket. For those sockets, the UDP server socket is the owner
  548. // of the socket object, so the clients cannot close their sockets, as closing one would close them all.
  549. int result = shutdown(connectSocket, SD_BOTH);
  550. if (result == KNET_SOCKET_ERROR)
  551. LOG(LogError, "Socket::Close(): Socket shutdown(SD_BOTH) failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
  552. else
  553. LOG(LogInfo, "Socket::Close(): Socket shutdown(SD_BOTH) succeeded on socket %s.", ToString().c_str());
  554. result = closesocket(connectSocket);
  555. if (result == KNET_SOCKET_ERROR)
  556. LOG(LogError, "Socket::Close(): closesocket() failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
  557. }
  558. connectSocket = INVALID_SOCKET;
  559. localEndPoint.Reset();
  560. localHostName = "";
  561. remoteEndPoint.Reset();
  562. remoteHostName = "";
  563. transport = InvalidTransportLayer;
  564. type = InvalidSocketType;
  565. readOpen = false;
  566. writeOpen = false;
  567. #ifdef WIN32
  568. FreeOverlappedTransferBuffers();
  569. #endif
  570. }
  571. #ifdef WIN32
  572. void Socket::FreeOverlappedTransferBuffers()
  573. {
  574. LOG(LogVerbose, "Socket::FreeOverlappedTransferBuffers(), this: %p.", this);
  575. /// \todo Use CancelIo to tear-down commited OverlappedTransferBuffers before freeing data. http://msdn.microsoft.com/en-us/library/aa363792(VS.85).aspx
  576. while(queuedReceiveBuffers.Size() > 0)
  577. DeleteOverlappedTransferBuffer(queuedReceiveBuffers.TakeFront());
  578. while(queuedSendBuffers.Size() > 0)
  579. DeleteOverlappedTransferBuffer(queuedSendBuffers.TakeFront());
  580. }
  581. #endif
  582. void Socket::SetBlocking(bool isBlocking)
  583. {
  584. if (connectSocket == INVALID_SOCKET)
  585. return;
  586. u_long nonBlocking = (isBlocking == false) ? 1 : 0;
  587. #ifdef WIN32
  588. if (ioctlsocket(connectSocket, FIONBIO, &nonBlocking))
  589. LOG(LogError, "Socket::SetBlocking: ioctlsocket failed with error %s!", Network::GetLastErrorString().c_str());
  590. #else
  591. int flags = fcntl(connectSocket, F_GETFL, 0);
  592. fcntl(connectSocket, F_SETFL, flags | O_NONBLOCK);
  593. #endif
  594. }
  595. /// @return True on success, false otherwise.
  596. bool Socket::Send(const char *data, size_t numBytes)
  597. {
  598. if (connectSocket == INVALID_SOCKET)
  599. {
  600. LOG(LogError, "Trying to send a datagram to INVALID_SOCKET!");
  601. return false;
  602. }
  603. // Server listen sockets are *not* for sending data. They only accept incoming connections.
  604. if (type == ServerListenSocket)
  605. {
  606. LOG(LogError, "Trying to send data through a server listen socket!");
  607. return false;
  608. }
  609. if (!writeOpen)
  610. {
  611. LOG(LogError, "Trying to send data to a socket that is not open for writing!");
  612. return false;
  613. }
  614. int bytesSent = 0;
  615. // sendto() to a connected socket causes EISCONN on OSX, so avoid it for client UDP sockets
  616. if (transport == SocketOverUDP && type != ClientSocket)
  617. bytesSent = sendto(connectSocket, data, numBytes, 0, (sockaddr*)&udpPeerAddress, sizeof(udpPeerAddress));
  618. else
  619. bytesSent = send(connectSocket, data, numBytes, 0);
  620. if (bytesSent == numBytes)
  621. {
  622. LOG(LogData, "Socket::EndSend: Sent out %d bytes to socket %s.", bytesSent, ToString().c_str());
  623. return true;
  624. }
  625. else if (bytesSent > 0) // Managed to send some data, but not all bytes.
  626. {
  627. assert(transport == SocketOverTCP); // Only TCP sockets should ever succeed 'partially'.
  628. // Our Socket::Send tries to guarantee that either all or nothing of the data is sent. We don't want
  629. // to report back to the upper layer that only part of the data was successfully sent. So, try to
  630. // re-issue the remainining bytes, but now in blocking mode, so we can wait for the rest of the data to
  631. // be sent.
  632. const int socketWriteTimeout = 5000; // msecs.
  633. bool waitSuccess = WaitForSendReady(socketWriteTimeout);
  634. if (!waitSuccess)
  635. {
  636. LOG(LogError, "Socket::EndSend: Warning! Managed to only partially send out %d bytes out of %d bytes in the buffer, and socket did not transition to write-ready in the timeout period. Closing connection.",
  637. bytesSent, (int)numBytes);
  638. Close();
  639. return false;
  640. }
  641. // Recursively call back to this function to process the remainder of the data.
  642. // Since bytesSent > 0, we should be making progress at each step of recursion, so there is no
  643. // danger of crashing the stack.
  644. return Send(data+bytesSent, numBytes-bytesSent);
  645. }
  646. else // Some kind of error occurred.
  647. {
  648. int error = Network::GetLastError();
  649. if (error != KNET_EWOULDBLOCK)
  650. {
  651. LOG(LogError, "Socket::EndSend() failed! Error: %s.", Network::GetErrorString(error).c_str());
  652. if (type == ServerClientSocket && transport == SocketOverUDP)
  653. {
  654. // UDP client sockets are shared between each client (and by the server socket),
  655. // so we can't actually call close() on the socket handle. Instead, resort
  656. // to a soft close as follows.
  657. readOpen = false;
  658. writeOpen = false;
  659. }
  660. else // For all other sockets, it's ok to close (socket is not shared).
  661. Close();
  662. }
  663. return false;
  664. }
  665. }
  666. bool Socket::WaitForSendReady(int msecs)
  667. {
  668. #ifdef WIN32
  669. fd_set writeSet;
  670. FD_ZERO(&writeSet);
  671. FD_SET(connectSocket, &writeSet);
  672. TIMEVAL tv = { msecs / 1000, (msecs % 1000) * 1000 };
  673. int ret = select(0, NULL, &writeSet, NULL, &tv);
  674. return ret != KNET_SOCKET_ERROR && ret != 0;
  675. #else
  676. Event waitEvent(connectSocket, EventWaitWrite);
  677. return waitEvent.Wait(msecs);
  678. #endif
  679. }
  680. bool Socket::IsOverlappedSendReady()
  681. {
  682. if (!writeOpen)
  683. return false;
  684. #ifdef WIN32
  685. if (queuedSendBuffers.CapacityLeft() > 0)
  686. return true;
  687. OverlappedTransferBuffer *sentData = *queuedSendBuffers.Front();
  688. DWORD flags = 0;
  689. BOOL ret = WSAGetOverlappedResult(connectSocket, &sentData->overlapped, (LPDWORD)&sentData->bytesContains,
  690. FALSE, &flags);
  691. return ret == TRUE;
  692. #else
  693. EventArray ea;
  694. ea.AddEvent(Event(connectSocket, EventWaitWrite));
  695. return ea.Wait(0) == 0;
  696. #endif
  697. }
  698. OverlappedTransferBuffer *Socket::BeginSend()
  699. {
  700. if (!writeOpen)
  701. return 0;
  702. #ifdef WIN32
  703. if (queuedSendBuffers.Size() > 0)
  704. {
  705. OverlappedTransferBuffer *sentData = *queuedSendBuffers.Front();
  706. DWORD flags = 0;
  707. BOOL ret = WSAGetOverlappedResult(connectSocket, &sentData->overlapped, (LPDWORD)&sentData->bytesContains,
  708. (queuedSendBuffers.CapacityLeft() == 0) ? TRUE : FALSE, &flags);
  709. int error = (ret == TRUE) ? 0 : Network::GetLastError();
  710. if (ret == TRUE)
  711. {
  712. queuedSendBuffers.PopFront();
  713. sentData->buffer.len = maxSendSize; // This is the number of bytes that the client is allowed to fill.
  714. return sentData;
  715. }
  716. if (ret == FALSE && error != WSA_IO_INCOMPLETE)
  717. {
  718. LOG(LogError, "Socket::BeginSend: WSAGetOverlappedResult failed with an error %s, code %d != WSA_IO_INCOMPLETE!",
  719. Network::GetErrorString(error).c_str(), error);
  720. writeOpen = false;
  721. return 0;
  722. }
  723. }
  724. if (queuedSendBuffers.CapacityLeft() == 0)
  725. return 0;
  726. #endif
  727. OverlappedTransferBuffer *transfer = AllocateOverlappedTransferBuffer(maxSendSize);
  728. return transfer; ///\todo In debug mode - track this pointer.
  729. }
  730. bool Socket::EndSend(OverlappedTransferBuffer *sendBuffer)
  731. {
  732. assert(sendBuffer);
  733. if (!sendBuffer)
  734. return false;
  735. #ifdef WIN32
  736. // Clear the event flag so that the completion of WSASend can trigger this and signal us.
  737. WSAResetEvent(sendBuffer->overlapped.hEvent);
  738. unsigned long bytesSent = 0;
  739. int ret;
  740. if (transport == SocketOverUDP)
  741. ret = WSASendTo(connectSocket, &sendBuffer->buffer, 1, (LPDWORD)&bytesSent, 0, (sockaddr*)&udpPeerAddress, sizeof(udpPeerAddress), &sendBuffer->overlapped, 0);
  742. else
  743. ret = WSASend(connectSocket, &sendBuffer->buffer, 1, (LPDWORD)&bytesSent, 0, &sendBuffer->overlapped, 0);
  744. int error = (ret == 0) ? 0 : Network::GetLastError();
  745. if (ret != 0 && error != WSA_IO_PENDING)
  746. {
  747. if (error != KNET_EWOULDBLOCK)
  748. {
  749. LOG(LogError, "Socket::EndSend() failed! Error: %s.", Network::GetErrorString(error).c_str());
  750. if (!IsUDPServerSocket())
  751. writeOpen = false;
  752. }
  753. DeleteOverlappedTransferBuffer(sendBuffer);
  754. return false;
  755. }
  756. bool success = queuedSendBuffers.Insert(sendBuffer);
  757. if (!success)
  758. {
  759. LOG(LogError, "queuedSendBuffers.Insert(send); failed!");
  760. ///\todo WARNING: Deleting a buffer that is submitted to WSASend. This crashes. The alternative
  761. /// is to leak. Refactor so that the above queuedSendBuffers.Insert is tried for success before calling WSASend.
  762. DeleteOverlappedTransferBuffer(sendBuffer);
  763. return false;
  764. }
  765. return true;
  766. #elif defined(UNIX) || defined(ANDROID)
  767. bool success = Send(sendBuffer->buffer.buf, sendBuffer->buffer.len);
  768. DeleteOverlappedTransferBuffer(sendBuffer);
  769. return success;
  770. #endif
  771. }
  772. void Socket::AbortSend(OverlappedTransferBuffer *send)
  773. {
  774. if (!writeOpen)
  775. {
  776. DeleteOverlappedTransferBuffer(send);
  777. return;
  778. }
  779. #ifdef WIN32
  780. // Set the event flag so as to signal that this buffer is completed immediately.
  781. if (WSASetEvent(send->overlapped.hEvent) != TRUE)
  782. {
  783. LOG(LogError, "Socket::AbortSend: WSASetEvent failed!");
  784. DeleteOverlappedTransferBuffer(send);
  785. return;
  786. }
  787. bool success = queuedSendBuffers.Insert(send);
  788. if (!success)
  789. {
  790. LOG(LogError, "queuedSendBuffers.Insert(send); failed! AbortOverlappedSend");
  791. DeleteOverlappedTransferBuffer(send);
  792. }
  793. #else
  794. DeleteOverlappedTransferBuffer(send);
  795. #endif
  796. }
  797. std::string Socket::ToString() const
  798. {
  799. sockaddr_in addr;
  800. socklen_t namelen = sizeof(addr);
  801. int peerRet = getpeername(connectSocket, (sockaddr*)&addr, &namelen); // Note: This works only if family==INETv4
  802. EndPoint peerName = EndPoint::FromSockAddrIn(addr);
  803. int sockRet = getsockname(connectSocket, (sockaddr*)&addr, &namelen); // Note: This works only if family==INETv4
  804. EndPoint sockName = EndPoint::FromSockAddrIn(addr);
  805. char str[256];
  806. sprintf(str, "%s:%d (%s, connected=%s, readOpen: %s, writeOpen: %s, maxSendSize=%d, sock: %s, peer: %s, socket: %d, this: %p)",
  807. DestinationAddress(), (int)DestinationPort(),
  808. (transport == SocketOverTCP) ? "TCP" : (IsUDPServerSocket() ? "UDP server" : (IsUDPSlaveSocket() ? "UDP Slave" : "UDP")),
  809. Connected() ? "true" : "false", readOpen ? "true" : "false", writeOpen ? "true" : "false",
  810. (int)maxSendSize, sockRet == 0 ? sockName.ToString().c_str() : "(-)",
  811. peerRet == 0 ? peerName.ToString().c_str() : "(-)", (int)connectSocket,
  812. this);
  813. return std::string(str);
  814. }
  815. void Socket::SetNaglesAlgorithmEnabled(bool enabled)
  816. {
  817. if (connectSocket == INVALID_SOCKET)
  818. {
  819. LOG(LogError, "Socket::SetNaglesAlgorithmEnabled called for invalid socket object!");
  820. return;
  821. }
  822. if (transport != SocketOverTCP)
  823. {
  824. LOG(LogError, "Calling Socket::SetNaglesAlgorithmEnabled is only valid for TCP sockets!");
  825. return;
  826. }
  827. #ifdef WIN32
  828. BOOL nagleEnabled = enabled ? TRUE : FALSE;
  829. int ret = setsockopt(connectSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&nagleEnabled, sizeof(nagleEnabled));
  830. #else
  831. int nagleEnabled = enabled ? 1 : 0;
  832. int ret = setsockopt(connectSocket, IPPROTO_TCP, TCP_NODELAY, &nagleEnabled, sizeof(nagleEnabled));
  833. #endif
  834. if (ret != 0)
  835. LOG(LogError, "Setting TCP_NODELAY=%s for socket %d failed. Reason: %s.",
  836. enabled ? "true" : "false", (int)connectSocket, Network::GetLastErrorString().c_str());
  837. }
  838. } // ~kNet