server.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <pthread.h>
  9. #include <signal.h>
  10. #include <fcntl.h>
  11. #include <sys/prctl.h>
  12. #include <sys/time.h>
  13. #include <errno.h>
  14. #include "server.h"
  15. /*
  16. buf - buf for send to client
  17. list - global list of active players
  18. listSem - sem for lock global list
  19. myself - pointer to current player
  20. net proto
  21. server -> client
  22. <num objs u8> <obj desc u8> <obj pos u8> ....
  23. client -> server
  24. <intent u8>
  25. */
  26. static inline void gameTickProcessor( struct instance* this, char tick ){
  27. int s;
  28. int res;
  29. char buf[2];
  30. char cmd[2];
  31. struct tanksPlayer* myself;
  32. struct tanksPlayer* player;
  33. int tmpX;
  34. int tmpY;
  35. s = 1;
  36. this->situation[0] = 0;
  37. for( myself = this->players; myself; myself = myself->next ) {
  38. memset( cmd, 0, 2 );
  39. /********* recv intent *********/
  40. res = recv( myself->sock, buf, 2, MSG_WAITALL );
  41. if( res < 0 ){
  42. if( errno != EAGAIN || errno != EWOULDBLOCK ) perror( "recv intent" );
  43. goto l_handleIntent;
  44. }
  45. if( res != 2 ){
  46. printf( "WARNING: Too few bytes received!\n" );
  47. goto l_handleIntent;
  48. }
  49. if( buf[0] == 'g' ) myself->gearbox = buf[1];
  50. else memcpy( cmd, buf, 2 );
  51. /********* handle intent *********/
  52. l_handleIntent:
  53. //if player spectator
  54. if( !myself->rot ){
  55. //select spawn point
  56. if( cmd[0] == 's' ){
  57. if( cmd[1] == '1' ){
  58. myself->rot = 'd';
  59. myself->posX = 1;
  60. myself->posY = 10;
  61. }else if( cmd[1] == '2' ){
  62. myself->rot = 'd';
  63. myself->posX = 8;
  64. myself->posY = 10;
  65. }else if( cmd[1] == '3' ){
  66. myself->rot = 'u';
  67. myself->posX = 1;
  68. myself->posY = 180;
  69. }else if( cmd[1] == '4' ){
  70. myself->rot = 'u';
  71. myself->posX = 8;
  72. myself->posY = 180;
  73. }
  74. myself->gearbox = 0x00;
  75. }
  76. //if player alive
  77. } else {
  78. //if player blasting
  79. if( myself->blast ){
  80. if( tick ){
  81. myself->blast--;
  82. if( myself->blast ){
  83. if( myself->rot == 'B' ) myself->rot = 'b';
  84. else myself->rot = 'B';
  85. } else {
  86. myself->rot = 0x00;
  87. }
  88. }
  89. //if player send "fire" cmd
  90. } else if( cmd[0] == 'f' && !myself->shotRot ){
  91. myself->shotPosX = myself->posX;
  92. myself->shotPosY = myself->posY;
  93. myself->shotRot = myself->rot;
  94. //handle tank move
  95. } else if( tick && myself->gearbox ) {
  96. tmpX = myself->posX;
  97. tmpY = myself->posY;
  98. //move up
  99. if( myself->gearbox == 'u' ){
  100. if( myself->gearbox != myself->rot ) myself->rot = myself->gearbox;
  101. else if( tmpY > 10 ){
  102. tmpY -= 10;
  103. //check collision
  104. for( player = this->players; player; player = player->next ){
  105. if( !player->rot ) continue;
  106. if( player->blast ) continue;
  107. if( player->posX != tmpX - 2 &&
  108. player->posX != tmpX - 1 &&
  109. player->posX != tmpX &&
  110. player->posX != tmpX + 1 &&
  111. player->posX != tmpX + 2 ) continue;
  112. if( player->posY == tmpY - 20 ) goto l_skipMove;
  113. }
  114. }
  115. //move left
  116. }else if( myself->gearbox == 'l' ){
  117. if( myself->gearbox != myself->rot ) myself->rot = myself->gearbox;
  118. else if( tmpX > 1 ){
  119. tmpX--;
  120. //check collision
  121. for( player = this->players; player; player = player->next ){
  122. if( !player->rot ) continue;
  123. if( player->blast ) continue;
  124. if( player->posY != tmpY - 20 &&
  125. player->posY != tmpY - 10 &&
  126. player->posY != tmpY &&
  127. player->posY != tmpY + 10 &&
  128. player->posY != tmpY + 20 ) continue;
  129. if( player->posX == tmpX - 2 ) goto l_skipMove;
  130. }
  131. }
  132. //move down
  133. } else if( myself->gearbox == 'd' ){
  134. if( myself->gearbox != myself->rot ) myself->rot = myself->gearbox;
  135. else if( tmpY < 180 ){
  136. tmpY += 10;
  137. //check collision
  138. for( player = this->players; player; player = player->next ){
  139. if( !player->rot ) continue;
  140. if( player->blast ) continue;
  141. if( player->posX != tmpX - 2 &&
  142. player->posX != tmpX - 1 &&
  143. player->posX != tmpX &&
  144. player->posX != tmpX + 1 &&
  145. player->posX != tmpX + 2 ) continue;
  146. if( player->posY == tmpY + 20 ) goto l_skipMove;
  147. }
  148. }
  149. //move right
  150. }else if( myself->gearbox == 'r' ){
  151. if( myself->gearbox != myself->rot ) myself->rot = myself->gearbox;
  152. else if( tmpX < 8 ){
  153. tmpX++;
  154. //check collision
  155. for( player = this->players; player; player = player->next ){
  156. if( !player->rot ) continue;
  157. if( player->blast ) continue;
  158. if( player->posY != tmpY - 20 &&
  159. player->posY != tmpY - 10 &&
  160. player->posY != tmpY &&
  161. player->posY != tmpY + 10 &&
  162. player->posY != tmpY + 20 ) continue;
  163. if( player->posX == tmpX + 2 ) goto l_skipMove;
  164. }
  165. }
  166. }
  167. myself->posX = tmpX;
  168. myself->posY = tmpY;
  169. }//handle tank move
  170. }//if player alive
  171. l_skipMove:
  172. //add myself to situation
  173. if( myself->rot ){
  174. this->situation[0]++;
  175. this->situation[s] = myself->rot;
  176. s++;
  177. this->situation[s] = myself->posX + myself->posY;
  178. s++;
  179. }
  180. /********* move shot *********/
  181. if( myself->shotRot ){
  182. if( myself->shotRot == 'u' ){
  183. if( myself->shotPosY > 0 ) myself->shotPosY -= 10;
  184. else myself->shotRot = 0x00;
  185. }else if( myself->shotRot == 'l' ){
  186. if( myself->shotPosX > 0 ) myself->shotPosX--;
  187. else myself->shotRot = 0x00;
  188. }else if( myself->shotRot == 'd' ){
  189. if( myself->shotPosY < 190 ) myself->shotPosY += 10;
  190. else myself->shotRot = 0x00;
  191. }else if( myself->shotRot == 'r' ){
  192. if( myself->shotPosX < 9 ) myself->shotPosX++;
  193. else myself->shotRot = 0x00;
  194. }
  195. //check hit
  196. for( player = this->players; player; player = player->next ){
  197. if( !player->rot ) continue;
  198. if( player->blast ) continue;
  199. if( player == myself ) continue;
  200. if( player->posX != myself->shotPosX && player->posX - 1 != myself->shotPosX && player->posX + 1 != myself->shotPosX ) continue;
  201. if( player->posY != myself->shotPosY && player->posY - 10 != myself->shotPosY && player->posY + 10 != myself->shotPosY ) continue;
  202. player->blast = 16;
  203. player->rot = 'B';
  204. myself->shotRot = 0x00;
  205. break;
  206. }
  207. //add my shot to situation
  208. if( myself->shotRot ){
  209. this->situation[0]++;
  210. this->situation[s] = 'f';
  211. s++;
  212. this->situation[s] = myself->shotPosX + myself->shotPosY;
  213. s++;
  214. }
  215. }
  216. }
  217. }
  218. static inline void playerRegister( struct instance* this, struct tanksPlayer* newPlayer ){
  219. newPlayer->next = this->players;
  220. this->players = newPlayer;
  221. this->onlinePlayers++;
  222. }
  223. static inline void playerUnregister( struct instance* this, struct tanksPlayer* delPlayer ){
  224. struct tanksPlayer* player;
  225. if( this->players == delPlayer ) this->players = delPlayer->next;
  226. else {
  227. for( player = this->players; player; player = player->next ){
  228. if( player->next == delPlayer ){
  229. player->next = delPlayer->next;
  230. break;
  231. }
  232. }
  233. }
  234. this->onlinePlayers--;
  235. }
  236. /**************
  237. func openTcpPort
  238. prepare and open port
  239. in
  240. port - port No to listen
  241. return
  242. neg on err
  243. else port fd
  244. ***************/
  245. static int openTcpPort( unsigned short port ){
  246. int res;
  247. int serverSocket;
  248. const int reuseAddrEnable = 1;
  249. struct sockaddr_in addr;
  250. //socket
  251. serverSocket = socket( AF_INET, SOCK_STREAM, 0 );
  252. if( serverSocket < 0 ){
  253. perror( "socket" );
  254. return -2;
  255. }
  256. //set reuseaddr opt
  257. res = setsockopt( serverSocket, SOL_SOCKET, SO_REUSEADDR, &reuseAddrEnable, sizeof(reuseAddrEnable) );
  258. if( res ){
  259. perror( "server sock set SO_REUSEADDR" );
  260. goto l_err;
  261. }
  262. //mark non block
  263. res = fcntl( serverSocket, F_SETFL, O_NONBLOCK );
  264. if( res ){
  265. perror( "server sock set O_NONBLOCK" );
  266. goto l_err;
  267. }
  268. //prepare to bind
  269. memset ( &addr, 0, sizeof(addr) );
  270. addr.sin_family = AF_INET;
  271. addr.sin_port = htons( port );
  272. addr.sin_addr.s_addr = htonl( INADDR_ANY );
  273. //bind
  274. res = bind( serverSocket, (struct sockaddr*)&addr, sizeof(addr) );
  275. if( res < 0 ){
  276. perror( "bind" );
  277. goto l_err;
  278. }
  279. //listen
  280. res = listen( serverSocket, 5 );
  281. if( res ){
  282. perror( "listen" );
  283. goto l_err;
  284. }
  285. return serverSocket;
  286. l_err:
  287. close( serverSocket );
  288. return -2;
  289. }
  290. /**********************************
  291. func acceptPlayer
  292. accept pending connection, alloc
  293. new player and register him
  294. input
  295. this - server instance
  296. return
  297. 0 - ok
  298. neg on err
  299. *************************************/
  300. static inline int acceptPlayer( struct instance* this ){
  301. int res;
  302. int sock;
  303. char buf[8];
  304. struct tanksPlayer* player;
  305. //max players
  306. if( this->onlinePlayers > 4 ) return 0;
  307. /*** CONNECT ***/
  308. //accept
  309. sock = accept( this->serverSocket, NULL, NULL );
  310. if( sock < 0 ){
  311. if( errno == EAGAIN || errno == EWOULDBLOCK ) return 0;
  312. perror( "accept" );
  313. close( this->serverSocket );
  314. return -2;
  315. }
  316. //mark player sock non block
  317. res = fcntl( sock, F_SETFL, O_NONBLOCK );
  318. if( res ){
  319. perror( "player sock set O_NONBLOCK (not fatal)" );
  320. close( sock );
  321. return 0;
  322. }
  323. /*** HANDSHAKE ***/
  324. res = read( sock, buf, 5 );
  325. if( res < 0 ) goto l_drop;
  326. buf[5] = 0x00;
  327. if( strcmp(buf, "TANKS") ) goto l_drop;
  328. res = write( sock, "OK", 2 );
  329. if( res != 2 ) goto l_drop;
  330. /*** REGISTER ***/
  331. //alloc player
  332. player = malloc( sizeof(*player) );
  333. if( !player ){
  334. printf( "ERROR: cannot allocate new player(not fatal).\n" );
  335. close( sock );
  336. return 0;
  337. }
  338. //init player
  339. memset( player, 0, sizeof(*player) );
  340. player->sock = sock;
  341. //register player
  342. playerRegister( this, player );
  343. printf( "Connected %i\n", sock );
  344. return 0;
  345. //handshake failed
  346. l_drop:
  347. printf( "%i handhake failed\n", sock );
  348. close( sock );
  349. return 0;
  350. }
  351. static inline void sendSituation2Players( struct instance* this ){
  352. int res;
  353. int bytes;
  354. //unsigned char buf[2];
  355. struct tanksPlayer* kick;
  356. struct tanksPlayer* myself;
  357. bytes = (this->situation[0] * 2) + 1;
  358. myself = this->players;
  359. l_next:
  360. if( !myself ) return;
  361. /*** SEND ***/
  362. res = write( myself->sock, this->situation, bytes );
  363. if( res < 0 ){
  364. perror( "send" );
  365. if( errno == EAGAIN || errno == EWOULDBLOCK ) goto l_iterDone;
  366. goto l_kick;
  367. }
  368. if( res != bytes ){
  369. printf( "send err\n" );
  370. goto l_kick;
  371. }
  372. l_iterDone:
  373. myself = myself->next;
  374. goto l_next;
  375. l_kick:
  376. kick = myself;
  377. myself = myself->next;
  378. //del from list
  379. playerUnregister( this, kick );
  380. //close socket
  381. close( kick->sock );
  382. printf( "Disconnected %i\n", kick->sock );
  383. //free()
  384. free( kick );
  385. goto l_next;
  386. }
  387. static int mainLoop( unsigned short port ){
  388. int res;
  389. char tick;
  390. struct instance this;
  391. struct timeval startTime;
  392. struct timeval endTime;
  393. long long int sleepTime;
  394. tick = 0x00;
  395. /*** PREPARE ***/
  396. //init instance
  397. memset( &this, 0, sizeof(this) );
  398. //open port
  399. this.serverSocket = openTcpPort( port );
  400. if( this.serverSocket < 0 ) return this.serverSocket;
  401. printf( "Listen %hu TCP...\n", port );
  402. /*** WORK PROCESS ***/
  403. l_work:
  404. //start time
  405. gettimeofday( &startTime, NULL );
  406. //accept
  407. res = acceptPlayer( &this );
  408. if( res ) return -2;
  409. //game tick
  410. gameTickProcessor( &this, tick );
  411. tick = ~tick;
  412. //communicate
  413. sendSituation2Players( &this );
  414. //end time
  415. gettimeofday( &endTime, NULL );
  416. //sleep
  417. sleepTime = 40000 - ((endTime.tv_usec+((endTime.tv_sec-startTime.tv_sec)*1000000))-startTime.tv_usec);
  418. if( sleepTime > 0 ) usleep( sleepTime );
  419. else printf( "WARNING: overload.\n" );
  420. //continue
  421. goto l_work;
  422. }
  423. int main( int argc, char* argv[], char* envp[] ){
  424. int i;
  425. int res;
  426. unsigned short port;
  427. port = 0;
  428. //ignore sigpipe
  429. signal( SIGPIPE, SIG_IGN );
  430. //base check
  431. if( argc < 2 ) {
  432. l_help:
  433. printf( "usage:\n\t%s -p <TCP port>\n", argv[0] );
  434. return 2;
  435. }
  436. //parse arguments
  437. for( i = 1; i < argc; i++ ){
  438. if( !strcmp(argv[i], "-p") ){
  439. i++;
  440. if( i == argc ) goto l_help;
  441. res = sscanf( argv[i], "%hu", &port );
  442. if( res != 1 ) goto l_help;
  443. }
  444. }
  445. //check parsed values
  446. if( !port ) goto l_help;
  447. //start server
  448. mainLoop( port );
  449. return 0;
  450. }