osxNetwork.mm 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 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. #import "platformOSX/platformOSX.h"
  23. #include "platform/platform.h"
  24. #include "platform/event.h"
  25. #include "platform/platformNetAsync.unix.h"
  26. #include <unistd.h>
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. #include <arpa/inet.h>
  30. #include <netdb.h>
  31. #include <netinet/in.h>
  32. #include <errno.h>
  33. #include <sys/time.h>
  34. // Header clean-up by William Taysom
  35. #include <sys/ioctl.h>
  36. // IPX fixes from William Taysom.
  37. #define IPX_NODE_LEN 6
  38. // for 10.2 compatability...
  39. #ifndef socklen_t
  40. #define socklen_t unsigned int
  41. #endif
  42. struct sockaddr_ipx
  43. {
  44. sa_family_t sipx_family;
  45. U16 sipx_port;
  46. U32 sipx_network;
  47. unsigned char sipx_node[IPX_NODE_LEN];
  48. U8 sipx_type;
  49. unsigned char sipx_zero; /* 16 byte fill */
  50. };
  51. // end wtaysom changes (May 26, 2004)
  52. #include <stdlib.h>
  53. #include "console/console.h"
  54. #include "game/gameInterface.h"
  55. #include "io/fileStream.h"
  56. #include "collection/vector.h"
  57. static Net::Error getLastError();
  58. static S32 defaultPort = 28000;
  59. static S32 netPort = 0;
  60. static int ipxSocket = InvalidSocket;
  61. static int udpSocket = InvalidSocket;
  62. // local enum for socket states for polled sockets
  63. enum SocketState
  64. {
  65. InvalidState,
  66. Connected,
  67. ConnectionPending,
  68. Listening,
  69. NameLookupRequired
  70. };
  71. // the Socket structure helps us keep track of the
  72. // above states
  73. struct Socket
  74. {
  75. Socket()
  76. {
  77. fd = InvalidSocket;
  78. state = InvalidState;
  79. remoteAddr[0] = 0;
  80. remotePort = -1;
  81. }
  82. NetSocket fd;
  83. S32 state;
  84. char remoteAddr[256];
  85. S32 remotePort;
  86. };
  87. // list of polled sockets
  88. static Vector<Socket*> gPolledSockets;
  89. static Socket* addPolledSocket(NetSocket& fd, S32 state,
  90. char* remoteAddr = NULL, S32 port = -1)
  91. {
  92. Socket* sock = new Socket();
  93. sock->fd = fd;
  94. sock->state = state;
  95. if (remoteAddr)
  96. dStrcpy(sock->remoteAddr, remoteAddr);
  97. if (port != -1)
  98. sock->remotePort = port;
  99. gPolledSockets.push_back(sock);
  100. return sock;
  101. }
  102. enum {
  103. MaxConnections = 1024,
  104. };
  105. bool netSocketWaitForWritable(NetSocket fd, S32 timeoutMs)
  106. {
  107. fd_set writefds;
  108. timeval timeout;
  109. FD_ZERO(&writefds);
  110. FD_SET( fd, &writefds );
  111. timeout.tv_sec = timeoutMs / 1000;
  112. timeout.tv_usec = ( timeoutMs % 1000 ) * 1000;
  113. if( select(fd + 1, NULL, &writefds, NULL, &timeout) > 0 )
  114. return true;
  115. return false;
  116. }
  117. bool Net::init()
  118. {
  119. Con::printSeparator();
  120. Con::printf("Network initialization:");
  121. NetAsync::startAsync();
  122. Con::printSeparator();
  123. return(true);
  124. }
  125. void Net::shutdown()
  126. {
  127. while (gPolledSockets.size() > 0)
  128. closeConnectTo(gPolledSockets[0]->fd);
  129. closePort();
  130. NetAsync::stopAsync();
  131. }
  132. static void netToIPSocketAddress(const NetAddress *address, struct sockaddr_in *sockAddr)
  133. {
  134. dMemset(sockAddr, 0, sizeof(struct sockaddr_in));
  135. sockAddr->sin_family = AF_INET;
  136. sockAddr->sin_port = htons(address->port);
  137. char tAddr[20];
  138. dSprintf(tAddr, 20, "%d.%d.%d.%d\n", address->netNum[0], address->netNum[1], address->netNum[2], address->netNum[3]);
  139. //fprintf(stdout,"netToIPSocketAddress(): %s\n",tAddr);fflush(NULL);
  140. sockAddr->sin_addr.s_addr = inet_addr(tAddr);
  141. }
  142. static void IPSocketToNetAddress(const struct sockaddr_in *sockAddr, NetAddress *address)
  143. {
  144. address->type = NetAddress::IPAddress;
  145. address->port = htons(sockAddr->sin_port);
  146. char *tAddr;
  147. tAddr = inet_ntoa(sockAddr->sin_addr);
  148. //fprintf(stdout,"IPSocketToNetAddress(): %s\n",tAddr);fflush(NULL);
  149. U8 nets[4];
  150. nets[0] = atoi(strtok(tAddr, "."));
  151. nets[1] = atoi(strtok(NULL, "."));
  152. nets[2] = atoi(strtok(NULL, "."));
  153. nets[3] = atoi(strtok(NULL, "."));
  154. //fprintf(stdout,"0 = %d, 1 = %d, 2 = %d, 3 = %d\n", nets[0], nets[1], nets[2], nets[3]);
  155. address->netNum[0] = nets[0];
  156. address->netNum[1] = nets[1];
  157. address->netNum[2] = nets[2];
  158. address->netNum[3] = nets[3];
  159. }
  160. static void netToIPXSocketAddress(const NetAddress *address, sockaddr_ipx *sockAddr)
  161. {
  162. dMemset(sockAddr, 0, sizeof(sockaddr_ipx));
  163. sockAddr->sipx_family = AF_INET;
  164. sockAddr->sipx_port = htons(address->port);
  165. sockAddr->sipx_network = address->netNum[0];
  166. sockAddr->sipx_node[0] = address->nodeNum[0];
  167. sockAddr->sipx_node[1] = address->nodeNum[1];
  168. sockAddr->sipx_node[2] = address->nodeNum[2];
  169. sockAddr->sipx_node[3] = address->nodeNum[3];
  170. sockAddr->sipx_node[4] = address->nodeNum[4];
  171. sockAddr->sipx_node[5] = address->nodeNum[5];
  172. }
  173. NetSocket Net::openListenPort(U16 port)
  174. {
  175. #ifdef TORQUE_ALLOW_JOURNALING
  176. if(Game->isJournalReading())
  177. {
  178. U32 ret;
  179. Game->journalRead(&ret);
  180. return NetSocket(ret);
  181. }
  182. #endif //TORQUE_ALLOW_JOURNALING
  183. NetSocket sock = openSocket();
  184. if (sock == InvalidSocket)
  185. {
  186. Con::errorf("Unable to open listen socket: %s", strerror(errno));
  187. return InvalidSocket;
  188. }
  189. if (bind(sock, port) != NoError)
  190. {
  191. Con::errorf("Unable to bind port %d: %s", port, strerror(errno));
  192. ::close(sock);
  193. return InvalidSocket;
  194. }
  195. if (listen(sock, 4) != NoError)
  196. {
  197. Con::errorf("Unable to listen on port %d: %s", port, strerror(errno));
  198. ::close(sock);
  199. return InvalidSocket;
  200. }
  201. setBlocking(sock, false);
  202. addPolledSocket(sock, Listening);
  203. #ifdef TORQUE_ALLOW_JOURNALING
  204. if (Game->isJournalWriting())
  205. Game->journalWrite(U32(sock));
  206. #endif //TORQUE_ALLOW_JOURNALING
  207. return sock;
  208. }
  209. NetSocket Net::openConnectTo(const char *addressString)
  210. {
  211. if(!dStrnicmp(addressString, "ipx:", 4))
  212. return InvalidSocket;
  213. if(!dStrnicmp(addressString, "ip:", 3))
  214. addressString += 3; // eat off the ip:
  215. char remoteAddr[256];
  216. dStrcpy(remoteAddr, addressString);
  217. char *portString = dStrchr(remoteAddr, ':');
  218. U16 port;
  219. if(portString)
  220. {
  221. *portString++ = 0;
  222. port = htons(dAtoi(portString));
  223. }
  224. else
  225. port = htons(defaultPort);
  226. if(!dStricmp(remoteAddr, "broadcast"))
  227. return InvalidSocket;
  228. #ifdef TORQUE_ALLOW_JOURNALING
  229. if(Game->isJournalReading())
  230. {
  231. U32 ret;
  232. Game->journalRead(&ret);
  233. return NetSocket(ret);
  234. }
  235. #endif //TORQUE_ALLOW_JOURNALING
  236. NetSocket sock = openSocket();
  237. setBlocking(sock, false);
  238. sockaddr_in ipAddr;
  239. dMemset(&ipAddr, 0, sizeof(ipAddr));
  240. if (inet_aton(remoteAddr, &ipAddr.sin_addr) != 0)
  241. {
  242. ipAddr.sin_port = port;
  243. ipAddr.sin_family = AF_INET;
  244. if(::connect(sock, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) == -1 &&
  245. errno != EINPROGRESS)
  246. {
  247. Con::errorf("Error connecting %s: %s",
  248. addressString, strerror(errno));
  249. ::close(sock);
  250. sock = InvalidSocket;
  251. }
  252. if(sock != InvalidSocket) {
  253. // add this socket to our list of polled sockets
  254. addPolledSocket(sock, ConnectionPending);
  255. }
  256. }
  257. else
  258. {
  259. // need to do an asynchronous name lookup. first, add the socket
  260. // to the polled list
  261. addPolledSocket(sock, NameLookupRequired, remoteAddr, port);
  262. // queue the lookup
  263. gNetAsync.queueLookup(remoteAddr, sock);
  264. }
  265. #ifdef TORQUE_ALLOW_JOURNALING
  266. if(Game->isJournalWriting())
  267. Game->journalWrite(U32(sock));
  268. #endif //TORQUE_ALLOW_JOURNALING
  269. return sock;
  270. }
  271. void Net::closeConnectTo(NetSocket sock)
  272. {
  273. #ifdef TORQUE_ALLOW_JOURNALING
  274. if(Game->isJournalReading())
  275. return;
  276. #endif //TORQUE_ALLOW_JOURNALING
  277. // if this socket is in the list of polled sockets, remove it
  278. for (int i = 0; i < gPolledSockets.size(); ++i)
  279. if (gPolledSockets[i]->fd == sock)
  280. {
  281. delete gPolledSockets[i];
  282. gPolledSockets.erase(i);
  283. break;
  284. }
  285. closeSocket(sock);
  286. }
  287. Net::Error Net::sendtoSocket(NetSocket socket, const U8 *buffer, int bufferSize)
  288. {
  289. #ifdef TORQUE_ALLOW_JOURNALING
  290. if(Game->isJournalReading())
  291. {
  292. U32 e;
  293. Game->journalRead(&e);
  294. return (Net::Error) e;
  295. }
  296. #endif //TORQUE_ALLOW_JOURNALING
  297. Net::Error e = send(socket, buffer, bufferSize);
  298. #ifdef TORQUE_ALLOW_JOURNALING
  299. if(Game->isJournalWriting())
  300. Game->journalWrite(U32(e));
  301. #endif //TORQUE_ALLOW_JOURNALING
  302. return e;
  303. }
  304. bool Net::openPort(S32 port)
  305. {
  306. if(udpSocket != InvalidSocket)
  307. close(udpSocket);
  308. if(ipxSocket != InvalidSocket)
  309. close(ipxSocket);
  310. udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
  311. ipxSocket = socket(AF_IPX, SOCK_DGRAM, 0);
  312. if(udpSocket != InvalidSocket)
  313. {
  314. Net::Error error;
  315. error = bind(udpSocket, port);
  316. if(error == NoError)
  317. error = setBufferSize(udpSocket, 32768);
  318. if(error == NoError)
  319. error = setBroadcast(udpSocket, true);
  320. if(error == NoError)
  321. error = setBlocking(udpSocket, false);
  322. if(error == NoError)
  323. Con::printf("UDP initialized on port %d", port);
  324. else
  325. {
  326. close(udpSocket);
  327. udpSocket = InvalidSocket;
  328. Con::printf("Unable to initialize UDP - error %d", error);
  329. }
  330. }
  331. if(ipxSocket != InvalidSocket)
  332. {
  333. Net::Error error = NoError;
  334. sockaddr_ipx ipxAddress;
  335. memset((char *)&ipxAddress, 0, sizeof(ipxAddress));
  336. ipxAddress.sipx_family = AF_IPX;
  337. ipxAddress.sipx_port = htons(port);
  338. S32 err = ::bind(ipxSocket, (struct sockaddr *)&ipxAddress, sizeof(ipxAddress));
  339. if(err)
  340. error = getLastError();
  341. if(error == NoError)
  342. error = setBufferSize(ipxSocket, 32768);
  343. if(error == NoError)
  344. error = setBroadcast(ipxSocket, true);
  345. if(error == NoError)
  346. error = setBlocking(ipxSocket, false);
  347. if(error == NoError)
  348. Con::printf("IPX initialized on port %d", port);
  349. else
  350. {
  351. close(ipxSocket);
  352. ipxSocket = InvalidSocket;
  353. Con::printf("Unable to initialize IPX - error %d", error);
  354. }
  355. }
  356. netPort = port;
  357. return ipxSocket != InvalidSocket || udpSocket != InvalidSocket;
  358. }
  359. void Net::closePort()
  360. {
  361. if(ipxSocket != InvalidSocket)
  362. close(ipxSocket);
  363. if(udpSocket != InvalidSocket)
  364. close(udpSocket);
  365. }
  366. Net::Error Net::sendto(const NetAddress *address, const U8 *buffer, S32 bufferSize)
  367. {
  368. #ifdef TORQUE_ALLOW_JOURNALING
  369. if(Game->isJournalReading())
  370. return NoError;
  371. #endif //TORQUE_ALLOW_JOURNALING
  372. if(address->type == NetAddress::IPAddress)
  373. {
  374. sockaddr_in ipAddr;
  375. netToIPSocketAddress(address, &ipAddr);
  376. if(::sendto(udpSocket, (const char*)buffer, bufferSize, 0,
  377. (sockaddr *) &ipAddr, sizeof(sockaddr_in)) == -1)
  378. return getLastError();
  379. else
  380. return NoError;
  381. }
  382. // Reached the end of the function unexpectedly
  383. return UnknownError;
  384. }
  385. void Net::process()
  386. {
  387. sockaddr sa;
  388. PacketReceiveEvent receiveEvent;
  389. for(;;)
  390. {
  391. U32 addrLen = sizeof(sa);
  392. S32 bytesRead = -1;
  393. if(udpSocket != InvalidSocket)
  394. bytesRead = recvfrom(udpSocket, (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
  395. if(bytesRead == -1 && ipxSocket != InvalidSocket)
  396. {
  397. addrLen = sizeof(sa);
  398. bytesRead = recvfrom(ipxSocket, (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
  399. }
  400. if(bytesRead == -1)
  401. break;
  402. if(sa.sa_family == AF_INET)
  403. IPSocketToNetAddress((sockaddr_in *) &sa, &receiveEvent.sourceAddress);
  404. else
  405. continue;
  406. NetAddress &na = receiveEvent.sourceAddress;
  407. if(na.type == NetAddress::IPAddress &&
  408. na.netNum[0] == 127 &&
  409. na.netNum[1] == 0 &&
  410. na.netNum[2] == 0 &&
  411. na.netNum[3] == 1 &&
  412. na.port == netPort)
  413. continue;
  414. if(bytesRead <= 0)
  415. continue;
  416. receiveEvent.size = PacketReceiveEventHeaderSize + bytesRead;
  417. Game->postEvent(receiveEvent);
  418. }
  419. // process the polled sockets. This blob of code performs functions
  420. // similar to WinsockProc in winNet.cc
  421. if (gPolledSockets.size() == 0)
  422. return;
  423. static ConnectedNotifyEvent notifyEvent;
  424. static ConnectedAcceptEvent acceptEvent;
  425. static ConnectedReceiveEvent cReceiveEvent;
  426. S32 optval;
  427. socklen_t optlen = sizeof(S32);
  428. S32 bytesRead;
  429. Net::Error err;
  430. bool removeSock = false;
  431. Socket *currentSock = NULL;
  432. sockaddr_in ipAddr;
  433. NetSocket incoming = InvalidSocket;
  434. char out_h_addr[1024];
  435. int out_h_length = 0;
  436. for (S32 i = 0; i < gPolledSockets.size();
  437. /* no increment, this is done at end of loop body */)
  438. {
  439. removeSock = false;
  440. currentSock = gPolledSockets[i];
  441. switch (currentSock->state)
  442. {
  443. case InvalidState:
  444. Con::errorf("Error, InvalidState socket in polled sockets list");
  445. break;
  446. case ConnectionPending:
  447. notifyEvent.tag = currentSock->fd;
  448. // see if it is now connected
  449. if (getsockopt(currentSock->fd, SOL_SOCKET, SO_ERROR,
  450. &optval, &optlen) == -1)
  451. {
  452. Con::errorf("Error getting socket options: %s", strerror(errno));
  453. notifyEvent.state = ConnectedNotifyEvent::ConnectFailed;
  454. Game->postEvent(notifyEvent);
  455. removeSock = true;
  456. }
  457. else
  458. {
  459. if (optval == EINPROGRESS)
  460. // still connecting...
  461. break;
  462. if (optval == 0)
  463. {
  464. // poll for writable status to be sure we're connected.
  465. bool ready = netSocketWaitForWritable(currentSock->fd,0);
  466. if(!ready)
  467. break;
  468. // connected.
  469. notifyEvent.state = ConnectedNotifyEvent::Connected;
  470. Game->postEvent(notifyEvent);
  471. currentSock->state = Connected;
  472. }
  473. else
  474. {
  475. // some kind of error
  476. Con::errorf("Error connecting: %s", strerror(errno));
  477. notifyEvent.state = ConnectedNotifyEvent::ConnectFailed;
  478. Game->postEvent(notifyEvent);
  479. removeSock = true;
  480. }
  481. }
  482. break;
  483. case Connected:
  484. bytesRead = 0;
  485. // try to get some data
  486. err = Net::recv(currentSock->fd, cReceiveEvent.data, MaxPacketDataSize, &bytesRead);
  487. if(err == Net::NoError)
  488. {
  489. if (bytesRead > 0)
  490. {
  491. // got some data, post it
  492. cReceiveEvent.tag = currentSock->fd;
  493. cReceiveEvent.size = ConnectedReceiveEventHeaderSize +
  494. bytesRead;
  495. Game->postEvent(cReceiveEvent);
  496. }
  497. else
  498. {
  499. // zero bytes read means EOF
  500. if (bytesRead < 0)
  501. // ack! this shouldn't happen
  502. Con::errorf("Unexpected error on socket: %s",
  503. strerror(errno));
  504. notifyEvent.tag = currentSock->fd;
  505. notifyEvent.state = ConnectedNotifyEvent::Disconnected;
  506. Game->postEvent(notifyEvent);
  507. removeSock = true;
  508. }
  509. }
  510. else if (err != Net::NoError && err != Net::WouldBlock)
  511. {
  512. Con::errorf("Error reading from socket: %s", strerror(errno));
  513. notifyEvent.tag = currentSock->fd;
  514. notifyEvent.state = ConnectedNotifyEvent::Disconnected;
  515. Game->postEvent(notifyEvent);
  516. removeSock = true;
  517. }
  518. break;
  519. case NameLookupRequired:
  520. // is the lookup complete?
  521. if (!gNetAsync.checkLookup(
  522. currentSock->fd, out_h_addr, &out_h_length,
  523. sizeof(out_h_addr)))
  524. break;
  525. notifyEvent.tag = currentSock->fd;
  526. if (out_h_length == -1)
  527. {
  528. Con::errorf("DNS lookup failed: %s", currentSock->remoteAddr);
  529. notifyEvent.state = ConnectedNotifyEvent::DNSFailed;
  530. removeSock = true;
  531. }
  532. else
  533. {
  534. // try to connect
  535. dMemcpy(&(ipAddr.sin_addr.s_addr), out_h_addr, out_h_length);
  536. ipAddr.sin_port = currentSock->remotePort;
  537. ipAddr.sin_family = AF_INET;
  538. if(::connect(currentSock->fd, (struct sockaddr *)&ipAddr,
  539. sizeof(ipAddr)) == -1)
  540. {
  541. if (errno == EINPROGRESS)
  542. {
  543. notifyEvent.state = ConnectedNotifyEvent::DNSResolved;
  544. currentSock->state = ConnectionPending;
  545. }
  546. else
  547. {
  548. Con::errorf("Error connecting to %s: %s",
  549. currentSock->remoteAddr, strerror(errno));
  550. notifyEvent.state = ConnectedNotifyEvent::ConnectFailed;
  551. removeSock = true;
  552. }
  553. }
  554. else
  555. {
  556. notifyEvent.state = ConnectedNotifyEvent::Connected;
  557. currentSock->state = Connected;
  558. }
  559. }
  560. Game->postEvent(notifyEvent);
  561. break;
  562. case Listening:
  563. incoming =
  564. Net::accept(currentSock->fd, &acceptEvent.address);
  565. if(incoming != InvalidSocket)
  566. {
  567. acceptEvent.portTag = currentSock->fd;
  568. acceptEvent.connectionTag = incoming;
  569. setBlocking(incoming, false);
  570. addPolledSocket(incoming, Connected);
  571. Game->postEvent(acceptEvent);
  572. }
  573. break;
  574. }
  575. // only increment index if we're not removing the connection, since
  576. // the removal will shift the indices down by one
  577. if (removeSock)
  578. closeConnectTo(currentSock->fd);
  579. else
  580. i++;
  581. }
  582. }
  583. NetSocket Net::openSocket()
  584. {
  585. int retSocket;
  586. retSocket = socket(AF_INET, SOCK_STREAM, 0);
  587. if(retSocket == InvalidSocket)
  588. return InvalidSocket;
  589. else
  590. return retSocket;
  591. }
  592. Net::Error Net::closeSocket(NetSocket socket)
  593. {
  594. if(socket != InvalidSocket)
  595. {
  596. // if we're quitting, allow the OS to close the sockets.
  597. // this is here to work around a bug in close().
  598. osxPlatState * platState = [osxPlatState sharedPlatState];
  599. if(platState.quit)
  600. return NoError;
  601. if(!close(socket))
  602. return NoError;
  603. else
  604. return getLastError();
  605. }
  606. else
  607. return NotASocket;
  608. }
  609. Net::Error Net::connect(NetSocket socket, const NetAddress *address)
  610. {
  611. if(address->type != NetAddress::IPAddress)
  612. return WrongProtocolType;
  613. sockaddr_in socketAddress;
  614. netToIPSocketAddress(address, &socketAddress);
  615. if(!::connect(socket, (sockaddr *) &socketAddress, sizeof(socketAddress)))
  616. return NoError;
  617. return getLastError();
  618. }
  619. Net::Error Net::listen(NetSocket socket, S32 backlog)
  620. {
  621. if(!::listen(socket, backlog))
  622. return NoError;
  623. return getLastError();
  624. }
  625. NetSocket Net::accept(NetSocket acceptSocket, NetAddress *remoteAddress)
  626. {
  627. sockaddr_in socketAddress;
  628. U32 addrLen = sizeof(socketAddress);
  629. int retVal = ::accept(acceptSocket, (sockaddr *) &socketAddress, &addrLen);
  630. if(retVal != InvalidSocket)
  631. {
  632. IPSocketToNetAddress(&socketAddress, remoteAddress);
  633. return retVal;
  634. }
  635. return InvalidSocket;
  636. }
  637. Net::Error Net::bind(NetSocket socket, U16 port)
  638. {
  639. S32 error;
  640. sockaddr_in socketAddress;
  641. dMemset((char *)&socketAddress, 0, sizeof(socketAddress));
  642. socketAddress.sin_family = AF_INET;
  643. // It's entirely possible that there are two NIC cards.
  644. // We let the user specify which one the server runs on.
  645. // thanks to [TPG]P1aGu3 for the name
  646. const char* serverIP = Con::getVariable( "Pref::Net::BindAddress" );
  647. // serverIP is guaranteed to be non-0.
  648. AssertFatal( serverIP, "serverIP is NULL!" );
  649. if( serverIP[0] != '\0' ) {
  650. // we're not empty
  651. socketAddress.sin_addr.s_addr = inet_addr( serverIP );
  652. if( socketAddress.sin_addr.s_addr != INADDR_NONE ) {
  653. Con::printf( "Binding server port to %s", serverIP );
  654. } else {
  655. Con::warnf( ConsoleLogEntry::General,
  656. "inet_addr() failed for %s while binding!",
  657. serverIP );
  658. socketAddress.sin_addr.s_addr = INADDR_ANY;
  659. }
  660. } else {
  661. Con::printf( "Binding server port to default IP" );
  662. socketAddress.sin_addr.s_addr = INADDR_ANY;
  663. }
  664. socketAddress.sin_port = htons(port);
  665. error = ::bind(socket, (sockaddr *) &socketAddress, sizeof(socketAddress));
  666. if(!error)
  667. return NoError;
  668. return getLastError();
  669. }
  670. Net::Error Net::setBufferSize(NetSocket socket, S32 bufferSize)
  671. {
  672. S32 error;
  673. error = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *) &bufferSize, sizeof(bufferSize));
  674. if(!error)
  675. error = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &bufferSize, sizeof(bufferSize));
  676. if(!error)
  677. return NoError;
  678. return getLastError();
  679. }
  680. Net::Error Net::setBroadcast(NetSocket socket, bool broadcast)
  681. {
  682. S32 bc = broadcast;
  683. S32 error = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char*)&bc, sizeof(bc));
  684. if(!error)
  685. return NoError;
  686. return getLastError();
  687. }
  688. Net::Error Net::setBlocking(NetSocket socket, bool blockingIO)
  689. {
  690. int notblock = !blockingIO;
  691. S32 error = ioctl(socket, FIONBIO, &notblock);
  692. if(!error)
  693. return NoError;
  694. return getLastError();
  695. }
  696. Net::Error Net::send(NetSocket socket, const U8 *buffer, S32 bufferSize)
  697. {
  698. errno = 0;
  699. S32 bytesWritten = ::send(socket, (const char*)buffer, bufferSize, 0);
  700. if(bytesWritten == -1)
  701. Con::errorf("Could not write to socket. Error: %s",strerror(errno));
  702. return getLastError();
  703. }
  704. Net::Error Net::recv(NetSocket socket, U8 *buffer, S32 bufferSize, S32 *bytesRead)
  705. {
  706. *bytesRead = ::recv(socket, (char*)buffer, bufferSize, 0);
  707. if(*bytesRead == -1)
  708. return getLastError();
  709. return NoError;
  710. }
  711. bool Net::compareAddresses(const NetAddress *a1, const NetAddress *a2)
  712. {
  713. if((a1->type != a2->type) ||
  714. (*((U32 *)a1->netNum) != *((U32 *)a2->netNum)) ||
  715. (a1->port != a2->port))
  716. return false;
  717. if(a1->type == NetAddress::IPAddress)
  718. return true;
  719. for(S32 i = 0; i < 6; i++)
  720. if(a1->nodeNum[i] != a2->nodeNum[i])
  721. return false;
  722. return true;
  723. }
  724. bool Net::stringToAddress(const char *addressString, NetAddress *address)
  725. {
  726. // assume IP if it doesn't have ipx: at the front.
  727. if(!dStrnicmp(addressString, "ip:", 3))
  728. addressString += 3; // eat off the ip:
  729. sockaddr_in ipAddr;
  730. char remoteAddr[256];
  731. if(strlen(addressString) > 255)
  732. return false;
  733. dStrcpy(remoteAddr, addressString);
  734. char *portString = dStrchr(remoteAddr, ':');
  735. if(portString)
  736. *portString++ = '\0';
  737. struct hostent *hp;
  738. if(!dStricmp(remoteAddr, "broadcast"))
  739. ipAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
  740. else
  741. {
  742. if (inet_aton(remoteAddr,&ipAddr.sin_addr) == 0) // error
  743. {
  744. if((hp = gethostbyname(remoteAddr)) == 0)
  745. return false;
  746. else
  747. memcpy(&ipAddr.sin_addr.s_addr, hp->h_addr, sizeof(in_addr));
  748. }
  749. }
  750. if(portString)
  751. ipAddr.sin_port = htons(dAtoi(portString));
  752. else
  753. ipAddr.sin_port = htons(defaultPort);
  754. ipAddr.sin_family = AF_INET;
  755. IPSocketToNetAddress(&ipAddr, address);
  756. return true;
  757. }
  758. void Net::addressToString(const NetAddress *address, char addressString[256])
  759. {
  760. if(address->type == NetAddress::IPAddress)
  761. {
  762. sockaddr_in ipAddr;
  763. netToIPSocketAddress(address, &ipAddr);
  764. if(ipAddr.sin_addr.s_addr == htonl(INADDR_BROADCAST))
  765. dSprintf(addressString, 256, "IP:Broadcast:%d", ntohs(ipAddr.sin_port));
  766. else
  767. dSprintf(addressString, 256, "IP:%s:%d", inet_ntoa(ipAddr.sin_addr),
  768. ntohs(ipAddr.sin_port));
  769. // dSprintf(addressString, 256, "IP:%d:%d", ipAddr.sin_addr.s_addr,
  770. // ntohs(ipAddr.sin_port));
  771. }
  772. else
  773. {
  774. return;
  775. dSprintf(addressString, 256, "IPX:%.2X%.2X%.2X%.2X:%.2X%.2X%.2X%.2X%.2X%.2X:%d",
  776. address->netNum[0], address->netNum[1], address->netNum[2], address->netNum[3],
  777. address->nodeNum[0], address->nodeNum[1], address->nodeNum[2], address->nodeNum[3], address->nodeNum[4], address->nodeNum[5],
  778. address->port);
  779. }
  780. }
  781. Net::Error getLastError()
  782. {
  783. if (errno == EAGAIN)
  784. return Net::WouldBlock;
  785. if (errno == 0)
  786. return Net::NoError;
  787. return Net::UnknownError;
  788. }