Network.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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 Network.cpp
  12. @brief */
  13. #include <string>
  14. #include <sstream>
  15. #include <cassert>
  16. #if defined(UNIX) || defined(ANDROID)
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <errno.h>
  21. #endif
  22. #ifdef KNET_USE_BOOST
  23. #include <boost/thread/thread.hpp>
  24. #endif
  25. #include "kNet/DebugMemoryLeakCheck.h"
  26. #include "kNet/Network.h"
  27. #include "kNet/TCPMessageConnection.h"
  28. #include "kNet/UDPMessageConnection.h"
  29. #include "kNet/NetworkWorkerThread.h"
  30. #include "kNet/NetworkLogging.h"
  31. namespace kNet
  32. {
  33. const int cMaxTCPSendSize = 25 * 1024 * 1024; // For TCP sockets, there is no specific limit to send(), specify something.
  34. const int cMaxUDPSendSize = 1400;
  35. std::string Network::GetErrorString(int error)
  36. {
  37. #ifdef WIN32
  38. void *lpMsgBuf = 0;
  39. HRESULT hresult = HRESULT_FROM_WIN32(error);
  40. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  41. 0, hresult, 0 /*Default language*/, (LPTSTR) &lpMsgBuf, 0, 0);
  42. // Copy message to C++ -style string, since the data need to be freed before return.
  43. std::stringstream ss;
  44. ss << (LPCSTR)lpMsgBuf << "(" << error << ")"; ///\todo Bug: The cast to LPCSTR converts wstr -> str if UNICODE is defined, which will cut out text.
  45. LocalFree(lpMsgBuf);
  46. return ss.str();
  47. #else
  48. std::stringstream ss;
  49. ss << strerror(error) << "(" << error << ")";
  50. return ss.str();
  51. #endif
  52. }
  53. int Network::GetLastError()
  54. {
  55. #ifdef WIN32
  56. return WSAGetLastError();
  57. #else
  58. return errno;
  59. #endif
  60. }
  61. std::string Network::GetLastErrorString()
  62. {
  63. return GetErrorString(GetLastError());
  64. }
  65. std::string FormatBytes(u64 numBytes)
  66. {
  67. return FormatBytes((double)numBytes);
  68. }
  69. std::string FormatBytes(double numBytes)
  70. {
  71. char str[256];
  72. if (numBytes >= 1000.0 * 1000.0 * 1000.0)
  73. sprintf(str, "%.3f GB", (float)(numBytes / (1024.0 * 1024.0 * 1024.0)));
  74. else if (numBytes >= 1000.0 * 1000.0)
  75. sprintf(str, "%.3f MB", (float)(numBytes / (1024.0 * 1024.0)));
  76. else if (numBytes >= 200.0)
  77. sprintf(str, "%.3f KB", (float)(numBytes / 1024.0));
  78. else
  79. sprintf(str, "%.2f B", (float)numBytes);
  80. return std::string(str);
  81. }
  82. Network::Network()
  83. {
  84. #ifdef WIN32
  85. memset(&wsaData, 0, sizeof(wsaData));
  86. #endif
  87. Init();
  88. }
  89. Network::~Network()
  90. {
  91. StopServer();
  92. DeInit();
  93. }
  94. void PrintLocalIP()
  95. {
  96. char ac[80];
  97. if (gethostname(ac, sizeof(ac)) == KNET_SOCKET_ERROR)
  98. {
  99. LOG(LogError, "Error getting local host name!");
  100. return;
  101. }
  102. LOG(LogInfo, "Host name is %s", ac);
  103. struct hostent *phe = gethostbyname(ac);
  104. if (phe == 0)
  105. {
  106. LOG(LogError, "Bad host lookup.");
  107. return;
  108. }
  109. for (int i = 0; phe->h_addr_list[i] != 0; ++i)
  110. {
  111. struct in_addr addr;
  112. memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
  113. LOG(LogInfo, "Address %d: %s", i, inet_ntoa(addr)); ///\todo inet_ntoa is deprecated! doesn't handle IPv6!
  114. }
  115. }
  116. void Network::PrintAddrInfo(const addrinfo *ptr)
  117. {
  118. if (!ptr)
  119. {
  120. LOG(LogError, "Null pointer passed to Network::PrintAddrInfo!");
  121. return;
  122. }
  123. LOG(LogInfo, "\tFlags: 0x%x\n", ptr->ai_flags);
  124. LOG(LogInfo, "\tFamily: ");
  125. switch(ptr->ai_family)
  126. {
  127. case AF_UNSPEC:
  128. LOG(LogInfo, "Unspecified\n");
  129. break;
  130. case AF_INET:
  131. LOG(LogInfo, "AF_INET (IPv4)\n");
  132. break;
  133. case AF_INET6:
  134. LOG(LogInfo, "AF_INET6 (IPv6)\n");
  135. break;
  136. #ifdef WIN32
  137. case AF_NETBIOS:
  138. LOG(LogInfo, "AF_NETBIOS (NetBIOS)\n");
  139. break;
  140. #endif
  141. default:
  142. LOG(LogInfo, "Other %u\n", ptr->ai_family);
  143. break;
  144. }
  145. LOG(LogInfo, "\tSocket type: ");
  146. switch(ptr->ai_socktype)
  147. {
  148. case 0:
  149. LOG(LogInfo, "Unspecified\n");
  150. break;
  151. case SOCK_STREAM:
  152. LOG(LogInfo, "SOCK_STREAM (stream)\n");
  153. break;
  154. case SOCK_DGRAM:
  155. LOG(LogInfo, "SOCK_DGRAM (datagram) \n");
  156. break;
  157. case SOCK_RAW:
  158. LOG(LogInfo, "SOCK_RAW (raw) \n");
  159. break;
  160. case SOCK_RDM:
  161. LOG(LogInfo, "SOCK_RDM (reliable message datagram)\n");
  162. break;
  163. case SOCK_SEQPACKET:
  164. LOG(LogInfo, "SOCK_SEQPACKET (pseudo-stream packet)\n");
  165. break;
  166. default:
  167. LOG(LogInfo, "Other %u\n", ptr->ai_socktype);
  168. break;
  169. }
  170. LOG(LogInfo, "\tProtocol: ");
  171. switch(ptr->ai_protocol)
  172. {
  173. case 0:
  174. LOG(LogInfo, "Unspecified\n");
  175. break;
  176. case IPPROTO_TCP:
  177. LOG(LogInfo, "IPPROTO_TCP (TCP)\n");
  178. break;
  179. case IPPROTO_UDP:
  180. LOG(LogInfo, "IPPROTO_UDP (UDP) \n");
  181. break;
  182. default:
  183. LOG(LogInfo, "Other %u\n", ptr->ai_protocol);
  184. break;
  185. }
  186. LOG(LogInfo, "\tLength of this sockaddr: %d\n", (int)ptr->ai_addrlen);
  187. LOG(LogInfo, "\tCanonical name: %s\n", ptr->ai_canonname);
  188. char address[256];
  189. sprintf(address, "%d.%d.%d.%d",
  190. (unsigned int)(unsigned char)ptr->ai_addr->sa_data[2], (unsigned int)(unsigned char)ptr->ai_addr->sa_data[3],
  191. (unsigned int)(unsigned char)ptr->ai_addr->sa_data[4], (unsigned int)(unsigned char)ptr->ai_addr->sa_data[5]);
  192. LOG(LogInfo, "Address of this sockaddr: %s.\n", address);
  193. }
  194. void Network::PrintHostNameInfo(const char *hostname, const char *port)
  195. {
  196. addrinfo hints;
  197. //--------------------------------
  198. // Setup the hints address info structure
  199. // which is passed to the getaddrinfo() function
  200. memset(&hints, 0, sizeof(hints));
  201. hints.ai_family = AF_UNSPEC;
  202. hints.ai_socktype = SOCK_STREAM;
  203. hints.ai_protocol = IPPROTO_TCP;
  204. //--------------------------------
  205. // Call getaddrinfo(). If the call succeeds,
  206. // the result variable will hold a linked list
  207. // of addrinfo structures containing response
  208. // information
  209. addrinfo *result = NULL;
  210. unsigned long dwRetval = (unsigned long)getaddrinfo(hostname, port, &hints, &result);
  211. if (dwRetval != 0)
  212. {
  213. LOG(LogError, "getaddrinfo failed with error: %d\n", (int)dwRetval);
  214. return;
  215. }
  216. LOG(LogInfo, "getaddrinfo returned success\n");
  217. int i = 1;
  218. // Retrieve each address and print out the hex bytes
  219. for (addrinfo *ptr = result; ptr != NULL; ptr = ptr->ai_next)
  220. {
  221. LOG(LogInfo, "getaddrinfo response %d\n", i++);
  222. PrintAddrInfo(ptr);
  223. }
  224. freeaddrinfo(result);
  225. PrintLocalIP();
  226. }
  227. void Network::Init()
  228. {
  229. #ifdef WIN32
  230. // Initialize Winsock
  231. int result = WSAStartup(MAKEWORD(2,2), &wsaData);
  232. if (result != 0)
  233. {
  234. LOG(LogError, "Network::Init: WSAStartup failed: %s!", GetErrorString(result).c_str());
  235. return;
  236. }
  237. #endif
  238. // Fetch the local system host name for later use. The local address is cached here
  239. // to avoid multiple queries to namespace providers.
  240. char str[256];
  241. int ret = gethostname(str, 256); // For more information, see http://msdn.microsoft.com/en-us/library/ms738527(VS.85).aspx .
  242. if (ret == 0)
  243. {
  244. localHostName = str;
  245. LOG(LogInfo, "Network::Init successful. gethostname returned %s", str);
  246. }
  247. else
  248. {
  249. LOG(LogError, "Network::Init: gethostname failed! Error: %s. Using 'localhost' as the local host name", GetLastErrorString().c_str());
  250. localHostName = "localhost";
  251. }
  252. }
  253. NetworkWorkerThread *Network::GetOrCreateWorkerThread()
  254. {
  255. static const int maxConnectionsPerThread = 8;
  256. // Find an existing thread with sufficiently low load.
  257. for(size_t i = 0; i < workerThreads.size(); ++i)
  258. if (workerThreads[i]->NumConnections() + workerThreads[i]->NumServers() < maxConnectionsPerThread)
  259. return workerThreads[i];
  260. // No appropriate thread found. Create a new one.
  261. NetworkWorkerThread *workerThread = new NetworkWorkerThread();
  262. workerThread->StartThread();
  263. workerThreads.push_back(workerThread);
  264. LOG(LogInfo, "Created a new NetworkWorkerThread. There are now %d worker threads.", (int)workerThreads.size());
  265. return workerThread;
  266. }
  267. void Network::AssignConnectionToWorkerThread(MessageConnection *connection)
  268. {
  269. NetworkWorkerThread *workerThread = GetOrCreateWorkerThread();
  270. connection->SetWorkerThread(workerThread);
  271. workerThread->AddConnection(connection);
  272. }
  273. void Network::AssignServerToWorkerThread(NetworkServer *server)
  274. {
  275. NetworkWorkerThread *workerThread = GetOrCreateWorkerThread();
  276. server->SetWorkerThread(workerThread);
  277. workerThread->AddServer(server);
  278. }
  279. void Network::RemoveConnectionFromItsWorkerThread(MessageConnection *connection)
  280. {
  281. if (!connection)
  282. return;
  283. NetworkWorkerThread *workerThread = connection->WorkerThread();
  284. if (workerThread)
  285. {
  286. workerThread->RemoveConnection(connection);
  287. connection->SetWorkerThread(0);
  288. if (workerThread->NumConnections() + workerThread->NumServers() == 0)
  289. CloseWorkerThread(workerThread);
  290. }
  291. }
  292. void Network::RemoveServerFromItsWorkerThread(NetworkServer *server)
  293. {
  294. if (!server)
  295. return;
  296. NetworkWorkerThread *workerThread = server->WorkerThread();
  297. if (workerThread)
  298. {
  299. workerThread->RemoveServer(server);
  300. server->SetWorkerThread(0);
  301. if (workerThread->NumConnections() + workerThread->NumServers() == 0)
  302. CloseWorkerThread(workerThread);
  303. }
  304. }
  305. void Network::CloseWorkerThread(NetworkWorkerThread *workerThread)
  306. {
  307. if (!workerThread)
  308. return;
  309. // We (should) never close a worker thread until we have first removed all the connections and servers it handles.
  310. if (workerThread->NumConnections() + workerThread->NumServers() > 0)
  311. LOG(LogError, "Warning: Closing a worker thread %p when it still has %d connections and %d servers to handle.", workerThread, workerThread->NumConnections(), workerThread->NumServers());
  312. for(size_t i = 0; i < workerThreads.size(); ++i)
  313. if (workerThreads[i] == workerThread)
  314. {
  315. // Remove the thread pointer from internal list.
  316. std::swap(workerThreads[i], workerThreads[workerThreads.size()-1]);
  317. workerThreads.pop_back();
  318. workerThread->StopThread();
  319. LOG(LogInfo, "Deleted a NetworkWorkerThread. There are now %d worker threads left.", (int)workerThreads.size());
  320. delete workerThread;
  321. return;
  322. }
  323. LOG(LogError, "Network::CloseWorkerThread: Asked to close worker thread %p, but no such thread is tracked by this Network object! Ignoring the request.", workerThread);
  324. }
  325. NetworkServer *Network::StartServer(unsigned short port, SocketTransportLayer transport, INetworkServerListener *serverListener, bool allowAddressReuse)
  326. {
  327. Socket *listenSock = OpenListenSocket(port, transport, allowAddressReuse);
  328. if (listenSock == 0)
  329. {
  330. LOG(LogError, "Failed to start server. Could not open listen port to %d using %s.", (int)port,
  331. transport == SocketOverTCP ? "TCP" : "UDP");
  332. return 0;
  333. }
  334. std::vector<Socket *> listenSockets;
  335. listenSockets.push_back(listenSock);
  336. server = new NetworkServer(this, listenSockets);
  337. server->RegisterServerListener(serverListener);
  338. AssignServerToWorkerThread(server);
  339. LOG(LogInfo, "Server up (%s). Waiting for client to connect.", listenSock->ToString().c_str());
  340. return server;
  341. }
  342. NetworkServer *Network::StartServer(const std::vector<std::pair<unsigned short, SocketTransportLayer> > &listenPorts,
  343. INetworkServerListener *serverListener, bool allowAddressReuse)
  344. {
  345. if (listenPorts.size() == 0)
  346. {
  347. LOG(LogError, "Failed to start server, since you did not provide a list of ports to listen to in Network::StartServer()!");
  348. return 0;
  349. }
  350. std::vector<Socket *> listenSockets;
  351. for(size_t i = 0; i < listenPorts.size(); ++i)
  352. {
  353. Socket *listenSock = OpenListenSocket(listenPorts[i].first, listenPorts[i].second, allowAddressReuse);
  354. if (listenSock)
  355. listenSockets.push_back(listenSock);
  356. }
  357. if (listenSockets.size() == 0)
  358. {
  359. LOG(LogError, "Failed to start server. No ports to listen to!");
  360. return 0;
  361. }
  362. server = new NetworkServer(this, listenSockets);
  363. server->RegisterServerListener(serverListener);
  364. AssignServerToWorkerThread(server);
  365. LOG(LogInfo, "Server up and listening on the following ports: ");
  366. {
  367. std::stringstream ss;
  368. ss << "UDP ";
  369. for(size_t i = 0; i < listenSockets.size(); ++i)
  370. if (listenSockets[i]->TransportLayer() == SocketOverUDP)
  371. ss << listenSockets[i]->LocalPort() << " ";
  372. LOG(LogInfo, ss.str().c_str());
  373. }
  374. {
  375. std::stringstream ss;
  376. ss << "TCP ";
  377. for(size_t i = 0; i < listenSockets.size(); ++i)
  378. if (listenSockets[i]->TransportLayer() == SocketOverTCP)
  379. ss << listenSockets[i]->LocalPort() << " ";
  380. LOG(LogInfo, ss.str().c_str());
  381. }
  382. return server;
  383. }
  384. void Network::StopServer()
  385. {
  386. if (!server)
  387. return;
  388. RemoveServerFromItsWorkerThread(server);
  389. ///\todo This is a forceful stop. Perhaps have a benign teardown as well?
  390. server = 0;
  391. LOG(LogVerbose, "Network::StopServer: Deinitialized NetworkServer.");
  392. }
  393. void Network::DeleteSocket(Socket *socket)
  394. {
  395. if (!socket)
  396. {
  397. LOG(LogError, "Network::DeleteSocket() called with a null socket pointer!");
  398. return;
  399. }
  400. for(std::list<Socket>::iterator iter = sockets.begin(); iter != sockets.end(); ++iter)
  401. if (&*iter == socket)
  402. {
  403. socket->Close();
  404. // The Socket pointers MessageConnection objects have are pointers to this list,
  405. // so after calling this function with a Socket pointer, the Socket is deleted for good.
  406. sockets.erase(iter);
  407. LOG(LogInfo, "Network::DeleteSocket: Closed socket %p.", socket);
  408. return;
  409. }
  410. LOG(LogError, "Network::DeleteSocket: Tried to free a nonexisting socket %p!", socket);
  411. }
  412. void Network::CloseConnection(MessageConnection *connection)
  413. {
  414. LOG(LogVerbose, "Network::CloseConnection: Closing down connection %p.", connection);
  415. if (!connection)
  416. return;
  417. RemoveConnectionFromItsWorkerThread(connection);
  418. DeleteSocket(connection->socket);
  419. connection->socket = 0;
  420. connection->owner = 0;
  421. connection->ownerServer = 0;
  422. connections.erase(connection);
  423. }
  424. void Network::DeInit()
  425. {
  426. LOG(LogVerbose, "Network::DeInit: Closing down.");
  427. PolledTimer timer;
  428. // Kill all connections.
  429. while(connections.size() > 0)
  430. {
  431. MessageConnection *connection = *connections.begin();
  432. CloseConnection(connection); // CloseConnection erases connection from the connections list, so this loop terminates.
  433. }
  434. // Kill the server, if it's running.
  435. StopServer();
  436. // Kill all worker threads.
  437. while(workerThreads.size() > 0)
  438. CloseWorkerThread(workerThreads.front()); // Erases the item from workerThreads, so this loop terminates.
  439. // Clean up any sockets that might be remaining.
  440. while(sockets.size() > 0)
  441. {
  442. sockets.front().Close();
  443. sockets.pop_front();
  444. }
  445. // Deinitialize network subsystem.
  446. #ifdef WIN32
  447. WSACleanup();
  448. #endif
  449. LOG(LogWaits, "Network::DeInit: Deinitialized kNet Network object, took %f msecs.", timer.MSecsElapsed());
  450. }
  451. void Network::NewMessageConnectionCreated(MessageConnection *connection)
  452. {
  453. connections.insert(connection);
  454. }
  455. Socket *Network::OpenListenSocket(unsigned short port, SocketTransportLayer transport, bool allowAddressReuse)
  456. {
  457. addrinfo *result = NULL;
  458. addrinfo *ptr = NULL;
  459. addrinfo hints;
  460. memset(&hints, 0, sizeof(hints));
  461. hints.ai_family = AF_INET;
  462. hints.ai_flags = AI_PASSIVE;
  463. hints.ai_socktype = (transport == SocketOverTCP) ? SOCK_STREAM : SOCK_DGRAM;
  464. hints.ai_protocol = (transport == SocketOverTCP) ? IPPROTO_TCP : IPPROTO_UDP;
  465. char strPort[256];
  466. sprintf(strPort, "%d", (unsigned int)port);
  467. int ret = getaddrinfo(NULL, strPort, &hints, &result);
  468. if (ret != 0)
  469. {
  470. LOG(LogError, "getaddrinfo failed: %s", GetErrorString(ret).c_str());
  471. return 0;
  472. }
  473. SOCKET listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  474. LOG(LogInfo, "Network::OpenListenSocket: Created listenSocket 0x%8X.", (unsigned int)listenSocket);
  475. if (listenSocket == INVALID_SOCKET)
  476. {
  477. LOG(LogError, "Error at socket(): %s", GetLastErrorString().c_str());
  478. freeaddrinfo(result);
  479. return 0;
  480. }
  481. if (allowAddressReuse)
  482. {
  483. // Allow other sockets to be bound to this address after this.
  484. // (Possibly unsecure, only enable for development purposes - to avoid having to wait for the server listen socket
  485. // to time out if the server crashes.)
  486. #ifdef WIN32
  487. BOOL val = TRUE;
  488. ret = setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
  489. #else
  490. int val = 1;
  491. ret = setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
  492. #endif
  493. if (ret != 0)
  494. LOG(LogError, "setsockopt to SO_REUSEADDR failed: %s", GetLastErrorString().c_str());
  495. }
  496. // It is safe to cast to a sockaddr_in, since we've specifically queried for AF_INET addresses.
  497. sockaddr_in localAddress = *(sockaddr_in*)&result->ai_addr;
  498. // Setup the listening socket - bind it to a local port.
  499. // If we are setting up a TCP socket, the socket will be only for listening and accepting incoming connections.
  500. // If we are setting up an UDP socket, all connection initialization and data transfers will be managed through this socket.
  501. ret = bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
  502. if (ret == KNET_SOCKET_ERROR)
  503. {
  504. LOG(LogError, "bind failed: %s when trying to bind to port %d with transport %s",
  505. GetLastErrorString().c_str(), (int)port, transport == SocketOverTCP ? "TCP" : "UDP");
  506. closesocket(listenSocket);
  507. freeaddrinfo(result);
  508. return 0;
  509. }
  510. freeaddrinfo(result);
  511. // For a reliable TCP socket, start the server with a call to listen().
  512. if (transport == SocketOverTCP)
  513. {
  514. // Transition the bound socket to a listening state.
  515. ret = listen(listenSocket, SOMAXCONN);
  516. if (ret == KNET_SOCKET_ERROR)
  517. {
  518. LOG(LogError, "Error at listen(): %s", GetLastErrorString().c_str());
  519. closesocket(listenSocket);
  520. return 0;
  521. }
  522. }
  523. EndPoint localEndPoint = EndPoint::FromSockAddrIn(localAddress);
  524. // We are starting up a server listen socket, which is not bound to an address. Use null address for the remote endpoint.
  525. EndPoint remoteEndPoint;
  526. remoteEndPoint.Reset();
  527. const size_t maxSendSize = (transport == SocketOverTCP ? cMaxTCPSendSize : cMaxUDPSendSize);
  528. sockets.push_back(Socket(listenSocket, localEndPoint, localHostName.c_str(), remoteEndPoint, "", transport, ServerListenSocket, maxSendSize));
  529. Socket *listenSock = &sockets.back();
  530. listenSock->SetBlocking(false);
  531. return listenSock;
  532. }
  533. Socket *Network::ConnectSocket(const char *address, unsigned short port, SocketTransportLayer transport)
  534. {
  535. addrinfo *result = NULL;
  536. addrinfo *ptr = NULL;
  537. addrinfo hints;
  538. memset(&hints, 0, sizeof(hints));
  539. hints.ai_family = AF_INET;
  540. hints.ai_socktype = (transport == SocketOverTCP) ? SOCK_STREAM : SOCK_DGRAM;
  541. hints.ai_protocol = (transport == SocketOverTCP) ? IPPROTO_TCP : IPPROTO_UDP;
  542. char strPort[256];
  543. sprintf(strPort, "%d", (unsigned int)port);
  544. int ret = getaddrinfo(address, strPort, &hints, &result);
  545. if (ret != 0)
  546. {
  547. LOG(LogError, "Network::Connect: getaddrinfo failed: %s", GetErrorString(ret).c_str());
  548. return 0;
  549. }
  550. #ifdef WIN32
  551. SOCKET connectSocket = WSASocket(result->ai_family, result->ai_socktype, result->ai_protocol,
  552. NULL, 0, WSA_FLAG_OVERLAPPED);
  553. #else
  554. SOCKET connectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  555. LOG(LogInfo, "A call to socket() returned a new socket 0x%8X.", (unsigned int)connectSocket);
  556. #endif
  557. if (connectSocket == INVALID_SOCKET)
  558. {
  559. LOG(LogError, "Network::Connect: Error at socket(): %s", GetLastErrorString().c_str());
  560. freeaddrinfo(result);
  561. return 0;
  562. }
  563. // Connect to server.
  564. #ifdef WIN32
  565. ret = WSAConnect(connectSocket, result->ai_addr, (int)result->ai_addrlen, 0, 0, 0, 0);
  566. #else
  567. ret = connect(connectSocket, result->ai_addr, (int)result->ai_addrlen);
  568. #endif
  569. if (ret == KNET_SOCKET_ERROR)
  570. {
  571. closesocket(connectSocket);
  572. connectSocket = INVALID_SOCKET;
  573. }
  574. freeaddrinfo(result);
  575. if (connectSocket == INVALID_SOCKET)
  576. {
  577. LOG(LogError, "Unable to connect to server!");
  578. return 0;
  579. }
  580. EndPoint localEndPoint;
  581. sockaddr_in sockname;
  582. socklen_t socknamelen = sizeof(sockname);
  583. ret = getsockname(connectSocket, (sockaddr*)&sockname, &socknamelen);
  584. if (ret == 0)
  585. localEndPoint = EndPoint::FromSockAddrIn(sockname);
  586. else
  587. LOG(LogError, "Network::ConnectSocket: getsockname failed: %s!", Network::GetLastErrorString().c_str());
  588. EndPoint remoteEndPoint;
  589. sockaddr_in peername;
  590. socklen_t peernamelen = sizeof(peername);
  591. ret = getpeername(connectSocket, (sockaddr*)&peername, &peernamelen);
  592. if (ret == 0)
  593. remoteEndPoint = EndPoint::FromSockAddrIn(peername);
  594. else
  595. LOG(LogError, "Network::ConnectSocket: getpeername failed: %s!", Network::GetLastErrorString().c_str());
  596. std::string remoteHostName = remoteEndPoint.IPToString();
  597. const size_t maxSendSize = (transport == SocketOverTCP) ? cMaxTCPSendSize : cMaxUDPSendSize;
  598. Socket socket(connectSocket, localEndPoint, localHostName.c_str(), remoteEndPoint, remoteHostName.c_str(), transport, ClientSocket, maxSendSize);
  599. socket.SetBlocking(false);
  600. sockets.push_back(socket);
  601. Socket *sock = &sockets.back();
  602. return sock;
  603. }
  604. Ptr(MessageConnection) Network::Connect(const char *address, unsigned short port,
  605. SocketTransportLayer transport, IMessageHandler *messageHandler, Datagram *connectMessage)
  606. {
  607. Socket *socket = ConnectSocket(address, port, transport);
  608. if (!socket)
  609. return 0;
  610. if (transport == SocketOverUDP)
  611. {
  612. SendUDPConnectDatagram(*socket, connectMessage);
  613. LOG(LogInfo, "Network::Connect: Sent a UDP Connection Start datagram to to %s.", socket->ToString().c_str());
  614. }
  615. else
  616. LOG(LogInfo, "Network::Connect: Connected a TCP socket to %s.", socket->ToString().c_str());
  617. Ptr(MessageConnection) connection;
  618. if (transport == SocketOverTCP)
  619. connection = new TCPMessageConnection(this, 0, socket, ConnectionOK);
  620. else
  621. connection = new UDPMessageConnection(this, 0, socket, ConnectionPending);
  622. connection->RegisterInboundMessageHandler(messageHandler);
  623. AssignConnectionToWorkerThread(connection);
  624. connections.insert(connection);
  625. return connection;
  626. }
  627. Socket *Network::CreateUDPSlaveSocket(Socket *serverListenSocket, const EndPoint &remoteEndPoint, const char *remoteHostName)
  628. {
  629. if (!serverListenSocket)
  630. {
  631. LOG(LogError, "Network::CreateUDPSlaveSocket called with null serverListenSocket handle!");
  632. return 0;
  633. }
  634. SOCKET udpSocket = serverListenSocket->GetSocketHandle();
  635. if (udpSocket == INVALID_SOCKET)
  636. {
  637. LOG(LogError, "Network::CreateUDPSlaveSocket called with a UDP server socket with invalid internal socket handle!");
  638. return 0;
  639. }
  640. sockets.push_back(Socket(udpSocket, serverListenSocket->LocalEndPoint(),
  641. serverListenSocket->LocalAddress(), remoteEndPoint, remoteHostName, SocketOverUDP, ServerClientSocket, cMaxUDPSendSize));
  642. Socket *socket = &sockets.back();
  643. socket->SetBlocking(false);
  644. LOG(LogInfo, "Network::CreateUDPSlaveSocket: Connected an UDP socket to %s.", socket->ToString().c_str());
  645. return socket;
  646. }
  647. Socket *Network::StoreSocket(const Socket &cp)
  648. {
  649. sockets.push_back(cp);
  650. return &sockets.back();
  651. }
  652. void Network::SendUDPConnectDatagram(Socket &socket, Datagram *connectMessage)
  653. {
  654. const int connectMessageSize = connectMessage ? connectMessage->size : 8;
  655. OverlappedTransferBuffer *sendData = socket.BeginSend(connectMessageSize);
  656. if (!sendData)
  657. {
  658. LOG(LogError, "Network::SendUDPConnectDatagram: socket.BeginSend failed! Cannot send UDP connection datagram!");
  659. return;
  660. }
  661. sendData->bytesContains = connectMessageSize;
  662. if (connectMessage)
  663. {
  664. ///\todo Craft the proper connection attempt datagram.
  665. memcpy(sendData->buffer.buf, connectMessage->data, sendData->buffer.len);
  666. LOG(LogVerbose, "Network::SendUDPConnectDatagram: Sending UDP connect message of size %d.", (int)sendData->buffer.len);
  667. }
  668. else
  669. {
  670. ///\todo Craft the proper connection attempt datagram.
  671. memset(sendData->buffer.buf, 0, sendData->buffer.len);
  672. LOG(LogVerbose, "Network::SendUDPConnectDatagram: Sending null UDP connect message of size %d.", (int)sendData->buffer.len);
  673. }
  674. socket.EndSend(sendData);
  675. }
  676. } // ~kNet