platformNet.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platformNet.h"
  23. #include "platform/event.h"
  24. #include "core/strings/stringFunctions.h"
  25. #if defined (TORQUE_OS_WIN32)
  26. #define TORQUE_USE_WINSOCK
  27. #include <errno.h>
  28. #include <winsock.h>
  29. #define EINPROGRESS WSAEINPROGRESS
  30. #define ioctl ioctlsocket
  31. typedef int socklen_t;
  32. #elif defined ( TORQUE_OS_MAC )
  33. #include <unistd.h>
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <sys/poll.h>
  37. #include <arpa/inet.h>
  38. #include <netdb.h>
  39. #include <netinet/in.h>
  40. #include <errno.h>
  41. #include <sys/ioctl.h>
  42. typedef sockaddr_in SOCKADDR_IN;
  43. typedef sockaddr * PSOCKADDR;
  44. typedef sockaddr SOCKADDR;
  45. typedef in_addr IN_ADDR;
  46. #define INVALID_SOCKET -1
  47. #define SOCKET_ERROR -1
  48. #define closesocket close
  49. #elif defined TORQUE_OS_LINUX
  50. #include <unistd.h>
  51. #include <sys/types.h>
  52. #include <sys/socket.h>
  53. #include <sys/poll.h>
  54. #include <arpa/inet.h>
  55. #include <netdb.h>
  56. #include <netinet/in.h>
  57. #include <errno.h>
  58. #include <sys/ioctl.h>
  59. typedef sockaddr_in SOCKADDR_IN;
  60. typedef sockaddr * PSOCKADDR;
  61. typedef sockaddr SOCKADDR;
  62. typedef in_addr IN_ADDR;
  63. #define INVALID_SOCKET -1
  64. #define SOCKET_ERROR -1
  65. #define closesocket close
  66. #elif defined( TORQUE_OS_XENON )
  67. #include <Xtl.h>
  68. #include <string>
  69. #define TORQUE_USE_WINSOCK
  70. #define EINPROGRESS WSAEINPROGRESS
  71. #define ioctl ioctlsocket
  72. typedef int socklen_t;
  73. DWORD _getLastErrorAndClear()
  74. {
  75. DWORD err = WSAGetLastError();
  76. WSASetLastError( 0 );
  77. return err;
  78. }
  79. #else
  80. #endif
  81. #if defined(TORQUE_USE_WINSOCK)
  82. static const char* strerror_wsa( int code )
  83. {
  84. switch( code )
  85. {
  86. #define E( name ) case name: return #name;
  87. E( WSANOTINITIALISED );
  88. E( WSAENETDOWN );
  89. E( WSAEADDRINUSE );
  90. E( WSAEINPROGRESS );
  91. E( WSAEALREADY );
  92. E( WSAEADDRNOTAVAIL );
  93. E( WSAEAFNOSUPPORT );
  94. E( WSAEFAULT );
  95. E( WSAEINVAL );
  96. E( WSAEISCONN );
  97. E( WSAENETUNREACH );
  98. E( WSAEHOSTUNREACH );
  99. E( WSAENOBUFS );
  100. E( WSAENOTSOCK );
  101. E( WSAETIMEDOUT );
  102. E( WSAEWOULDBLOCK );
  103. E( WSAEACCES );
  104. #undef E
  105. default:
  106. return "Unknown";
  107. }
  108. }
  109. #endif
  110. #include "core/util/tVector.h"
  111. #include "platform/platformNetAsync.h"
  112. #include "console/console.h"
  113. #include "core/util/journal/process.h"
  114. #include "core/util/journal/journal.h"
  115. static Net::Error getLastError();
  116. static S32 defaultPort = 28000;
  117. static S32 netPort = 0;
  118. static int udpSocket = InvalidSocket;
  119. ConnectionNotifyEvent Net::smConnectionNotify;
  120. ConnectionAcceptedEvent Net::smConnectionAccept;
  121. ConnectionReceiveEvent Net::smConnectionReceive;
  122. PacketReceiveEvent Net::smPacketReceive;
  123. // local enum for socket states for polled sockets
  124. enum SocketState
  125. {
  126. InvalidState,
  127. Connected,
  128. ConnectionPending,
  129. Listening,
  130. NameLookupRequired
  131. };
  132. // the Socket structure helps us keep track of the
  133. // above states
  134. struct Socket
  135. {
  136. Socket()
  137. {
  138. fd = InvalidSocket;
  139. state = InvalidState;
  140. remoteAddr[0] = 0;
  141. remotePort = -1;
  142. }
  143. NetSocket fd;
  144. S32 state;
  145. char remoteAddr[256];
  146. S32 remotePort;
  147. };
  148. // list of polled sockets
  149. static Vector<Socket*> gPolledSockets( __FILE__, __LINE__ );
  150. static Socket* addPolledSocket(NetSocket& fd, S32 state,
  151. char* remoteAddr = NULL, S32 port = -1)
  152. {
  153. Socket* sock = new Socket();
  154. sock->fd = fd;
  155. sock->state = state;
  156. if (remoteAddr)
  157. dStrcpy(sock->remoteAddr, remoteAddr);
  158. if (port != -1)
  159. sock->remotePort = port;
  160. gPolledSockets.push_back(sock);
  161. return sock;
  162. }
  163. enum {
  164. MaxConnections = 1024,
  165. };
  166. bool netSocketWaitForWritable(NetSocket fd, S32 timeoutMs)
  167. {
  168. fd_set writefds;
  169. timeval timeout;
  170. FD_ZERO(&writefds);
  171. FD_SET( fd, &writefds );
  172. timeout.tv_sec = timeoutMs / 1000;
  173. timeout.tv_usec = ( timeoutMs % 1000 ) * 1000;
  174. if( select(fd + 1, NULL, &writefds, NULL, &timeout) > 0 )
  175. return true;
  176. return false;
  177. }
  178. static S32 initCount = 0;
  179. bool Net::init()
  180. {
  181. #if defined(TORQUE_USE_WINSOCK)
  182. if(!initCount)
  183. {
  184. #ifdef TORQUE_OS_XENON
  185. // Configure startup parameters
  186. XNetStartupParams xnsp;
  187. memset( &xnsp, 0, sizeof( xnsp ) );
  188. xnsp.cfgSizeOfStruct = sizeof( XNetStartupParams );
  189. #ifndef TORQUE_DISABLE_PC_CONNECTIVITY
  190. xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;
  191. Con::warnf("XNET_STARTUP_BYPASS_SECURITY enabled! This build can talk to PCs!");
  192. #endif
  193. AssertISV( !XNetStartup( &xnsp ), "Net::init - failed to init XNet" );
  194. #endif
  195. WSADATA stWSAData;
  196. AssertISV( !WSAStartup( 0x0101, &stWSAData ), "Net::init - failed to init WinSock!" );
  197. //logprintf("Winsock initialization %s", success ? "succeeded." : "failed!");
  198. }
  199. #endif
  200. initCount++;
  201. Process::notify(&Net::process, PROCESS_NET_ORDER);
  202. return(true);
  203. }
  204. void Net::shutdown()
  205. {
  206. Process::remove(&Net::process);
  207. while (gPolledSockets.size() > 0)
  208. closeConnectTo(gPolledSockets[0]->fd);
  209. closePort();
  210. initCount--;
  211. #if defined(TORQUE_USE_WINSOCK)
  212. if(!initCount)
  213. {
  214. WSACleanup();
  215. #ifdef TORQUE_OS_XENON
  216. XNetCleanup();
  217. #endif
  218. }
  219. #endif
  220. }
  221. Net::Error getLastError()
  222. {
  223. #if defined(TORQUE_USE_WINSOCK)
  224. S32 err = WSAGetLastError();
  225. switch(err)
  226. {
  227. case 0:
  228. return Net::NoError;
  229. case WSAEWOULDBLOCK:
  230. return Net::WouldBlock;
  231. default:
  232. return Net::UnknownError;
  233. }
  234. #else
  235. if (errno == EAGAIN)
  236. return Net::WouldBlock;
  237. if (errno == 0)
  238. return Net::NoError;
  239. return Net::UnknownError;
  240. #endif
  241. }
  242. static void netToIPSocketAddress(const NetAddress *address, struct sockaddr_in *sockAddr)
  243. {
  244. dMemset(sockAddr, 0, sizeof(struct sockaddr_in));
  245. sockAddr->sin_family = AF_INET;
  246. sockAddr->sin_port = htons(address->port);
  247. char tAddr[20];
  248. dSprintf(tAddr, 20, "%d.%d.%d.%d", address->netNum[0], address->netNum[1], address->netNum[2], address->netNum[3]);
  249. //fprintf(stdout,"netToIPSocketAddress(): %s\n",tAddr);fflush(NULL);
  250. sockAddr->sin_addr.s_addr = inet_addr(tAddr);
  251. }
  252. static void IPSocketToNetAddress(const struct sockaddr_in *sockAddr, NetAddress *address)
  253. {
  254. address->type = NetAddress::IPAddress;
  255. address->port = htons(sockAddr->sin_port);
  256. #ifndef TORQUE_OS_XENON
  257. char *tAddr;
  258. tAddr = inet_ntoa(sockAddr->sin_addr);
  259. //fprintf(stdout,"IPSocketToNetAddress(): %s\n",tAddr);fflush(NULL);
  260. U8 nets[4];
  261. nets[0] = atoi(strtok(tAddr, "."));
  262. nets[1] = atoi(strtok(NULL, "."));
  263. nets[2] = atoi(strtok(NULL, "."));
  264. nets[3] = atoi(strtok(NULL, "."));
  265. //fprintf(stdout,"0 = %d, 1 = %d, 2 = %d, 3 = %d\n", nets[0], nets[1], nets[2], nets[3]);
  266. address->netNum[0] = nets[0];
  267. address->netNum[1] = nets[1];
  268. address->netNum[2] = nets[2];
  269. address->netNum[3] = nets[3];
  270. #else
  271. address->netNum[0] = sockAddr->sin_addr.s_net;
  272. address->netNum[1] = sockAddr->sin_addr.s_host;
  273. address->netNum[2] = sockAddr->sin_addr.s_lh;
  274. address->netNum[3] = sockAddr->sin_addr.s_impno;
  275. #endif
  276. }
  277. NetSocket Net::openListenPort(U16 port)
  278. {
  279. if(Journal::IsPlaying())
  280. {
  281. U32 ret;
  282. Journal::Read(&ret);
  283. return NetSocket(ret);
  284. }
  285. NetSocket sock = openSocket();
  286. if (sock == InvalidSocket)
  287. {
  288. Con::errorf("Unable to open listen socket: %s", strerror(errno));
  289. return InvalidSocket;
  290. }
  291. if (bind(sock, port) != NoError)
  292. {
  293. Con::errorf("Unable to bind port %d: %s", port, strerror(errno));
  294. ::closesocket(sock);
  295. return InvalidSocket;
  296. }
  297. if (listen(sock, 4) != NoError)
  298. {
  299. Con::errorf("Unable to listen on port %d: %s", port, strerror(errno));
  300. ::closesocket(sock);
  301. return InvalidSocket;
  302. }
  303. setBlocking(sock, false);
  304. addPolledSocket(sock, Listening);
  305. if(Journal::IsRecording())
  306. Journal::Write(U32(sock));
  307. return sock;
  308. }
  309. NetSocket Net::openConnectTo(const char *addressString)
  310. {
  311. if(!dStrnicmp(addressString, "ipx:", 4))
  312. // ipx support deprecated
  313. return InvalidSocket;
  314. if(!dStrnicmp(addressString, "ip:", 3))
  315. addressString += 3; // eat off the ip:
  316. char remoteAddr[256];
  317. dStrcpy(remoteAddr, addressString);
  318. char *portString = dStrchr(remoteAddr, ':');
  319. U16 port;
  320. if(portString)
  321. {
  322. *portString++ = 0;
  323. port = htons(dAtoi(portString));
  324. }
  325. else
  326. port = htons(defaultPort);
  327. if(!dStricmp(remoteAddr, "broadcast"))
  328. return InvalidSocket;
  329. if(Journal::IsPlaying())
  330. {
  331. U32 ret;
  332. Journal::Read(&ret);
  333. return NetSocket(ret);
  334. }
  335. NetSocket sock = openSocket();
  336. setBlocking(sock, false);
  337. sockaddr_in ipAddr;
  338. dMemset(&ipAddr, 0, sizeof(ipAddr));
  339. ipAddr.sin_addr.s_addr = inet_addr(remoteAddr);
  340. if(ipAddr.sin_addr.s_addr != INADDR_NONE)
  341. {
  342. ipAddr.sin_port = port;
  343. ipAddr.sin_family = AF_INET;
  344. if(::connect(sock, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) == -1)
  345. {
  346. S32 err = getLastError();
  347. if(err != Net::WouldBlock)
  348. {
  349. Con::errorf("Error connecting %s: %s",
  350. addressString, strerror(err));
  351. ::closesocket(sock);
  352. sock = InvalidSocket;
  353. }
  354. }
  355. if(sock != InvalidSocket)
  356. {
  357. // add this socket to our list of polled sockets
  358. addPolledSocket(sock, ConnectionPending);
  359. }
  360. }
  361. else
  362. {
  363. // need to do an asynchronous name lookup. first, add the socket
  364. // to the polled list
  365. addPolledSocket(sock, NameLookupRequired, remoteAddr, port);
  366. // queue the lookup
  367. gNetAsync.queueLookup(remoteAddr, sock);
  368. }
  369. if(Journal::IsRecording())
  370. Journal::Write(U32(sock));
  371. return sock;
  372. }
  373. void Net::closeConnectTo(NetSocket sock)
  374. {
  375. if(Journal::IsPlaying())
  376. return;
  377. // if this socket is in the list of polled sockets, remove it
  378. for (int i = 0; i < gPolledSockets.size(); ++i)
  379. {
  380. if (gPolledSockets[i]->fd == sock)
  381. {
  382. delete gPolledSockets[i];
  383. gPolledSockets.erase(i);
  384. break;
  385. }
  386. }
  387. closeSocket(sock);
  388. }
  389. Net::Error Net::sendtoSocket(NetSocket socket, const U8 *buffer, int bufferSize)
  390. {
  391. if(Journal::IsPlaying())
  392. {
  393. U32 e;
  394. Journal::Read(&e);
  395. return (Net::Error) e;
  396. }
  397. Net::Error e = send(socket, buffer, bufferSize);
  398. if(Journal::IsRecording())
  399. Journal::Write(U32(e));
  400. return e;
  401. }
  402. bool Net::openPort(S32 port, bool doBind)
  403. {
  404. if(udpSocket != InvalidSocket)
  405. ::closesocket(udpSocket);
  406. // we turn off VDP in non-release builds because VDP does not support broadcast packets
  407. // which are required for LAN queries (PC->Xbox connectivity). The wire protocol still
  408. // uses the VDP packet structure, though.
  409. int protocol = 0;
  410. bool useVDP = false;
  411. #ifdef TORQUE_DISABLE_PC_CONNECTIVITY
  412. // Xbox uses a VDP (voice/data protocol) socket for networking
  413. protocol = IPPROTO_VDP;
  414. useVDP = true;
  415. #endif
  416. udpSocket = socket(AF_INET, SOCK_DGRAM, protocol);
  417. if(udpSocket != InvalidSocket)
  418. {
  419. Net::Error error = NoError;
  420. if (doBind)
  421. {
  422. error = bind(udpSocket, port);
  423. }
  424. if(error == NoError)
  425. error = setBufferSize(udpSocket, 32768);
  426. if(error == NoError && !useVDP)
  427. error = setBroadcast(udpSocket, true);
  428. if(error == NoError)
  429. error = setBlocking(udpSocket, false);
  430. if(error == NoError)
  431. Con::printf("UDP initialized on port %d", port);
  432. else
  433. {
  434. ::closesocket(udpSocket);
  435. udpSocket = InvalidSocket;
  436. Con::printf("Unable to initialize UDP - error %d", error);
  437. }
  438. }
  439. netPort = port;
  440. return udpSocket != InvalidSocket;
  441. }
  442. NetSocket Net::getPort()
  443. {
  444. return udpSocket;
  445. }
  446. void Net::closePort()
  447. {
  448. if(udpSocket != InvalidSocket)
  449. ::closesocket(udpSocket);
  450. }
  451. Net::Error Net::sendto(const NetAddress *address, const U8 *buffer, S32 bufferSize)
  452. {
  453. if(Journal::IsPlaying())
  454. return NoError;
  455. if(address->type == NetAddress::IPAddress)
  456. {
  457. sockaddr_in ipAddr;
  458. netToIPSocketAddress(address, &ipAddr);
  459. if(::sendto(udpSocket, (const char*)buffer, bufferSize, 0,
  460. (sockaddr *) &ipAddr, sizeof(sockaddr_in)) == SOCKET_ERROR)
  461. return getLastError();
  462. else
  463. return NoError;
  464. }
  465. else
  466. {
  467. SOCKADDR_IN ipAddr;
  468. netToIPSocketAddress(address, &ipAddr);
  469. if(::sendto(udpSocket, (const char*)buffer, bufferSize, 0,
  470. (PSOCKADDR) &ipAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
  471. return getLastError();
  472. else
  473. return NoError;
  474. }
  475. }
  476. void Net::process()
  477. {
  478. sockaddr sa;
  479. sa.sa_family = AF_UNSPEC;
  480. NetAddress srcAddress;
  481. RawData tmpBuffer;
  482. tmpBuffer.alloc(MaxPacketDataSize);
  483. for(;;)
  484. {
  485. socklen_t addrLen = sizeof(sa);
  486. S32 bytesRead = -1;
  487. if(udpSocket != InvalidSocket)
  488. bytesRead = recvfrom(udpSocket, (char *) tmpBuffer.data, MaxPacketDataSize, 0, &sa, &addrLen);
  489. if(bytesRead == -1)
  490. break;
  491. if(sa.sa_family == AF_INET)
  492. IPSocketToNetAddress((sockaddr_in *) &sa, &srcAddress);
  493. else
  494. continue;
  495. if(bytesRead <= 0)
  496. continue;
  497. if(srcAddress.type == NetAddress::IPAddress &&
  498. srcAddress.netNum[0] == 127 &&
  499. srcAddress.netNum[1] == 0 &&
  500. srcAddress.netNum[2] == 0 &&
  501. srcAddress.netNum[3] == 1 &&
  502. srcAddress.port == netPort)
  503. continue;
  504. tmpBuffer.size = bytesRead;
  505. Net::smPacketReceive.trigger(srcAddress, tmpBuffer);
  506. }
  507. // process the polled sockets. This blob of code performs functions
  508. // similar to WinsockProc in winNet.cc
  509. if (gPolledSockets.size() == 0)
  510. return;
  511. S32 optval;
  512. socklen_t optlen = sizeof(S32);
  513. S32 bytesRead;
  514. Net::Error err;
  515. bool removeSock = false;
  516. Socket *currentSock = NULL;
  517. sockaddr_in ipAddr;
  518. NetSocket incoming = InvalidSocket;
  519. char out_h_addr[1024];
  520. int out_h_length = 0;
  521. RawData readBuff;
  522. for (S32 i = 0; i < gPolledSockets.size();
  523. /* no increment, this is done at end of loop body */)
  524. {
  525. removeSock = false;
  526. currentSock = gPolledSockets[i];
  527. switch (currentSock->state)
  528. {
  529. case ::InvalidState:
  530. Con::errorf("Error, InvalidState socket in polled sockets list");
  531. break;
  532. case ::ConnectionPending:
  533. // see if it is now connected
  534. #ifdef TORQUE_OS_XENON
  535. // WSASetLastError has no return value, however part of the SO_ERROR behavior
  536. // is to clear the last error, so this needs to be done here.
  537. if( ( optval = _getLastErrorAndClear() ) == -1 )
  538. #else
  539. if (getsockopt(currentSock->fd, SOL_SOCKET, SO_ERROR,
  540. (char*)&optval, &optlen) == -1)
  541. #endif
  542. {
  543. Con::errorf("Error getting socket options: %s", strerror(errno));
  544. Net::smConnectionNotify.trigger(currentSock->fd, Net::ConnectFailed);
  545. removeSock = true;
  546. }
  547. else
  548. {
  549. if (optval == EINPROGRESS)
  550. // still connecting...
  551. break;
  552. if (optval == 0)
  553. {
  554. // poll for writable status to be sure we're connected.
  555. bool ready = netSocketWaitForWritable(currentSock->fd,0);
  556. if(!ready)
  557. break;
  558. currentSock->state = ::Connected;
  559. Net::smConnectionNotify.trigger(currentSock->fd, Net::Connected);
  560. }
  561. else
  562. {
  563. // some kind of error
  564. Con::errorf("Error connecting: %s", strerror(errno));
  565. Net::smConnectionNotify.trigger(currentSock->fd, Net::ConnectFailed);
  566. removeSock = true;
  567. }
  568. }
  569. break;
  570. case ::Connected:
  571. // try to get some data
  572. bytesRead = 0;
  573. readBuff.alloc(MaxPacketDataSize);
  574. err = Net::recv(currentSock->fd, (U8*)readBuff.data, MaxPacketDataSize, &bytesRead);
  575. if(err == Net::NoError)
  576. {
  577. if (bytesRead > 0)
  578. {
  579. // got some data, post it
  580. readBuff.size = bytesRead;
  581. Net::smConnectionReceive.trigger(currentSock->fd, readBuff);
  582. }
  583. else
  584. {
  585. // ack! this shouldn't happen
  586. if (bytesRead < 0)
  587. Con::errorf("Unexpected error on socket: %s", strerror(errno));
  588. // zero bytes read means EOF
  589. Net::smConnectionNotify.trigger(currentSock->fd, Net::Disconnected);
  590. removeSock = true;
  591. }
  592. }
  593. else if (err != Net::NoError && err != Net::WouldBlock)
  594. {
  595. Con::errorf("Error reading from socket: %s", strerror(errno));
  596. Net::smConnectionNotify.trigger(currentSock->fd, Net::Disconnected);
  597. removeSock = true;
  598. }
  599. break;
  600. case ::NameLookupRequired:
  601. // is the lookup complete?
  602. if (!gNetAsync.checkLookup(
  603. currentSock->fd, out_h_addr, &out_h_length,
  604. sizeof(out_h_addr)))
  605. break;
  606. U32 newState;
  607. if (out_h_length == -1)
  608. {
  609. Con::errorf("DNS lookup failed: %s", currentSock->remoteAddr);
  610. newState = Net::DNSFailed;
  611. removeSock = true;
  612. }
  613. else
  614. {
  615. // try to connect
  616. dMemcpy(&(ipAddr.sin_addr.s_addr), out_h_addr, out_h_length);
  617. ipAddr.sin_port = currentSock->remotePort;
  618. ipAddr.sin_family = AF_INET;
  619. if(::connect(currentSock->fd, (struct sockaddr *)&ipAddr,
  620. sizeof(ipAddr)) == -1)
  621. {
  622. int errorCode;
  623. #if defined(TORQUE_USE_WINSOCK)
  624. errorCode = WSAGetLastError();
  625. if( errorCode == WSAEINPROGRESS || errorCode == WSAEWOULDBLOCK )
  626. #else
  627. errorCode = errno;
  628. if (errno == EINPROGRESS)
  629. #endif
  630. {
  631. newState = Net::DNSResolved;
  632. currentSock->state = ::ConnectionPending;
  633. }
  634. else
  635. {
  636. const char* errorString;
  637. #if defined(TORQUE_USE_WINSOCK)
  638. errorString = strerror_wsa( errorCode );
  639. #else
  640. errorString = strerror( errorCode );
  641. #endif
  642. Con::errorf("Error connecting to %s: %s (%i)",
  643. currentSock->remoteAddr, errorString, errorCode);
  644. newState = Net::ConnectFailed;
  645. removeSock = true;
  646. }
  647. }
  648. else
  649. {
  650. newState = Net::Connected;
  651. currentSock->state = Net::Connected;
  652. }
  653. }
  654. Net::smConnectionNotify.trigger(currentSock->fd, newState);
  655. break;
  656. case ::Listening:
  657. NetAddress incomingAddy;
  658. incoming = Net::accept(currentSock->fd, &incomingAddy);
  659. if(incoming != InvalidSocket)
  660. {
  661. setBlocking(incoming, false);
  662. addPolledSocket(incoming, Connected);
  663. Net::smConnectionAccept.trigger(currentSock->fd, incoming, incomingAddy);
  664. }
  665. break;
  666. }
  667. // only increment index if we're not removing the connection, since
  668. // the removal will shift the indices down by one
  669. if (removeSock)
  670. closeConnectTo(currentSock->fd);
  671. else
  672. i++;
  673. }
  674. }
  675. NetSocket Net::openSocket()
  676. {
  677. int retSocket;
  678. retSocket = socket(AF_INET, SOCK_STREAM, 0);
  679. if(retSocket == InvalidSocket)
  680. return InvalidSocket;
  681. else
  682. return retSocket;
  683. }
  684. Net::Error Net::closeSocket(NetSocket socket)
  685. {
  686. if(socket != InvalidSocket)
  687. {
  688. if(!closesocket(socket))
  689. return NoError;
  690. else
  691. return getLastError();
  692. }
  693. else
  694. return NotASocket;
  695. }
  696. Net::Error Net::connect(NetSocket socket, const NetAddress *address)
  697. {
  698. if(address->type != NetAddress::IPAddress)
  699. return WrongProtocolType;
  700. sockaddr_in socketAddress;
  701. netToIPSocketAddress(address, &socketAddress);
  702. if(!::connect(socket, (sockaddr *) &socketAddress, sizeof(socketAddress)))
  703. return NoError;
  704. return getLastError();
  705. }
  706. Net::Error Net::listen(NetSocket socket, S32 backlog)
  707. {
  708. if(!::listen(socket, backlog))
  709. return NoError;
  710. return getLastError();
  711. }
  712. NetSocket Net::accept(NetSocket acceptSocket, NetAddress *remoteAddress)
  713. {
  714. sockaddr_in socketAddress;
  715. socklen_t addrLen = sizeof(socketAddress);
  716. int retVal = ::accept(acceptSocket, (sockaddr *) &socketAddress, &addrLen);
  717. if(retVal != InvalidSocket)
  718. {
  719. IPSocketToNetAddress(&socketAddress, remoteAddress);
  720. return retVal;
  721. }
  722. return InvalidSocket;
  723. }
  724. Net::Error Net::bind(NetSocket socket, U16 port)
  725. {
  726. S32 error;
  727. sockaddr_in socketAddress;
  728. dMemset((char *)&socketAddress, 0, sizeof(socketAddress));
  729. socketAddress.sin_family = AF_INET;
  730. // It's entirely possible that there are two NIC cards.
  731. // We let the user specify which one the server runs on.
  732. // thanks to [TPG]P1aGu3 for the name
  733. const char* serverIP = Con::getVariable( "pref::Net::BindAddress" );
  734. // serverIP is guaranteed to be non-0.
  735. AssertFatal( serverIP, "serverIP is NULL!" );
  736. if( serverIP[0] != '\0' ) {
  737. // we're not empty
  738. socketAddress.sin_addr.s_addr = inet_addr( serverIP );
  739. if( socketAddress.sin_addr.s_addr != INADDR_NONE ) {
  740. Con::printf( "Binding server port to %s", serverIP );
  741. } else {
  742. Con::warnf( ConsoleLogEntry::General,
  743. "inet_addr() failed for %s while binding!",
  744. serverIP );
  745. socketAddress.sin_addr.s_addr = INADDR_ANY;
  746. }
  747. } else {
  748. Con::printf( "Binding server port to default IP" );
  749. socketAddress.sin_addr.s_addr = INADDR_ANY;
  750. }
  751. socketAddress.sin_port = htons(port);
  752. error = ::bind(socket, (sockaddr *) &socketAddress, sizeof(socketAddress));
  753. if(!error)
  754. return NoError;
  755. return getLastError();
  756. }
  757. Net::Error Net::setBufferSize(NetSocket socket, S32 bufferSize)
  758. {
  759. S32 error;
  760. error = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *) &bufferSize, sizeof(bufferSize));
  761. if(!error)
  762. error = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &bufferSize, sizeof(bufferSize));
  763. if(!error)
  764. return NoError;
  765. return getLastError();
  766. }
  767. Net::Error Net::setBroadcast(NetSocket socket, bool broadcast)
  768. {
  769. S32 bc = broadcast;
  770. S32 error = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char*)&bc, sizeof(bc));
  771. if(!error)
  772. return NoError;
  773. return getLastError();
  774. }
  775. Net::Error Net::setBlocking(NetSocket socket, bool blockingIO)
  776. {
  777. unsigned long notblock = !blockingIO;
  778. S32 error = ioctl(socket, FIONBIO, &notblock);
  779. if(!error)
  780. return NoError;
  781. return getLastError();
  782. }
  783. Net::Error Net::send(NetSocket socket, const U8 *buffer, S32 bufferSize)
  784. {
  785. errno = 0;
  786. S32 bytesWritten = ::send(socket, (const char*)buffer, bufferSize, 0);
  787. if(bytesWritten == -1)
  788. #if defined(TORQUE_USE_WINSOCK)
  789. Con::errorf("Could not write to socket. Error: %s",strerror_wsa( WSAGetLastError() ));
  790. #else
  791. Con::errorf("Could not write to socket. Error: %s",strerror(errno));
  792. #endif
  793. return getLastError();
  794. }
  795. Net::Error Net::recv(NetSocket socket, U8 *buffer, S32 bufferSize, S32 *bytesRead)
  796. {
  797. *bytesRead = ::recv(socket, (char*)buffer, bufferSize, 0);
  798. if(*bytesRead == -1)
  799. return getLastError();
  800. return NoError;
  801. }
  802. bool Net::compareAddresses(const NetAddress *a1, const NetAddress *a2)
  803. {
  804. if((a1->type != a2->type) ||
  805. (*((U32 *)a1->netNum) != *((U32 *)a2->netNum)) ||
  806. (a1->port != a2->port))
  807. return false;
  808. if(a1->type == NetAddress::IPAddress)
  809. return true;
  810. for(S32 i = 0; i < 6; i++)
  811. if(a1->nodeNum[i] != a2->nodeNum[i])
  812. return false;
  813. return true;
  814. }
  815. bool Net::stringToAddress(const char *addressString, NetAddress *address)
  816. {
  817. if(!dStrnicmp(addressString, "ipx:", 4))
  818. // ipx support deprecated
  819. return false;
  820. if(!dStrnicmp(addressString, "ip:", 3))
  821. addressString += 3; // eat off the ip:
  822. sockaddr_in ipAddr;
  823. char remoteAddr[256];
  824. if(strlen(addressString) > 255)
  825. return false;
  826. dStrcpy(remoteAddr, addressString);
  827. char *portString = dStrchr(remoteAddr, ':');
  828. if(portString)
  829. *portString++ = '\0';
  830. if(!dStricmp(remoteAddr, "broadcast"))
  831. ipAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
  832. else
  833. {
  834. ipAddr.sin_addr.s_addr = inet_addr(remoteAddr);
  835. if (ipAddr.sin_addr.s_addr == INADDR_NONE) // error
  836. {
  837. // On the Xbox, 'gethostbyname' does not exist so...
  838. #ifndef TORQUE_OS_XENON
  839. struct hostent *hp;
  840. if((hp = gethostbyname(remoteAddr)) == 0)
  841. return false;
  842. else
  843. memcpy(&ipAddr.sin_addr.s_addr, hp->h_addr, sizeof(in_addr));
  844. #else
  845. // On the Xbox do XNetDnsLookup
  846. XNDNS *pxndns = NULL;
  847. HANDLE hEvent = CreateEvent(NULL, false, false, NULL);
  848. XNetDnsLookup(remoteAddr, hEvent, &pxndns);
  849. // Wait for event (passing NULL as a handle to XNetDnsLookup will NOT
  850. // cause it to behave synchronously, so do not remove the handle/wait
  851. while(pxndns->iStatus == WSAEINPROGRESS)
  852. WaitForSingleObject(hEvent, INFINITE);
  853. bool foundAddr = pxndns->iStatus == 0 && pxndns->cina > 0;
  854. if(foundAddr)
  855. {
  856. // Lets just grab the first address returned, for now
  857. memcpy(&ipAddr.sin_addr, pxndns->aina, sizeof(IN_ADDR));
  858. }
  859. XNetDnsRelease(pxndns);
  860. CloseHandle(hEvent);
  861. // If we didn't successfully resolve the DNS lookup, bail after the
  862. // handles are released
  863. if(!foundAddr)
  864. return false;
  865. #endif
  866. }
  867. }
  868. if(portString)
  869. ipAddr.sin_port = htons(dAtoi(portString));
  870. else
  871. ipAddr.sin_port = htons(defaultPort);
  872. ipAddr.sin_family = AF_INET;
  873. IPSocketToNetAddress(&ipAddr, address);
  874. return true;
  875. }
  876. void Net::addressToString(const NetAddress *address, char addressString[256])
  877. {
  878. if(address->type == NetAddress::IPAddress)
  879. {
  880. sockaddr_in ipAddr;
  881. netToIPSocketAddress(address, &ipAddr);
  882. if(ipAddr.sin_addr.s_addr == htonl(INADDR_BROADCAST))
  883. dSprintf(addressString, 256, "IP:Broadcast:%d", ntohs(ipAddr.sin_port));
  884. else
  885. {
  886. #ifndef TORQUE_OS_XENON
  887. dSprintf(addressString, 256, "IP:%s:%d", inet_ntoa(ipAddr.sin_addr),
  888. ntohs(ipAddr.sin_port));
  889. #else
  890. dSprintf(addressString, 256, "IP:%d.%d.%d.%d:%d", ipAddr.sin_addr.s_net,
  891. ipAddr.sin_addr.s_host, ipAddr.sin_addr.s_lh,
  892. ipAddr.sin_addr.s_impno, ntohs( ipAddr.sin_port ) );
  893. #endif
  894. }
  895. }
  896. else
  897. {
  898. *addressString = 0;
  899. return;
  900. }
  901. }