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.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. #include "bomber.h"
  2. #include "announce.h"
  3. #include "game.h"
  4. #include "menu.h"
  5. #include "network.h"
  6. #include "utils.h"
  7. #include "draw.h"
  8. #define MAXMSG 4096
  9. int udpsocket;
  10. const unsigned char gameversion[4]={0xda,0x01,0x00,0x09};
  11. struct netnode netnodes[MAXNETNODES];
  12. static int informsize;
  13. static unsigned char regpacket[64];
  14. static struct sockaddr_in myname={0},mastername={0};
  15. static socklen_t senderlength;
  16. static struct sockaddr_in sender={0};
  17. static unsigned char mesg[MAXMSG]="";
  18. uchar needwhole=0;
  19. int mydatacount;
  20. int myslot;
  21. network_type network = NETWORK_NONE;
  22. int actioncount;
  23. unsigned char actionblock[ACTIONHIST*MAXNETNODES];
  24. int myaction;
  25. unsigned char actions[MAXNETNODES];
  26. unsigned char latestactions[MAXNETNODES];
  27. long latestcounts[MAXNETNODES];
  28. enum network_packet_types {
  29. PKT_ACK, /* perfect copy of packet received */
  30. /* join / host game */
  31. /* slave -> master packets */
  32. PKT_JOIN, /* 4 bytes version #, 4 bytes joinunique #, 16 bytes name */
  33. PKT_QUIT, /* 4 bytes unique # */
  34. /* master -> slave packets */
  35. PKT_INVITE, /* 4 bytes unique #, 1 byte your slot (0xff for kick, no data following it) #, any # of 1:slot,16:name sets (-1 end) */
  36. PKT_BEGIN, /* clone of INVITE */
  37. PKT_CONFIG, /* 4 bytes unique #, config */
  38. PKT_ACCEPT, /* 4 bytes join unique #, 132 bytes seed + unique #, config, slot info (see invite) */
  39. PKT_REJECT, /* 4 bytes join unique #, 4 bytes version #, 1: reason */
  40. /* ingame actions */
  41. /* slave -> master packets */
  42. PKT_MYDATA, /* 4 bytes unique #,4 bytes frame #, 1 byte data */
  43. /* master -> slave packets */
  44. PKT_STEP, /* 4 bytes unique #, 4 bytes frame #, history x MAXNETNODES bytes ACT_* */
  45. PKT_INVALID = 0xff
  46. };
  47. enum reject_reason {
  48. REJECT_FULL,
  49. REJECT_VERSION
  50. /* TODO: password? */
  51. };
  52. #define _REJECT_LAST REJECT_VERSION
  53. const char *reject_reason_str[] = {
  54. "Server full",
  55. "Version mismatch"
  56. };
  57. /* all bytes stored MSB first */
  58. /*
  59. game startup:
  60. <master and matcher>
  61. Master: send REGISTER to matcher with optional password, wait for ack. If
  62. timout, resend.
  63. matcher: Wait for REGISTER packet, when received maintain database. respond
  64. to sender with ACK. REGISTER packet can close a game also. The REGISTER
  65. packet sent by the master has a unique word to be used to avoid confusion.
  66. REGISTER packet also contains a game version #
  67. After master registers game and receives ACK, just waits for slaves to contact.
  68. <slave and matcher>
  69. slave: send QUERY to matcher with optional password, wait for INFO, if timeout,
  70. resend.
  71. matcher: respond to QUERY with INFO packet. matcher need not maintain any
  72. database for slave requests. INFO packet contains IP addr and port for each
  73. master machine that matches the QUERY spec (ALL or password). Only a
  74. certain MAX # of entries are sent if there are too many to choose from.
  75. <slave and master>
  76. slave: send JOIN to master, wait for INVITE. If timeout, resend. JOIN packet
  77. contains the unique word the master created. JOIN also contains username.
  78. master: Respond to JOIN with INVITE. INVITE contains unique word from JOIN
  79. packet. INVITE either contains NO meaning game no longer exists or is closed
  80. or player is not invited. IF yes, INVITE contains info on other players
  81. already in the game (username and slot # for each). Master allocates the
  82. slots and avoids confusion based on IP addr and port #. INVITE also contains
  83. game options structure. Whenever a new player JOINS and is admitted, master
  84. sends updated INVITE packets to everyone already in the JOIN list. Whenever
  85. master changes game options, master sends out another set of INVITES
  86. Duplicate JOINS are answered with updated INVITE but nothing changes as far
  87. as allocation.
  88. Master player launches game after he's satisfied everyone has joined.
  89. Master sends BEGIN packet to everyone. BEGIN is identical to INVITE except
  90. that the data is final. Slave must respond with its first MYDATA packet with
  91. frame # of 0. If master times out waiting, master sends duplicate BEGIN to
  92. wayward slaves. Once master has received MYDATA from everyone, game starts.
  93. Within game slave sends MYDATA to master and waits for STEP packet. If
  94. timeout, slave sends duplicate MYDATA.
  95. If master times out waiting for a slave's MYDATA, slave gets dropped. MYDATAs
  96. received will be answered with PKT_QUIT.
  97. */
  98. /* Network I/O, building/checking packets */
  99. #if defined (TEST_LATENCY)
  100. #define NUMQ 512
  101. struct message {
  102. int time;
  103. struct sockaddr_in *to;
  104. int tosize;
  105. unsigned char msg[512];
  106. int len;
  107. } message[NUMQ]={0};
  108. outmsgs() {
  109. int i;
  110. for(i=0;i<NUMQ;++i) {
  111. if(message[i].time) {
  112. --message[i].time;
  113. if(message[i].time) continue;
  114. sendto(udpsocket,message[i].msg,message[i].len,0,
  115. message[i].to,sizeof(struct sockaddr_in));
  116. }
  117. }
  118. }
  119. #endif
  120. static int putmsg(struct sockaddr_in *toname,unsigned char *msg,int len) {
  121. int status;
  122. #if defined (TEST_LATENCY)
  123. int i;
  124. for(i=0;i<NUMQ;++i) {
  125. if(!message[i].time) {
  126. message[i].time=10;
  127. message[i].to=toname;
  128. memcpy(message[i].msg,msg,len);
  129. message[i].len=len;
  130. break;
  131. }
  132. }
  133. return 0;
  134. #else
  135. status=sendto(udpsocket,msg,len,0,
  136. (struct sockaddr *)toname,sizeof(struct sockaddr_in));
  137. return status;
  138. #endif
  139. }
  140. static int getmsg(int msec) {
  141. int size;
  142. memset(&sender,0,sizeof(sender));
  143. senderlength=sizeof(sender);
  144. if(msec) {
  145. struct timeval timeout;
  146. fd_set readfds;
  147. int res;
  148. memset(&timeout,0,sizeof(timeout));
  149. timeout.tv_sec=msec/1000;
  150. timeout.tv_usec=(msec%1000)*1000;
  151. FD_ZERO(&readfds);
  152. FD_SET(udpsocket,&readfds);
  153. res=select(udpsocket+1,&readfds,0,0,&timeout);
  154. if(res<=0) return -1;
  155. }
  156. size=recvfrom(udpsocket,mesg,MAXMSG,0,
  157. (struct sockaddr *)&sender,&senderlength);
  158. return size;
  159. }
  160. static int isvalidunique(unsigned char *p) {
  161. return 0 == memcmp(p, &network_unique, 4);
  162. }
  163. static int isvalidversion(unsigned char *p) {
  164. return 0 == memcmp(p, gameversion, 4);
  165. }
  166. static unsigned char* writeuint32(unsigned char *p, Uint32 i) {
  167. p[0]=i>>24L;
  168. p[1]=i>>16L;
  169. p[2]=i>>8L;
  170. p[3]=i;
  171. return p+4;
  172. }
  173. static Uint32 readuint32(unsigned char *p) {
  174. return (p[0]<<24L) | (p[1]<<16L) | (p[2]<<8) | p[3];
  175. }
  176. static unsigned char* write_unique(unsigned char *p) {
  177. memcpy(p, &network_unique, 4);
  178. return p + 4;
  179. }
  180. static unsigned char* write_version(unsigned char *p) {
  181. memcpy(p, &gameversion, 4);
  182. return p + 4;
  183. }
  184. static int isvalidmsg_from_slave() {
  185. int i;
  186. void *host;
  187. void *port;
  188. if (!isvalidunique(mesg+1)) return -1;
  189. host=&sender.sin_addr.s_addr;
  190. port=&sender.sin_port;
  191. for(i=1;i<MAXNETNODES;++i)
  192. if(netnodes[i].used &&
  193. !memcmp(&netnodes[i].netname.sin_addr.s_addr,host,4) &&
  194. !memcmp(&netnodes[i].netname.sin_port,port,2))
  195. return i;
  196. return -1;
  197. }
  198. static int isvalidmsg_from_master() {
  199. if (sender.sin_family != mastername.sin_family
  200. || sender.sin_addr.s_addr != mastername.sin_addr.s_addr
  201. || sender.sin_port != mastername.sin_port) return 0;
  202. return 1;
  203. }
  204. /* Handling game actions */
  205. static void addactions(void) {
  206. memmove(actionblock+MAXNETNODES, actionblock, (ACTIONHIST-1)*MAXNETNODES);
  207. memcpy(actionblock, actions, MAXNETNODES);
  208. ++actioncount;
  209. }
  210. static void sendactions(int which) {
  211. unsigned char msg[512];
  212. msg[0] = PKT_STEP;
  213. write_unique(msg + 1);
  214. writeuint32(msg + 5, actioncount);
  215. memcpy(msg + 9, actionblock, MAXNETNODES*ACTIONHIST);
  216. putmsg(&netnodes[which].netname, msg, MAXNETNODES*ACTIONHIST + 9);
  217. }
  218. static void sendmine(int frame) {
  219. unsigned char msg[64];
  220. msg[0] = PKT_MYDATA;
  221. write_unique(msg + 1);
  222. writeuint32(msg + 5, frame);
  223. msg[9] = myaction;
  224. putmsg(&mastername, msg, 10);
  225. }
  226. int networktraffic(void) {
  227. int i;
  228. int length;
  229. int whosent;
  230. long now;
  231. long count;
  232. switch (network) {
  233. case NETWORK_NONE:
  234. return -1;
  235. case NETWORK_MASTER:
  236. memcpy(actions,latestactions,MAXNETNODES);
  237. actions[0]=myaction;
  238. if (myaction == ACT_QUIT) {
  239. for (i = 1; i < MAXNETNODES; ++i) {
  240. if (netnodes[i].used)
  241. actions[i] = ACT_QUIT;
  242. }
  243. } else {
  244. for (i = 1; i < MAXNETNODES; ++i) {
  245. if (netnodes[i].used)
  246. actions[i] &= ACT_MASK; /* only keep direction */
  247. }
  248. now = gtime();
  249. for (;;) {
  250. if (gtime() - now > 15) break;
  251. length = getmsg(5);
  252. if (length > 0 && *mesg != PKT_MYDATA) fprintf(stderr, "Strange packet %d\n", (int) *mesg);
  253. /* check for unexpected old packets...
  254. * for example JOIN on frame 0, respond with BEGIN if player already in game
  255. * respond with uninvite INVITE on JOIN from others
  256. */
  257. if (length < 10) continue;
  258. whosent = isvalidmsg_from_slave();
  259. if (whosent <= 0) continue;
  260. count = readuint32(mesg+5);
  261. if (count > latestcounts[whosent]) {
  262. latestcounts[whosent] = count;
  263. actions[whosent] = (actions[whosent] & ~ACT_MASK) | mesg[9]; /* don't drop "action" keys */
  264. }
  265. }
  266. }
  267. addactions(); /* update action history block */
  268. for (i = 1; i < MAXNETNODES; ++i) {
  269. if(netnodes[i].used) {
  270. sendactions(i); /* send actions to every active node */
  271. if (actions[i] == ACT_QUIT)
  272. netnodes[i].used = 0; /* remove disconnected clients */
  273. }
  274. }
  275. return actioncount;
  276. case NETWORK_SLAVE:
  277. count = -1; /* set to actioncount if we got at least one packet */
  278. now = gtime();
  279. ++mydatacount;
  280. sendmine(mydatacount);
  281. for (;;) {
  282. /* if we got already one packet we only wait 3msec, otherwise 30msec */
  283. long cur = gtime();
  284. if (count >= 0 && cur - now > 3) break;
  285. if (exitflag || cur - now > 30) break;
  286. length = getmsg(count >= 0 ? 3 : 20);
  287. if (MAXNETNODES * ACTIONHIST + 9 != length) continue;
  288. if (!isvalidmsg_from_master()) continue;
  289. i = readuint32(mesg + 5);
  290. if (i < actioncount) continue;
  291. count = actioncount = i;
  292. memcpy(actionblock, mesg + 9, MAXNETNODES * ACTIONHIST);
  293. }
  294. return actioncount;
  295. }
  296. return -1;
  297. }
  298. /* Handling socket init */
  299. int winsock=0;
  300. void getsocket(void) {
  301. int status;
  302. socklen_t slen = sizeof(myname);
  303. #if defined(__WIN32__) || defined(WIN32)
  304. char dummydata[128];
  305. if(WSAStartup(0x0101,(void *)dummydata)) {
  306. printf("Windows dumped\n");
  307. exit(1);
  308. }
  309. winsock=1;
  310. #endif
  311. udpsocket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
  312. if(udpsocket==-1) {
  313. perror("socket()");
  314. exit(1);
  315. }
  316. memset(&myname,0,sizeof(myname));
  317. myname.sin_family=AF_INET;
  318. myname.sin_addr.s_addr=htonl(INADDR_ANY);
  319. myname.sin_port=htons(0);
  320. status=bind(udpsocket,(struct sockaddr *) &myname,sizeof(myname));
  321. if(-1 == status) {
  322. perror("bind()");
  323. exit(1);
  324. }
  325. status = getsockname(udpsocket, (struct sockaddr *) &myname, &slen);
  326. if(-1 == status) {
  327. perror("getsockname()");
  328. exit(1);
  329. }
  330. }
  331. void freesocket(void) {
  332. #if defined(__WIN32__) || defined(WIN32)
  333. if(!winsock) return;
  334. WSACleanup();
  335. #endif
  336. }
  337. /* Join / Host Games */
  338. /* Master side */
  339. static unsigned char* write_inform(unsigned char* put) {
  340. int i;
  341. *put++ = 0xff; /* slot specific for each slave */
  342. for (i = 0; i < MAXNETNODES; ++i) {
  343. if(!netnodes[i].used) continue;
  344. *put++ = i;
  345. memmove(put, netnodes[i].name, 16);
  346. put += 16;
  347. }
  348. *put++ = 0xff;
  349. return put;
  350. }
  351. static void send_inform_all(unsigned char type) {
  352. int i;
  353. unsigned char *put = mesg;
  354. *put++ = type;
  355. put = write_unique(put);
  356. put = write_inform(put);
  357. informsize = put-mesg;
  358. for(i=1;i<MAXNETNODES;++i) {
  359. if(netnodes[i].used) {
  360. mesg[5] = i;
  361. putmsg(&netnodes[i].netname, mesg, informsize);
  362. }
  363. }
  364. }
  365. static unsigned char* write_config(unsigned char* put) {
  366. *put++ = configopts.density;
  367. *put++ = configopts.flames;
  368. *put++ = configopts.bombs;
  369. *put++ = configopts.generosity;
  370. return put;
  371. }
  372. static void build_config() {
  373. unsigned char *put;
  374. put=mesg;
  375. *put++=PKT_CONFIG;
  376. put = write_config(put);
  377. informsize=put-mesg;
  378. }
  379. static void send_config1(int which) {
  380. putmsg(&netnodes[which].netname,mesg,informsize);
  381. }
  382. void send_config() {
  383. int i;
  384. build_config();
  385. for (i = 1; i < MAXNETNODES; ++i)
  386. if (netnodes[i].used)
  387. send_config1(i);
  388. }
  389. static void send_reject(struct sockaddr_in *toname, Uint32 network_join_unique, unsigned char reason) {
  390. mesg[0] = PKT_REJECT;
  391. memcpy(mesg+1, &network_join_unique, sizeof(network_join_unique));
  392. write_version(mesg+5);
  393. mesg[9] = reason;
  394. putmsg(&sender,mesg,10);
  395. }
  396. static void send_accept(Uint32 network_join_unique) {
  397. unsigned char *put = mesg;
  398. *put++ = PKT_ACCEPT;
  399. memcpy(put, &network_join_unique, sizeof(network_join_unique));
  400. put += sizeof(network_join_unique);
  401. put = write_seed_unique(put);
  402. put = write_config(put);
  403. put = write_inform(put);
  404. putmsg(&sender,mesg,put-mesg);
  405. }
  406. int start_network_game() {
  407. if(!registergame(playername, myname.sin_port, gameversion)) return 0;
  408. memset(netnodes,0,sizeof(netnodes));
  409. netnodes[0].used=1;
  410. memmove(netnodes[0].name,playername,16);
  411. myslot=0;
  412. return 1;
  413. }
  414. int begin_network_game() {
  415. send_inform_all(PKT_BEGIN);
  416. network = NETWORK_MASTER;
  417. /* TODO: wait for ack */
  418. return 1;
  419. }
  420. void send_invites() {
  421. send_inform_all(PKT_INVITE);
  422. }
  423. void cancel_network_game() {
  424. int i;
  425. mesg[0] = PKT_INVITE;
  426. write_unique(mesg+1);
  427. mesg[5] = 0xff;
  428. for(i=1;i<MAXNETNODES;++i) {
  429. if(netnodes[i].used) {
  430. putmsg(&netnodes[i].netname,mesg,6);
  431. }
  432. }
  433. }
  434. int handle_joins() {
  435. int size;
  436. int i, j;
  437. unsigned char temp[64];
  438. Uint32 network_join_unique;
  439. size=getmsg(40);
  440. switch (*mesg) {
  441. case PKT_JOIN:
  442. if (size < 25) return 0;
  443. memcpy(&network_join_unique, mesg+5, sizeof(network_join_unique));
  444. if (!isvalidversion(mesg+1)) {
  445. send_reject(&sender, network_join_unique, REJECT_VERSION);
  446. return 0;
  447. }
  448. break;
  449. case PKT_QUIT:
  450. if (size < 5 || !isvalidunique(mesg+1)) return 0;
  451. break;
  452. default:
  453. return 0;
  454. }
  455. /* Find host in list:
  456. * i == MAXETNODES: host not found, otherwise the found host
  457. * only if host not found:
  458. * j == -1: no free slot, otherwise first free slot
  459. */
  460. j = -1;
  461. for (i = 1; i < MAXNETNODES; ++i) {
  462. if (!netnodes[i].used) {
  463. if (-1 == j) j = i;
  464. continue; /* don't compare with unused host */
  465. }
  466. if(memcmp(&netnodes[i].netname.sin_addr.s_addr,
  467. &sender.sin_addr.s_addr,4)) continue;
  468. if(memcmp(&netnodes[i].netname.sin_port,
  469. &sender.sin_port,2)) continue;
  470. /* found host */
  471. break;
  472. }
  473. switch (*mesg) {
  474. case PKT_QUIT:
  475. if(i < MAXNETNODES) /* if host found, reset entry */
  476. memset(netnodes+i,0,sizeof(struct netnode));
  477. /* send always ACK for QUITs */
  478. *temp=PKT_ACK;
  479. memmove(temp+1,mesg,5);
  480. putmsg(&sender,temp,6);
  481. break;
  482. case PKT_JOIN:
  483. if (i==MAXNETNODES && j==-1) { /* reject */
  484. send_reject(&sender, network_join_unique, REJECT_FULL);
  485. return 0;
  486. }
  487. if(i==MAXNETNODES) i=j;
  488. memmove(&netnodes[i].netname.sin_addr.s_addr,
  489. &sender.sin_addr.s_addr,4);
  490. memmove(&netnodes[i].netname.sin_port,
  491. &sender.sin_port,2);
  492. netnodes[i].netname.sin_family=AF_INET;
  493. netnodes[i].used=1;
  494. memcpy(netnodes[i].name,mesg+9,16);
  495. netnodes[i].name[15] = '\0';
  496. send_accept(network_join_unique);
  497. break;
  498. }
  499. return 1;
  500. }
  501. /* Client side */
  502. static int read_inform(unsigned char** pbuf, int *psize) {
  503. unsigned char *buf = *pbuf;
  504. int size = *psize;
  505. int i;
  506. if (size < 1) return 0;
  507. myslot = *buf++; size--;
  508. if (0xff == myslot) return 1;
  509. if (size < 1) return 0;
  510. while (0xff != *buf) {
  511. i = *buf++; size--;
  512. if (size < 17 || i >= MAXNETNODES) return 0;
  513. netnodes[i].used = 1;
  514. memcpy(netnodes[i].name, buf, 16);
  515. buf += 16;
  516. size -= 16;
  517. }
  518. *psize = size;
  519. *pbuf = buf;
  520. return 1;
  521. }
  522. static void read_config(unsigned char* buf) {
  523. GameOptions opts;
  524. memset(&opts, 0, sizeof(opts));
  525. opts.density = *buf++;
  526. opts.flames = *buf++;
  527. opts.bombs = *buf++;
  528. opts.generosity = *buf++;
  529. set_game_options(&opts);
  530. }
  531. /* returns 0=ignore packet,1=we're rejected,2=INVITE/CONFIG,3=BEGIN */
  532. int scaninvite(int msec) {
  533. int size;
  534. unsigned char *take;
  535. size = getmsg(msec);
  536. if (size < 6) return 0;
  537. if (*mesg!=PKT_INVITE && *mesg!=PKT_BEGIN && *mesg!=PKT_CONFIG) return 0;
  538. if (!isvalidmsg_from_master()) return 0;
  539. if (!isvalidunique(mesg+1)) return 0;
  540. take = mesg+5;
  541. size -= 5;
  542. switch (*mesg) {
  543. case PKT_INVITE:
  544. case PKT_BEGIN:
  545. if (!read_inform(&take, &size)) return 0;
  546. if (0xff == myslot) return 1; /* master closed game */
  547. break;
  548. case PKT_CONFIG:
  549. if (size < 4) return 0;
  550. read_config(take);
  551. break;
  552. }
  553. if (*mesg == PKT_BEGIN) {
  554. network = NETWORK_SLAVE;
  555. return 3;
  556. } else {
  557. return 2;
  558. }
  559. }
  560. int send_join(struct sockaddr_in *netname, char playername[16]) {
  561. int size;
  562. long now;
  563. Uint32 join_unique = gtime();
  564. unsigned char *buf;
  565. mastername = *netname;
  566. *regpacket=PKT_JOIN;
  567. write_version(regpacket + 1);
  568. writeuint32(regpacket+5, join_unique);
  569. memcpy(regpacket+9, playername, 16);
  570. now=longtime();
  571. putmsg(&mastername,regpacket,1+4+4+16);
  572. while(longtime()-now < 3) {
  573. if (0 == (size = getmsg(1000))) {
  574. /* got no message, send join again */
  575. putmsg(&mastername,regpacket,1+4+4+16);
  576. continue;
  577. }
  578. if (size < 5) continue;
  579. if (readuint32(mesg+1) != join_unique) continue;
  580. switch (*mesg) {
  581. case PKT_ACCEPT:
  582. if (size < 1+4+132+4+2) continue;
  583. read_seed_unique(mesg + 5);
  584. read_config(mesg+137);
  585. buf = mesg+141;
  586. size -= 141;
  587. if (!read_inform(&buf,&size)) return 0;
  588. return 2;
  589. case PKT_REJECT:
  590. if (size < 10 || mesg[9] > _REJECT_LAST) {
  591. failure("Couldn't connect");
  592. } else {
  593. failure("Couldn't connect: %s", reject_reason_str[mesg[9]]);
  594. }
  595. return 0;
  596. default:
  597. break;
  598. }
  599. }
  600. failure("Could not connect - Timeout");
  601. return 0;
  602. }
  603. void send_quit() {
  604. long now;
  605. int size;
  606. *regpacket = PKT_QUIT;
  607. write_unique(regpacket+1);
  608. now=longtime();
  609. while(longtime()-now<10) {
  610. putmsg(&mastername,regpacket,5);
  611. size=getmsg(1000);
  612. if(size<6) continue;
  613. if(mesg[0] != PKT_ACK || mesg[1] != PKT_QUIT) continue;
  614. if (isvalidunique(mesg+2))
  615. break;
  616. }
  617. }