Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Network.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*================================================================
  3. *
  4. * Project : UnRaider
  5. * Author : Terry 'Mongoose' Hendrix II
  6. * Website : http://www.westga.edu/~stu7440/
  7. * Email : stu7440@westga.edu
  8. * Object : Network
  9. * License : No use w/o permission (C) 2002 Mongoose
  10. * Comments:
  11. *
  12. *
  13. * This file was generated using Mongoose's C++
  14. * template generator script. <stu7440@westga.edu>
  15. *
  16. *-- History -------------------------------------------------
  17. *
  18. * 2002.06.21:
  19. * Mongoose - Created
  20. =================================================================*/
  21. #include "Network.h"
  22. #include <unistd.h>
  23. #include <signal.h>
  24. #include <string.h>
  25. #include <time.h>
  26. #include <sys/time.h>
  27. #include <errno.h>
  28. #include <strings.h>
  29. #include <stdio.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <netdb.h>
  34. #include <arpa/inet.h>
  35. #include <stdlib.h>
  36. //#define LOCAL_BCAST
  37. #define NETWORK_RELIABLE
  38. #define MAX_CLIENTS 32
  39. typedef struct client_s
  40. {
  41. unsigned int uid;
  42. char active;
  43. unsigned int seq;
  44. unsigned int frameExpected;
  45. } client_t;
  46. #ifdef USING_PTHREADS
  47. # include <pthread.h>
  48. pthread_t gPThreadId[3];
  49. #endif
  50. unsigned int gUID;
  51. client_t gClients[MAX_CLIENTS];
  52. unsigned int gNumClients = 0;
  53. network_frame_t gPiggyBack;
  54. ////////////////////////////////////////////////////////////
  55. // Constructors
  56. ////////////////////////////////////////////////////////////
  57. Network *Network::mInstance = 0x0;
  58. Network *Network::Instance()
  59. {
  60. if (mInstance == 0x0)
  61. {
  62. mInstance = new Network();
  63. }
  64. return mInstance;
  65. }
  66. void killNetworkSingleton()
  67. {
  68. printf("Shutting down Network...\n");
  69. // Requires public deconstructor
  70. delete Network::Instance();
  71. }
  72. Network::Network()
  73. {
  74. strncpy(mRemoteHost, "localhost", REMOTE_HOST_STR_SZ);
  75. memset(mBindHost, 0, BIND_HOST_STR_SZ);
  76. setPort(8080);
  77. mPiggyBack = true;
  78. mNetworkReliable = true;
  79. mSpawnedClient = false;
  80. mSpawnedServer = false;
  81. mKillClient = false;
  82. mKillServer = false;
  83. mDebug = false;
  84. gUID = getUID();
  85. printf("UID %u\n", gUID);
  86. for (gNumClients = MAX_CLIENTS; gNumClients > 0;)
  87. {
  88. --gNumClients;
  89. gClients[gNumClients].active = 0;
  90. gClients[gNumClients].uid = 0;
  91. gClients[gNumClients].seq = 0;
  92. }
  93. }
  94. Network::~Network()
  95. {
  96. killServerThread();
  97. killClientThread();
  98. }
  99. ////////////////////////////////////////////////////////////
  100. // Public Accessors
  101. ////////////////////////////////////////////////////////////
  102. network_frame_t &Network::getPiggyBack()
  103. {
  104. return gPiggyBack;
  105. }
  106. unsigned int Network::getUID()
  107. {
  108. struct timeval tv;
  109. struct timezone tz;
  110. gettimeofday(&tv, &tz);
  111. srand(tv.tv_usec);
  112. return ((unsigned int)(tv.tv_sec * getRandom(2.0, 3.3) -
  113. tv.tv_sec * getRandom(1.0, 2.0)) +
  114. (unsigned int)(tv.tv_usec * getRandom(2.0, 3.3) -
  115. tv.tv_usec * getRandom(1.0, 2.0)) +
  116. (unsigned int)getRandom(666.0, 5000.0));
  117. }
  118. float Network::getRandom(float from, float to)
  119. {
  120. return from + (to*rand()/(RAND_MAX+1.0));
  121. }
  122. int Network::getPort()
  123. {
  124. return mPort;
  125. }
  126. ////////////////////////////////////////////////////////////
  127. // Public Mutators
  128. ////////////////////////////////////////////////////////////
  129. void *client_thread(void *v)
  130. {
  131. Network &network = *Network::Instance();
  132. network.runClient();
  133. return NULL;
  134. }
  135. void *server_thread(void *v)
  136. {
  137. Network &network = *Network::Instance();
  138. network.runServer();
  139. return NULL;
  140. }
  141. void Network::setBindHost(char *s)
  142. {
  143. if (!s && !s[0])
  144. return;
  145. strncpy(mBindHost, s, BIND_HOST_STR_SZ);
  146. }
  147. void Network::setRemoteHost(char *s)
  148. {
  149. if (!s && !s[0])
  150. return;
  151. strncpy(mRemoteHost, s, REMOTE_HOST_STR_SZ);
  152. }
  153. void Network::setDebug(bool toggle)
  154. {
  155. mDebug = toggle;
  156. }
  157. void Network::setPort(unsigned int port)
  158. {
  159. mPort = port;
  160. }
  161. void Network::killServerThread()
  162. {
  163. mKillServer = true;
  164. // Remember for mutex
  165. // while (mKillServer)
  166. // {
  167. // }
  168. mSpawnedServer = false;
  169. }
  170. void Network::killClientThread()
  171. {
  172. mKillClient = true;
  173. // Remember for mutex
  174. // while (mKillClient)
  175. // {
  176. // }
  177. mSpawnedClient = false;
  178. }
  179. void Network::spawnServerThread()
  180. {
  181. // For now don't handle shutting down server to start client and vv
  182. if (!mSpawnedServer && !mSpawnedClient)
  183. {
  184. #ifdef USING_PTHREADS
  185. pthread_create(gPThreadId + 0, 0, server_thread, NULL);
  186. #else
  187. printf("Network::spawnServerThread> Build doesn't support threads\n");
  188. #endif
  189. mSpawnedServer = true;
  190. }
  191. }
  192. void Network::spawnClientThread()
  193. {
  194. // For now don't handle shutting down server to start client and vv
  195. if (!mSpawnedServer && !mSpawnedClient)
  196. {
  197. #ifdef USING_PTHREADS
  198. pthread_create(gPThreadId + 1, 0, client_thread, NULL);
  199. #else
  200. printf("Network::spawnClientThread> Build doesn't support threads\n");
  201. #endif
  202. mSpawnedClient = true;
  203. }
  204. }
  205. ////////////////////////////////////////////////////////////
  206. // Protected Mutators
  207. ////////////////////////////////////////////////////////////
  208. int Network::runServer()
  209. {
  210. unsigned int fsize;
  211. int socket_fd, cc, cip;
  212. struct sockaddr_in s_in, from;
  213. char hostid[64];
  214. network_frame_t f;
  215. unsigned int i;
  216. unsigned int packetsRecieved = 0;
  217. socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  218. if (socket_fd < 0)
  219. {
  220. perror("recv_udp:socket");
  221. return -1;
  222. }
  223. if (mBindHost[0])
  224. {
  225. strncpy(hostid, mBindHost, 64);
  226. }
  227. else
  228. {
  229. if (gethostname(hostid, 64) < 0)
  230. {
  231. perror("Server: recv_udp:gethostname");
  232. return -1;
  233. }
  234. printf("Server: gethostname returned '%s'\n", hostid);
  235. fflush(stdout);
  236. }
  237. // Setup for port binding
  238. memset(&s_in, 0, sizeof(s_in));
  239. s_in.sin_family = AF_INET;
  240. #ifdef LOCAL_BCAST
  241. struct hostent *hostptr;
  242. if ((hostptr = gethostbyname(hostid)) == NULL)
  243. {
  244. fprintf(stderr, "Server: recv_udp, Invalid host name '%s'\n", hostid);
  245. return -1;
  246. }
  247. memcpy((void *)(&s_in.sin_addr), hostptr->h_addr, hostptr->h_length);
  248. #else
  249. s_in.sin_addr.s_addr = htonl(INADDR_ANY);
  250. #endif
  251. int port = getPort();
  252. s_in.sin_port = htons(port); // htons new
  253. fflush(stdout);
  254. // Bind
  255. while (bind(socket_fd, (struct sockaddr *)&s_in, sizeof(s_in)) < 0)
  256. {
  257. if (s_in.sin_port++ > (port + 10))
  258. {
  259. perror("Server: recv_udp:bind exhausted");
  260. return -1;
  261. }
  262. }
  263. cip = ntohl(s_in.sin_addr.s_addr);
  264. printf("Server: Started on ( %i.%i.%i.%i:%i )\n",
  265. cip >> 24, cip << 8 >> 24,
  266. cip << 16 >> 24, cip << 24 >> 24, s_in.sin_port);
  267. for (; !mKillClient;)
  268. {
  269. fsize = sizeof(from);
  270. // 1. Wait for event
  271. // 2. Get inbound frame
  272. cc = recvfrom(socket_fd, &f, sizeof(network_frame_t), 0,
  273. (struct sockaddr *)&from, &fsize);
  274. if (cc < 0)
  275. {
  276. perror("Server: recv_udp:recvfrom");
  277. continue;
  278. }
  279. ++packetsRecieved;
  280. if (mDebug)
  281. {
  282. printf("=====================================================\n");
  283. printf("Packet %i\n", packetsRecieved);
  284. printf("Server: Recieved packet from %u\n",
  285. f.uid);
  286. }
  287. // A. Look and see if this client has connected before
  288. for (i = 0; i < gNumClients; ++i)
  289. {
  290. if (gClients[i].uid == f.uid)
  291. {
  292. break;
  293. }
  294. }
  295. // B. Collect client data if it's a new connection
  296. if (!gClients[i].active)
  297. {
  298. for (i = 0; i < gNumClients+1; ++i)
  299. {
  300. if ((i + 1) < MAX_CLIENTS && !gClients[i].active)
  301. {
  302. gClients[i].uid = f.uid;
  303. gClients[i].active = 1;
  304. gClients[i].frameExpected = 0;
  305. ++gNumClients;
  306. printf("Server: %u made connection, as client %i\n",
  307. gClients[i].uid, i);
  308. break;
  309. }
  310. }
  311. if (i == MAX_CLIENTS || !gClients[i].active)
  312. {
  313. if (mDebug)
  314. {
  315. printf("Server: Handshake packet from %u failed?\n",
  316. f.uid);
  317. }
  318. continue;
  319. }
  320. }
  321. cip = ntohl(from.sin_addr.s_addr);
  322. if (mDebug)
  323. {
  324. printf("Server: Client (Famliy %d, Address %i.%i.%i.%i:%d)\n",
  325. ntohs(from.sin_family), cip >> 24, cip << 8 >> 24,
  326. cip << 16 >> 24, cip << 24 >> 24,
  327. ntohs(from.sin_port));
  328. printf("Server: Datalink layer recieved: packet seq %i\n",
  329. f.seq);
  330. }
  331. if (mNetworkReliable)
  332. {
  333. if (f.seq == gClients[i].seq)
  334. {
  335. if (mDebug)
  336. {
  337. printf("SERVER> Msg from %u\n", f.uid);
  338. }
  339. to_network_layer(f.data);
  340. gClients[i].seq = f.seq;
  341. }
  342. else
  343. {
  344. continue;
  345. }
  346. }
  347. // FIXME: Combine with above, duh
  348. // 3. Send to network layer
  349. if (gClients[i].frameExpected == f.header)
  350. {
  351. f.data.cid = i;
  352. to_network_layer(f.data);
  353. gClients[i].frameExpected = !gClients[i].frameExpected;
  354. }
  355. fflush(stdout);
  356. #ifdef UNIT_TEST_NETWORK
  357. if ((rand() % 10 == 0))
  358. {
  359. printf("Server: Simulating a lost ack %i\n", f.seq);
  360. continue;
  361. }
  362. #endif
  363. // 4. Send ACK, w/ piggyback if requested
  364. if (mPiggyBack)
  365. {
  366. gPiggyBack.header = 0;
  367. gPiggyBack.seq = f.seq;
  368. gPiggyBack.uid = gUID;
  369. if (mDebug)
  370. {
  371. printf("SERVER> Sending data by piggyback\n");
  372. }
  373. cc = sendto(socket_fd, &gPiggyBack, sizeof(gPiggyBack), 0,
  374. (struct sockaddr *)&from, sizeof(from));
  375. }
  376. else
  377. {
  378. f.header = 0;
  379. f.seq = 0;
  380. f.uid = gUID;
  381. cc = sendto(socket_fd, &f, sizeof(f), 0,
  382. (struct sockaddr *)&from, sizeof(from));
  383. }
  384. if (cc < 0)
  385. {
  386. perror("Server: send_udp:sendto");
  387. }
  388. else
  389. {
  390. if (mDebug)
  391. {
  392. printf("Server: Ack sent to %u\n", gClients[i].uid);
  393. }
  394. }
  395. }
  396. mKillClient = false;
  397. return 0;
  398. }
  399. void Network::runClient()
  400. {
  401. unsigned int fsize, last_frame_sent = 0;
  402. int socket_fd, cc, done;
  403. struct sockaddr_in dest;
  404. struct hostent *hostptr;
  405. network_frame_t f;
  406. struct timeval timeout;
  407. fd_set readfds;
  408. unsigned int packetsSent = 0;
  409. unsigned int seq = 0;
  410. char timedOut = 1;
  411. if (!mRemoteHost || !mRemoteHost[0])
  412. {
  413. return;
  414. }
  415. memset((char*) &timeout, 0, sizeof(timeout));
  416. timeout.tv_sec = 5;
  417. socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  418. if (socket_fd == -1)
  419. {
  420. perror("Client: send_udp: socket");
  421. exit(0);
  422. }
  423. if ((hostptr = gethostbyname(mRemoteHost)) == NULL)
  424. {
  425. fprintf(stderr, "Client: send_udp: invalid host name, %s\n",
  426. mRemoteHost);
  427. exit(0);
  428. }
  429. // Setup connection
  430. bzero((char*) &dest, sizeof(dest));
  431. dest.sin_family = AF_INET;
  432. int port = getPort();
  433. dest.sin_port = htons(port);
  434. #ifdef LOCAL_BCAST
  435. memcpy(hostptr->h_addr, (char *) &dest.sin_addr, hostptr->h_length);
  436. #else
  437. if (inet_pton(AF_INET, mRemoteHost, &dest.sin_addr) < 0)
  438. {
  439. perror("inet_pton");
  440. return;
  441. }
  442. #endif
  443. // init
  444. f.data.send = 0;
  445. f.seq = 0;
  446. for (; !mKillServer;)
  447. {
  448. ++packetsSent;
  449. if (mDebug)
  450. {
  451. printf("=====================================================\n");
  452. printf("Packet %i\n", packetsSent);
  453. }
  454. // 1. Get packet to send over wire
  455. if (mNetworkReliable && timedOut && f.seq != seq)
  456. {
  457. if (mDebug)
  458. {
  459. printf("Client: Resending packet\n");
  460. }
  461. }
  462. else
  463. {
  464. from_network_layer(&f.data, &last_frame_sent);
  465. if (!f.data.send)
  466. {
  467. usleep(20);
  468. continue;
  469. }
  470. }
  471. // 2. Copy to frame
  472. f.seq = 0;//seq; // 0 forces all packets to check out
  473. f.uid = gUID;
  474. // 3. Send over the wire
  475. done = 0;
  476. timedOut = 0;
  477. while (!done)
  478. {
  479. if (mDebug)
  480. {
  481. printf("Client: Sending packet %i\n", f.seq);
  482. }
  483. cc = sendto(socket_fd, &f, sizeof(f), 0,
  484. (struct sockaddr *)&dest, sizeof(dest));
  485. if (cc < 0)
  486. {
  487. perror("Client: send_udp:sendto");
  488. if (errno == EMSGSIZE)
  489. {
  490. printf("Client: packet was too large\n");
  491. }
  492. }
  493. else
  494. {
  495. f.data.send = 0;
  496. }
  497. // Comment out this to enable more reliable service
  498. done = 1;
  499. }
  500. // 4. Wait for +ack or resend
  501. FD_ZERO(&readfds);
  502. // Setup socket to listen on here
  503. FD_SET(socket_fd, &readfds);
  504. // Set timeout in milliseconds
  505. timeout.tv_usec = 850;
  506. cc = select(socket_fd + 1, &readfds, NULL, NULL, &timeout);
  507. if ((cc < 0) && (errno != EINTR))
  508. {
  509. // there was an local error with select
  510. }
  511. if (cc == 0)
  512. {
  513. if (mDebug)
  514. {
  515. printf("Client: Timeout detected on packet %i\n", f.seq);
  516. }
  517. timedOut = 1;
  518. continue;
  519. }
  520. // Clear header for recv use
  521. f.header = 0;
  522. fsize = sizeof(dest);
  523. cc = recvfrom(socket_fd, &f, sizeof(f), 0,
  524. (struct sockaddr *)&dest, &fsize);
  525. if (cc < 0)
  526. {
  527. perror("Client: recv_udp:recvfrom");
  528. }
  529. else
  530. {
  531. if (mDebug)
  532. {
  533. printf("Client: Datalink layer recieved: packet seq %i\n", f.seq);
  534. printf("CLIENT> Msg from %u\n", f.uid);
  535. }
  536. to_network_layer(f.data);
  537. }
  538. if (seq == f.seq)
  539. {
  540. if (mDebug)
  541. {
  542. printf("Client: Recieved ack %i\n", f.seq);
  543. }
  544. ++seq;
  545. }
  546. }
  547. mKillServer = false;
  548. }
  549. ////////////////////////////////////////////////////////////
  550. // Private Accessors
  551. ////////////////////////////////////////////////////////////
  552. ////////////////////////////////////////////////////////////
  553. // Private Mutators
  554. ////////////////////////////////////////////////////////////
  555. ////////////////////////////////////////////////////////////
  556. // Unit Test code
  557. ////////////////////////////////////////////////////////////
  558. #ifdef UNIT_TEST_NETWORK
  559. void from_network_layer(network_packet_t *p, unsigned int *last_id)
  560. {
  561. static unsigned int i = 0;
  562. if (!p)
  563. {
  564. return;
  565. }
  566. *last_id = i++;
  567. sleep(1);
  568. p->send = 1;
  569. p->pos[0] = i*3;
  570. p->pos[1] = i*3+1;
  571. p->pos[2] = i*3+2;
  572. printf("<S>ending { %f %f %f }\n", p->pos[0], p->pos[1], p->pos[2]);
  573. }
  574. void to_network_layer(network_packet_t p)
  575. {
  576. printf("<R>ecieved { %f %f %f }\n", p.pos[0], p.pos[1], p.pos[2]);
  577. gPiggyBack.data.pos[0] = gPiggyBack.seq*4;
  578. gPiggyBack.data.pos[1] = gPiggyBack.seq*4+1;
  579. gPiggyBack.data.pos[2] = gPiggyBack.seq*4+2;
  580. gPiggyBack.data.send = 1;
  581. gPiggyBack.data.yaw = 90.0f;
  582. }
  583. int main(int argc, char *argv[])
  584. {
  585. printf("\n\n[Network class test]\n");
  586. Network &test = *Network::Instance();
  587. if (argc > 3)
  588. {
  589. if (argv[1][1] == 'v')
  590. {
  591. test.setDebug(true);
  592. }
  593. switch (argv[1][0])
  594. {
  595. case 'c':
  596. test.setRemoteHost(argv[2]);
  597. test.setPort(atoi(argv[3]));
  598. test.runClient();
  599. break;
  600. case 's':
  601. test.setBindHost(argv[2]);
  602. test.setPort(atoi(argv[3]));
  603. test.runServer();
  604. break;
  605. default:
  606. printf("Error in command line, run %s for help\n", argv[0]);
  607. }
  608. }
  609. else if (argc > 2)
  610. {
  611. test.setPort(atoi(argv[2]));
  612. test.runServer();
  613. }
  614. else
  615. {
  616. printf("Server: %s s [bind_host_name] port\n", argv[0]);
  617. printf("Client: %s c remote_host_name remote_host_port\n", argv[0]);
  618. printf("Append 'v' behind c/s option for verbose. eg cv\n");
  619. }
  620. killNetworkSingleton();
  621. return 0;
  622. }
  623. #endif