Mercurial > ~darius > hgwebdir.cgi > paradise_client
comparison socket.c @ 3:5a977ccbc7a9 default tip
Empty changelog
author | darius |
---|---|
date | Sat, 06 Dec 1997 05:41:29 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:fba0b6e6cdc7 | 3:5a977ccbc7a9 |
---|---|
1 /* $Id: socket.c,v 1.1.1.1 1997/12/06 05:41:31 darius Exp $ */ | |
2 | |
3 /* | |
4 * Socket.c | |
5 * | |
6 * Kevin P. Smith 1/29/89 | |
7 * UDP stuff v1.0 by Andy McFadden Feb-Apr 1992 | |
8 * | |
9 * UDP protocol v1.0 | |
10 * | |
11 * Routines to allow connection to the xtrek server. | |
12 */ | |
13 #include "copyright2.h" | |
14 | |
15 /* to see the packets sent/received: [BDyess] */ | |
16 #if 0 | |
17 #define SHOW_SEND | |
18 #define SHOW_RECEIVED | |
19 #endif /* 0 */ | |
20 | |
21 #ifndef GATEWAY | |
22 #define USE_PORTSWAP /* instead of using recvfrom() */ | |
23 #endif | |
24 | |
25 #undef USE_PORTSWAP /* recvfrom is a better scheme */ | |
26 | |
27 #include <stdio.h> | |
28 #ifdef __STDC__ | |
29 #include <stdlib.h> | |
30 #endif | |
31 #include <sys/types.h> | |
32 #include <sys/time.h> | |
33 #ifdef RS6K | |
34 #include <sys/select.h> | |
35 #endif | |
36 #ifndef DNET | |
37 #include <sys/socket.h> | |
38 #include <netinet/in.h> | |
39 #include <netinet/tcp.h> | |
40 #include <netdb.h> | |
41 #else | |
42 #include <devices/timer.h> | |
43 #include <dos/dos.h> | |
44 #endif /* DNET */ | |
45 #include <math.h> | |
46 #include <errno.h> | |
47 #include <zlib.h> /* for terrain info */ | |
48 #include "Wlib.h" | |
49 #include "defs.h" | |
50 #include "struct.h" | |
51 #include "data.h" | |
52 #include "packets.h" | |
53 #include "proto.h" | |
54 #include "gameconf.h" | |
55 #ifdef SOUND | |
56 #include "Slib.h" | |
57 #endif /* SOUND */ | |
58 #include "sound.h" | |
59 | |
60 #define INCLUDE_SCAN /* include Amdahl scanning beams */ | |
61 #define INCLUDE_VISTRACT /* include visible tractor beams */ | |
62 | |
63 #ifdef GATEWAY | |
64 /* | |
65 * (these values are now defined in "main.c":) | |
66 * char *gw_mach = "charon"; |client gateway; strcmp(serverName) | |
67 * int gw_serv_port = 5000; |what to tell the server to use | |
68 * int gw_port = 5001; |where we will contact gw | |
69 * int gw_local_port = 5100; |where we expect gw to contact us | |
70 * | |
71 * The client binds to "5100" and sends "5000" to the server (TCP). The | |
72 * server sees that and sends a UDP packet to gw on port udp5000, which passes | |
73 * it through to port udp5100 on the client. The client-gw gets the server's | |
74 * host and port from recvfrom. (The client can't use the same method since | |
75 * these sockets are one-way only, so it connect()s to gw_port (udp5001) | |
76 * on the gateway machine regardless of what the server sends.) | |
77 * | |
78 * So all we need in .gwrc is: | |
79 * udp 5000 5001 tde.uts 5100 | |
80 * | |
81 * assuming the client is on tde.uts. Note that a UDP declaration will | |
82 * work for ANY server, but you need one per player, and the client has to | |
83 * have the port numbers in advance. | |
84 * | |
85 * If we're using a standard server, we're set. If we're running through a | |
86 * gatewayed server, we have to do some unpleasant work on the server side... | |
87 */ | |
88 #endif | |
89 | |
90 #ifdef SIZE_LOGGING | |
91 int send_total = 0; | |
92 int receive_total = 0; | |
93 #endif /* SIZE_LOGGING */ | |
94 | |
95 /* Prototypes */ | |
96 static void resetForce P((void)); | |
97 static void checkForce P((void)); | |
98 #ifdef nodef | |
99 static void set_tcp_opts P((int s)); | |
100 static void set_udp_opts P((int s)); | |
101 #endif /* nodef */ | |
102 static int doRead P((int asock)); | |
103 static void handleTorp P((struct torp_spacket * packet)); | |
104 static void handleTorpInfo P((struct torp_info_spacket * packet)); | |
105 static void handleStatus P((struct status_spacket * packet)); | |
106 static void handleSelf P((struct you_spacket * packet)); | |
107 static void handlePlayer P((struct player_spacket * packet)); | |
108 static void handleWarning P((struct warning_spacket * packet)); | |
109 void sendServerPacket P((struct player_spacket * packet)); | |
110 static void handlePlanet P((struct planet_spacket * packet)); | |
111 static void handlePhaser P((struct phaser_spacket * packet)); | |
112 void handleMessage P((struct mesg_spacket * packet)); | |
113 static void handleQueue P((struct queue_spacket * packet)); | |
114 static void handlePickok P((struct pickok_spacket * packet)); | |
115 static void handleLogin P((struct login_spacket * packet)); | |
116 static void handlePlasmaInfo P((struct plasma_info_spacket * packet)); | |
117 static void handlePlasma P((struct plasma_spacket * packet)); | |
118 static void handleFlags P((struct flags_spacket * packet)); | |
119 static void handleKills P((struct kills_spacket * packet)); | |
120 static void handlePStatus P((struct pstatus_spacket * packet)); | |
121 static void handleMotd P((struct motd_spacket * packet)); | |
122 static void handleMask P((struct mask_spacket * packet)); | |
123 static void pickSocket P((int old)); | |
124 static void handleBadVersion P((struct badversion_spacket * packet)); | |
125 int gwrite P((int fd, char *buf, int bytes)); | |
126 static void handleHostile P((struct hostile_spacket * packet)); | |
127 static void handlePlyrLogin P((struct plyr_login_spacket * packet)); | |
128 static void handleStats P((struct stats_spacket * packet)); | |
129 static void handlePlyrInfo P((struct plyr_info_spacket * packet)); | |
130 static void handlePlanetLoc P((struct planet_loc_spacket * packet)); | |
131 static void handleReserved P((struct reserved_spacket * packet)); | |
132 | |
133 static void handleScan P((struct scan_spacket * packet)); | |
134 static void handleSequence P((struct sequence_spacket * packet)); | |
135 static void handleUdpReply P((struct udp_reply_spacket * packet)); | |
136 static void informScan P((int p)); | |
137 static int openUdpConn P((void)); | |
138 #ifdef USE_PORTSWAP | |
139 static int connUdpConn P((void)); | |
140 #endif | |
141 static int recvUdpConn P((void)); | |
142 static void printUdpInfo P((void)); | |
143 /*static void dumpShip P((struct ship *shipp ));*/ | |
144 /*static int swapl P((int in ));*/ | |
145 static void handleShipCap P((struct ship_cap_spacket * packet)); | |
146 static void handleMotdPic P((struct motd_pic_spacket * packet)); | |
147 static void handleStats2 P((struct stats_spacket2 * packet)); | |
148 static void handleStatus2 P((struct status_spacket2 * packet)); | |
149 static void handlePlanet2 P((struct planet_spacket2 * packet)); | |
150 static void handleTerrain2 P((struct terrain_packet2 * pkt)); | |
151 static void handleTerrainInfo2 P((struct terrain_info_packet2 *pkt)); | |
152 static void handleTempPack P((struct obvious_packet * packet)); | |
153 static void handleThingy P((struct thingy_spacket * packet)); | |
154 static void handleThingyInfo P((struct thingy_info_spacket * packet)); | |
155 static void handleRSAKey P((struct rsa_key_spacket * packet)); | |
156 void handlePing(); | |
157 static void handleExtension1 P((struct paradiseext1_spacket *)); | |
158 | |
159 static void handleEmpty(); | |
160 | |
161 | |
162 #ifdef SHORT_PACKETS | |
163 void handleShortReply(), handleVPlayer(), handleVTorp(), | |
164 handleSelfShort(), handleSelfShip(), handleVPlanet(), handleSWarning(); | |
165 void handleVTorpInfo(), handleSMessage(); | |
166 #endif | |
167 | |
168 #ifdef FEATURE | |
169 void handleFeature(); /* feature.c */ | |
170 #endif | |
171 | |
172 struct packet_handler handlers[] = { | |
173 {NULL}, /* record 0 */ | |
174 {handleMessage}, /* SP_MESSAGE */ | |
175 {handlePlyrInfo}, /* SP_PLAYER_INFO */ | |
176 {handleKills}, /* SP_KILLS */ | |
177 {handlePlayer}, /* SP_PLAYER */ | |
178 {handleTorpInfo}, /* SP_TORP_INFO */ | |
179 {handleTorp}, /* SP_TORP */ | |
180 {handlePhaser}, /* SP_PHASER */ | |
181 {handlePlasmaInfo}, /* SP_PLASMA_INFO */ | |
182 {handlePlasma}, /* SP_PLASMA */ | |
183 {handleWarning}, /* SP_WARNING */ | |
184 {handleMotd}, /* SP_MOTD */ | |
185 {handleSelf}, /* SP_YOU */ | |
186 {handleQueue}, /* SP_QUEUE */ | |
187 {handleStatus}, /* SP_STATUS */ | |
188 {handlePlanet}, /* SP_PLANET */ | |
189 {handlePickok}, /* SP_PICKOK */ | |
190 {handleLogin}, /* SP_LOGIN */ | |
191 {handleFlags}, /* SP_FLAGS */ | |
192 {handleMask}, /* SP_MASK */ | |
193 {handlePStatus}, /* SP_PSTATUS */ | |
194 {handleBadVersion}, /* SP_BADVERSION */ | |
195 {handleHostile}, /* SP_HOSTILE */ | |
196 {handleStats}, /* SP_STATS */ | |
197 {handlePlyrLogin}, /* SP_PL_LOGIN */ | |
198 {handleReserved}, /* SP_RESERVED */ | |
199 {handlePlanetLoc}, /* SP_PLANET_LOC */ | |
200 {handleScan}, /* SP_SCAN (ATM) */ | |
201 {handleUdpReply}, /* SP_UDP_STAT */ | |
202 {handleSequence}, /* SP_SEQUENCE */ | |
203 {handleSequence}, /* SP_SC_SEQUENCE */ | |
204 {handleRSAKey}, /* SP_RSA_KEY */ | |
205 {handleMotdPic}, /* SP_MOTD_PIC */ | |
206 {handleStats2}, /* SP_STATS2 */ | |
207 {handleStatus2}, /* SP_STATUS2 */ | |
208 {handlePlanet2}, /* SP_PLANET2 */ | |
209 {handleTempPack}, /* SP_TEMP_5 */ | |
210 {handleThingy}, /* SP_THINGY */ | |
211 {handleThingyInfo}, /* SP_THINGY_INFO */ | |
212 {handleShipCap}, /* SP_SHIP_CAP */ | |
213 | |
214 #ifdef SHORT_PACKETS | |
215 {handleShortReply}, /* SP_S_REPLY */ | |
216 {handleSMessage}, /* SP_S_MESSAGE */ | |
217 {handleSWarning}, /* SP_S_WARNING */ | |
218 {handleSelfShort}, /* SP_S_YOU */ | |
219 {handleSelfShip}, /* SP_S_YOU_SS */ | |
220 {handleVPlayer}, /* SP_S_PLAYER */ | |
221 #else | |
222 {handleEmpty}, /* 40 */ | |
223 {handleEmpty}, /* 41 */ | |
224 {handleEmpty}, /* 42 */ | |
225 {handleEmpty}, /* 43 */ | |
226 {handleEmpty}, /* 44 */ | |
227 {handleEmpty}, /* 45 */ | |
228 #endif | |
229 {handlePing}, /* SP_PING */ | |
230 #ifdef SHORT_PACKETS | |
231 {handleVTorp}, /* SP_S_TORP */ | |
232 {handleVTorpInfo}, /* SP_S_TORP_INFO */ | |
233 {handleVTorp}, /* SP_S_8_TORP */ | |
234 {handleVPlanet}, /* SP_S_PLANET */ | |
235 #else | |
236 {handleEmpty}, /* 47 */ | |
237 {handleEmpty}, | |
238 {handleEmpty}, | |
239 {handleEmpty}, /* 50 */ | |
240 #endif | |
241 {handleGameparams}, | |
242 {handleExtension1}, | |
243 {handleTerrain2}, /* 53 */ | |
244 {handleTerrainInfo2}, | |
245 {handleEmpty}, | |
246 {handleEmpty}, | |
247 {handleEmpty}, | |
248 {handleEmpty}, | |
249 {handleEmpty}, /* 59 */ | |
250 #ifdef FEATURE | |
251 {handleFeature}, /* SP_FEATURE */ | |
252 #else | |
253 {handleEmpty}, /* 60 */ | |
254 #endif | |
255 }; | |
256 | |
257 #define NUM_HANDLERS (sizeof(handlers)/sizeof(*handlers)) | |
258 | |
259 #define NUM_PACKETS (sizeof(handlers) / sizeof(handlers[0]) - 1) | |
260 | |
261 int serverDead = 0; | |
262 | |
263 int UdpLocalPort = 0; /* do we want a specified local UDP port */ | |
264 | |
265 #ifdef SIZE_LOGGING | |
266 void | |
267 print_totals() | |
268 /* prints the total number of bytes sent/received. Called when exiting the | |
269 client [BDyess] */ | |
270 { | |
271 time_t timeSpent = time(NULL) - timeStart; | |
272 | |
273 /* | |
274 printf("Total bytes sent: %d\nTotal bytes received: %d\n", | |
275 send_total, receive_total); | |
276 */ | |
277 /* ftp format [BDyess] */ | |
278 if (timeSpent < 600 /* 10 minutes */ ) { | |
279 printf("%8d bytes sent in %d seconds (%.3f Kbytes/s)\n", | |
280 send_total, timeSpent, | |
281 (float) send_total / (1024.0 * timeSpent)); | |
282 printf("%8d bytes received in %d seconds (%.3f Kbytes/s)\n", | |
283 receive_total, timeSpent, | |
284 (float) receive_total / (1024.0 * timeSpent)); | |
285 } else { /* number too big for seconds, use minutes */ | |
286 printf("%8d bytes sent in %.1f minutes (%.3f Kbytes/s)\n", | |
287 send_total, timeSpent / 60.0, | |
288 (float) send_total / (1024.0 * timeSpent)); | |
289 printf("%8d bytes received in %.1f minutes (%.3f Kbytes/s)\n", | |
290 receive_total, timeSpent / 60.0, | |
291 (float) receive_total / (1024.0 * timeSpent)); | |
292 } | |
293 } | |
294 #else | |
295 #define EXIT exit | |
296 #endif /* SIZE_LOGGING */ | |
297 | |
298 int udpLocalPort = 0; | |
299 static int udpServerPort = 0; | |
300 static long serveraddr = 0; | |
301 static long sequence = 0; | |
302 static int drop_flag = 0; | |
303 static int chan = -1; /* tells sequence checker where packet is | |
304 from */ | |
305 static short fSpeed, fDirection, fShield, fOrbit, fRepair, fBeamup, fBeamdown, fCloak, | |
306 fBomb, fDockperm, fPhaser, fPlasma, fPlayLock, fPlanLock, fTractor, | |
307 fRepress; | |
308 | |
309 /* reset all the "force command" variables */ | |
310 static void | |
311 resetForce() | |
312 { | |
313 fSpeed = fDirection = fShield = fOrbit = fRepair = fBeamup = fBeamdown = | |
314 fCloak = fBomb = fDockperm = fPhaser = fPlasma = fPlayLock = fPlanLock = | |
315 fTractor = fRepress = -1; | |
316 } | |
317 | |
318 /* | |
319 * If something we want to happen hasn't yet, send it again. | |
320 * | |
321 * The low byte is the request, the high byte is a max count. When the max | |
322 * count reaches zero, the client stops trying. Checking is done with a | |
323 * macro for speed & clarity. | |
324 */ | |
325 #define FCHECK_FLAGS(flag, force, const) { \ | |
326 if (force > 0) { \ | |
327 if (((me->p_flags & flag) && 1) ^ ((force & 0xff) && 1)) { \ | |
328 speedReq.type = const; \ | |
329 speedReq.speed = (force & 0xff); \ | |
330 sendServerPacket((struct player_spacket *)&speedReq); \ | |
331 V_UDPDIAG(("Forced %d:%d\n", const, force & 0xff)); \ | |
332 force -= 0x100; \ | |
333 if (force < 0x100) force = -1; /* give up */ \ | |
334 } else \ | |
335 force = -1; \ | |
336 } \ | |
337 } | |
338 #define FCHECK_VAL(value, force, const) { \ | |
339 if (force > 0) { \ | |
340 if ((value) != (force & 0xff)) { \ | |
341 speedReq.type = const; \ | |
342 speedReq.speed = (force & 0xff); \ | |
343 sendServerPacket((struct player_spacket *)&speedReq); \ | |
344 V_UDPDIAG(("Forced %d:%d\n", const, force & 0xff)); \ | |
345 force -= 0x100; \ | |
346 if (force < 0x100) force = -1; /* give up */ \ | |
347 } else \ | |
348 force = -1; \ | |
349 } \ | |
350 } | |
351 #define FCHECK_TRACT(flag, force, const) { \ | |
352 if (force > 0) { \ | |
353 if (((me->p_flags & flag) && 1) ^ ((force & 0xff) && 1)) { \ | |
354 tractorReq.type = const; \ | |
355 tractorReq.state = ((force & 0xff) >= 0x40); \ | |
356 tractorReq.pnum = (force & 0xff) & (~0x40); \ | |
357 sendServerPacket((struct player_spacket *)&tractorReq); \ | |
358 V_UDPDIAG(("Forced %d:%d/%d\n", const, \ | |
359 tractorReq.state, tractorReq.pnum)); \ | |
360 force -= 0x100; \ | |
361 if (force < 0x100) force = -1; /* give up */ \ | |
362 } else \ | |
363 force = -1; \ | |
364 } \ | |
365 } | |
366 | |
367 static void | |
368 checkForce() | |
369 { | |
370 struct speed_cpacket speedReq; | |
371 struct tractor_cpacket tractorReq; | |
372 | |
373 /* upgrading kludge [BDyess] */ | |
374 if (!upgrading) | |
375 FCHECK_VAL(me->p_speed, fSpeed, CP_SPEED); /* almost always repeats */ | |
376 FCHECK_VAL(me->p_dir, fDirection, CP_DIRECTION); /* (ditto) */ | |
377 FCHECK_FLAGS(PFSHIELD, fShield, CP_SHIELD); | |
378 FCHECK_FLAGS(PFORBIT, fOrbit, CP_ORBIT); | |
379 FCHECK_FLAGS(PFREPAIR, fRepair, CP_REPAIR); | |
380 FCHECK_FLAGS(PFBEAMUP, fBeamup, CP_BEAM); | |
381 FCHECK_FLAGS(PFBEAMDOWN, fBeamdown, CP_BEAM); | |
382 FCHECK_FLAGS(PFCLOAK, fCloak, CP_CLOAK); | |
383 FCHECK_FLAGS(PFBOMB, fBomb, CP_BOMB); | |
384 FCHECK_FLAGS(PFDOCKOK, fDockperm, CP_DOCKPERM); | |
385 FCHECK_VAL(phasers[me->p_no].ph_status, fPhaser, CP_PHASER); /* bug: dir 0 */ | |
386 FCHECK_VAL(plasmatorps[me->p_no].pt_status, fPlasma, CP_PLASMA); /* (ditto) */ | |
387 FCHECK_FLAGS(PFPLOCK, fPlayLock, CP_PLAYLOCK); | |
388 FCHECK_FLAGS(PFPLLOCK, fPlanLock, CP_PLANLOCK); | |
389 | |
390 #ifdef HOCKEY | |
391 /* kludge to help prevent self-deflects */ | |
392 if(! (hockey && me->p_tractor == 'g'-'a'+10 /*puck*/)) { | |
393 #endif | |
394 FCHECK_TRACT(PFTRACT, fTractor, CP_TRACTOR); | |
395 FCHECK_TRACT(PFPRESS, fRepress, CP_REPRESS); | |
396 #ifdef HOCKEY | |
397 } | |
398 #endif | |
399 } | |
400 | |
401 | |
402 int | |
403 idx_to_mask(i) | |
404 int i; | |
405 { | |
406 if (i == number_of_teams) | |
407 return ALLTEAM; | |
408 return 1 << i; | |
409 } | |
410 | |
411 int | |
412 mask_to_idx(m) | |
413 int m; | |
414 { | |
415 int i, j; | |
416 for (i = 1, j = -1; m > 0 && i < 5; i++, m >>= 1) | |
417 if (m & 1) | |
418 j += i; | |
419 if (j > number_of_teams) | |
420 j = number_of_teams; | |
421 return j; | |
422 } | |
423 | |
424 | |
425 void | |
426 connectToServer(port) | |
427 int port; | |
428 { | |
429 #ifndef DNET | |
430 int s; | |
431 struct sockaddr_in addr; | |
432 struct sockaddr_in naddr; | |
433 int len; | |
434 fd_set readfds; | |
435 struct timeval timeout; | |
436 struct hostent *hp; | |
437 | |
438 serverDead = 0; | |
439 if (sock != -1) { | |
440 shutdown(sock, 2); | |
441 sock = -1; | |
442 } | |
443 sleep(3); /* I think this is necessary for some unknown | |
444 reason */ | |
445 | |
446 #ifdef RWATCH | |
447 printf("rwatch: Waiting for connection. \n"); | |
448 #else | |
449 printf("Waiting for connection (port %d). \n", port); | |
450 #endif /* RWATCH */ | |
451 | |
452 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
453 #ifdef RWATCH | |
454 printf("rwatch: I can't create a socket\n"); | |
455 #else | |
456 printf("I can't create a socket\n"); | |
457 #endif /* RWATCH */ | |
458 #ifdef AUTOKEY | |
459 if (autoKey) | |
460 W_AutoRepeatOn(); | |
461 #endif | |
462 | |
463 EXIT(2); | |
464 } | |
465 #ifndef RWATCH | |
466 #ifdef nodef /* don't use for now */ | |
467 set_tcp_opts(s); | |
468 #endif /* nodef */ | |
469 #endif /* RWATCH */ | |
470 | |
471 addr.sin_family = AF_INET; | |
472 addr.sin_addr.s_addr = INADDR_ANY; | |
473 addr.sin_port = htons(port); | |
474 | |
475 if (bind(s, (struct sockaddr *) & addr, sizeof(addr)) < 0) { | |
476 sleep(10); | |
477 if (bind(s, (struct sockaddr *) & addr, sizeof(addr)) < 0) { | |
478 sleep(10); | |
479 if (bind(s, (struct sockaddr *) & addr, sizeof(addr)) < 0) { | |
480 #ifdef RWATCH | |
481 printf("rwatch: I can't bind to port!\n"); | |
482 #else | |
483 printf("I can't bind to port!\n"); | |
484 #endif /* RWATCH */ | |
485 #ifdef AUTOKEY | |
486 if (autoKey) | |
487 W_AutoRepeatOn(); | |
488 #endif | |
489 | |
490 EXIT(3); | |
491 } | |
492 } | |
493 } | |
494 listen(s, 1); | |
495 | |
496 len = sizeof(naddr); | |
497 | |
498 tryagain: | |
499 timeout.tv_sec = 240; /* four minutes */ | |
500 timeout.tv_usec = 0; | |
501 FD_ZERO(&readfds); | |
502 FD_SET(s, &readfds); | |
503 if (select(32, &readfds, NULL, NULL, &timeout) == 0) { | |
504 #ifdef RWATCH | |
505 printf("rwatch: server died.\n"); | |
506 #else | |
507 printf("Well, I think the server died!\n"); | |
508 #endif /* RWATCH */ | |
509 #ifdef AUTOKEY | |
510 if (autoKey) | |
511 W_AutoRepeatOn(); | |
512 #endif | |
513 | |
514 EXIT(0); | |
515 } | |
516 sock = accept(s, (struct sockaddr *) & naddr, &len); | |
517 | |
518 if (sock == -1) { | |
519 #ifdef RWATCH | |
520 perror("rwatch: accept"); | |
521 #else | |
522 perror("accept"); | |
523 #endif /* RWATCH */ | |
524 goto tryagain; | |
525 } | |
526 close(s); | |
527 pickSocket(port); /* new socket != port */ | |
528 | |
529 | |
530 /* | |
531 This is strictly necessary; it tries to determine who the caller is, | |
532 and set "serverName" and "serveraddr" appropriately. | |
533 */ | |
534 len = sizeof(struct sockaddr_in); | |
535 if (getpeername(sock, (struct sockaddr *) & addr, &len) < 0) { | |
536 perror("unable to get peername"); | |
537 serverName = "nowhere"; | |
538 } else { | |
539 serveraddr = addr.sin_addr.s_addr; | |
540 hp = gethostbyaddr((char *) &addr.sin_addr.s_addr, sizeof(long), AF_INET); | |
541 if (hp != NULL) { | |
542 serverName = (char *) malloc(strlen(hp->h_name) + 1); | |
543 strcpy(serverName, hp->h_name); | |
544 } else { | |
545 serverName = (char *) malloc(strlen((char *) inet_ntoa(addr.sin_addr)) + 1); | |
546 strcpy(serverName, (char *) inet_ntoa(addr.sin_addr)); | |
547 } | |
548 } | |
549 printf("Connection from server %s (0x%x)\n", serverName, serveraddr); | |
550 | |
551 #else /* DNET */ | |
552 /* | |
553 unix end DNet server process connects to the server, on specified * | |
554 port | |
555 */ | |
556 ConnectToDNetServer(port); | |
557 #endif /* DNET */ | |
558 | |
559 } | |
560 | |
561 | |
562 #ifndef DNET | |
563 #ifdef nodef | |
564 static void | |
565 set_tcp_opts(s) | |
566 int s; | |
567 { | |
568 int optval = 1; | |
569 struct protoent *ent; | |
570 | |
571 ent = getprotobyname("TCP"); | |
572 if (!ent) { | |
573 fprintf(stderr, "TCP protocol not found.\n"); | |
574 return; | |
575 } | |
576 if (setsockopt(s, ent->p_proto, TCP_NODELAY, &optval, sizeof(int)) < 0) | |
577 perror("setsockopt"); | |
578 } | |
579 | |
580 static void | |
581 set_udp_opts(s) | |
582 int s; | |
583 { | |
584 int optval = BUFSIZ; | |
585 struct protoent *ent; | |
586 ent = getprotobyname("UDP"); | |
587 if (!ent) { | |
588 fprintf(stderr, "UDP protocol not found.\n"); | |
589 return; | |
590 } | |
591 if (setsockopt(s, ent->p_proto, SO_RCVBUF, &optval, sizeof(int)) < 0) | |
592 perror("setsockopt"); | |
593 } | |
594 #endif /* nodef */ | |
595 | |
596 #endif /* DNET */ | |
597 | |
598 void | |
599 callServer(port, server) | |
600 int port; | |
601 char *server; | |
602 { | |
603 #ifndef DNET | |
604 int s; | |
605 struct sockaddr_in addr; | |
606 struct hostent *hp; | |
607 #endif | |
608 serverDead = 0; | |
609 | |
610 printf("Calling %s on port %d.\n", server, port); | |
611 #ifdef DNET | |
612 CallDNetServer(server, port); | |
613 #else | |
614 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
615 printf("I can't create a socket\n"); | |
616 EXIT(0); | |
617 } | |
618 #ifndef RWATCH | |
619 #ifdef nodef | |
620 set_tcp_opts(s); | |
621 #endif /* nodef */ | |
622 #endif /* RWATCH */ | |
623 | |
624 addr.sin_family = AF_INET; | |
625 addr.sin_port = htons(port); | |
626 | |
627 if ((addr.sin_addr.s_addr = inet_addr(server)) == -1) { | |
628 if ((hp = gethostbyname(server)) == NULL) { | |
629 printf("Who is %s?\n", server); | |
630 EXIT(0); | |
631 } else { | |
632 addr.sin_addr.s_addr = *(long *) hp->h_addr; | |
633 } | |
634 } | |
635 serveraddr = addr.sin_addr.s_addr; | |
636 | |
637 if (connect(s, (struct sockaddr *) & addr, sizeof(addr)) < 0) { | |
638 printf("Server not listening!\n"); | |
639 EXIT(0); | |
640 } | |
641 printf("Got connection.\n"); | |
642 | |
643 sock = s; | |
644 #endif /* DNET */ | |
645 /* pickSocket is utterly useless with DNet, but the server needs the | |
646 packet to tell it the client is ready to start. */ | |
647 | |
648 #ifdef RECORDER | |
649 startRecorder(); | |
650 #endif | |
651 pickSocket(port); /* new socket != port */ | |
652 } | |
653 | |
654 int | |
655 isServerDead() | |
656 { | |
657 return (serverDead); | |
658 } | |
659 | |
660 void | |
661 socketPause(sec, usec) | |
662 int sec, usec; | |
663 { | |
664 struct timeval timeout; | |
665 fd_set readfds; | |
666 | |
667 #ifdef RECORDER | |
668 if (playback) | |
669 return; | |
670 #endif | |
671 #ifdef DNET | |
672 (void) DNetServerPause(sec, usec, 0); | |
673 #else | |
674 | |
675 timeout.tv_sec = sec; | |
676 timeout.tv_usec = usec; | |
677 FD_ZERO(&readfds); | |
678 FD_SET(sock, &readfds); | |
679 if (udpSock >= 0) /* new */ | |
680 FD_SET(udpSock, &readfds); | |
681 select(32, &readfds, 0, 0, &timeout); | |
682 #endif /* DNET */ | |
683 } | |
684 | |
685 int | |
686 readFromServer() | |
687 { | |
688 struct timeval timeout; | |
689 fd_set readfds; | |
690 int retval = 0, rs; | |
691 | |
692 #ifdef RECORDER | |
693 if (playback) { | |
694 while (!pb_update) | |
695 doRead(sock); | |
696 return 1; | |
697 } | |
698 #endif | |
699 | |
700 if (serverDead) | |
701 return (0); | |
702 if (commMode == COMM_TCP) | |
703 drop_flag = 0; /* just in case */ | |
704 | |
705 #ifndef DNET | |
706 timeout.tv_sec = 0; | |
707 timeout.tv_usec = 0; | |
708 | |
709 FD_ZERO(&readfds); | |
710 FD_SET(sock, &readfds); | |
711 if (udpSock >= 0) | |
712 FD_SET(udpSock, &readfds); | |
713 if ((rs = select(32, &readfds, 0, 0, &timeout)) != 0) { | |
714 if (rs < 0) { | |
715 /* NEW */ | |
716 perror("select"); | |
717 return 0; | |
718 } | |
719 #else | |
720 /* this should have been done before calling the function.. not sure about this, should maybe be doing | |
721 DNetServerPause here? -JR*/ | |
722 /* sigsPending=Wait(sockMask | udpSockMask | SIGBREAKF_CTRL_C); | |
723 */ | |
724 if (sigsPending & SIGBREAKF_CTRL_C) { | |
725 printf("readFromServer: Ctrl-C break, exiting\n"); | |
726 exit(0); | |
727 } | |
728 /* note for DNet FD_ISSET is redefined. */ | |
729 #endif /* DNET */ | |
730 /* Read info from the xtrek server */ | |
731 if (FD_ISSET(sock, &readfds)) { | |
732 chan = sock; | |
733 retval += doRead(sock); | |
734 } | |
735 if (udpSock >= 0 && FD_ISSET(udpSock, &readfds)) { | |
736 /* WAS V_ *//* should be! */ | |
737 V_UDPDIAG(("Activity on UDP socket\n")); | |
738 chan = udpSock; | |
739 if (commStatus == STAT_VERIFY_UDP) { | |
740 warning("UDP connection established"); | |
741 sequence = 0; /* reset sequence #s */ | |
742 resetForce(); | |
743 | |
744 if (udpDebug) | |
745 printUdpInfo(); | |
746 UDPDIAG(("UDP connection established.\n")); | |
747 | |
748 commMode = COMM_UDP; | |
749 commStatus = STAT_CONNECTED; | |
750 commSwitchTimeout = 0; | |
751 if (udpClientRecv != MODE_SIMPLE) | |
752 sendUdpReq(COMM_MODE + udpClientRecv); | |
753 if (udpWin) { | |
754 udprefresh(UDP_CURRENT); | |
755 udprefresh(UDP_STATUS); | |
756 } | |
757 } | |
758 retval += doRead(udpSock); | |
759 } | |
760 #ifndef DNET | |
761 } | |
762 #endif | |
763 | |
764 /* if switching comm mode, decrement timeout counter */ | |
765 if (commSwitchTimeout > 0) { | |
766 if (!(--commSwitchTimeout)) { | |
767 /* | |
768 timed out; could be initial request to non-UDP server (which won't | |
769 be answered), or the verify packet got lost en route to the | |
770 server. Could also be a request for TCP which timed out (weird), | |
771 in which case we just reset anyway. | |
772 */ | |
773 commModeReq = commMode = COMM_TCP; | |
774 commStatus = STAT_CONNECTED; | |
775 if (udpSock >= 0) | |
776 closeUdpConn(); | |
777 if (udpWin) { | |
778 udprefresh(UDP_CURRENT); | |
779 udprefresh(UDP_STATUS); | |
780 } | |
781 warning("Timed out waiting for UDP response from server"); | |
782 UDPDIAG(("Timed out waiting for UDP response from server\n")); | |
783 } | |
784 } | |
785 /* if we're in a UDP "force" mode, check to see if we need to do something */ | |
786 if (commMode == COMM_UDP && udpClientSend > 1) | |
787 checkForce(); | |
788 | |
789 return (retval != 0); /* convert to 1/0 */ | |
790 } | |
791 | |
792 | |
793 /* this used to be part of the routine above */ | |
794 char buf[BUFSIZ * 2 + 16]; | |
795 | |
796 static int | |
797 doRead(asock) | |
798 int asock; | |
799 { | |
800 char *bufptr; | |
801 int size; | |
802 int count; | |
803 int temp; | |
804 #ifdef HANDLER_TIMES | |
805 struct timeval htpre, htpost; | |
806 extern void log_time(int, struct timeval *, struct timeval *); | |
807 #endif | |
808 | |
809 #ifndef DNET | |
810 struct timeval timeout; | |
811 fd_set readfds; | |
812 timeout.tv_sec = 0; | |
813 timeout.tv_usec = 0; | |
814 #endif /* DNET */ | |
815 | |
816 count = sock_read(asock, buf, 2 * BUFSIZ); | |
817 #ifdef DNET | |
818 if (count == 0) { /* yuck. */ | |
819 return 0; | |
820 } | |
821 #endif | |
822 /* TMP */ | |
823 #ifdef nodef | |
824 if (asock == udpSock) | |
825 printf("read %d bytes\n", count); | |
826 #endif /* nodef */ | |
827 | |
828 if (count <= 0) { | |
829 if (asock == udpSock) { | |
830 #ifndef DNET | |
831 if (errno == ECONNREFUSED) { | |
832 struct sockaddr_in addr; | |
833 | |
834 UDPDIAG(("asock=%d, sock=%d, udpSock=%d, errno=%d\n", | |
835 asock, sock, udpSock, errno)); | |
836 UDPDIAG(("count=%d\n", count)); | |
837 UDPDIAG(("Hiccup(%d)! Reconnecting\n", errno)); | |
838 addr.sin_addr.s_addr = serveraddr; | |
839 addr.sin_port = htons(udpServerPort); | |
840 addr.sin_family = AF_INET; | |
841 if (connect(udpSock, (struct sockaddr *) & addr, sizeof(addr)) < 0) { | |
842 perror("connect"); | |
843 UDPDIAG(("Unable to reconnect\n")); | |
844 /* and fall through to disconnect */ | |
845 } else { | |
846 UDPDIAG(("Reconnect successful\n")); | |
847 return (0); | |
848 } | |
849 } | |
850 #endif /* DNET */ | |
851 UDPDIAG(("*** UDP disconnected (res=%d, err=%d)\n", | |
852 count, errno)); | |
853 warning("UDP link severed"); | |
854 printUdpInfo(); | |
855 closeUdpConn(); | |
856 commMode = commModeReq = COMM_TCP; | |
857 commStatus = STAT_CONNECTED; | |
858 if (udpWin) { | |
859 udprefresh(UDP_STATUS); | |
860 udprefresh(UDP_CURRENT); | |
861 } | |
862 return (0); | |
863 } | |
864 #ifndef RWATCH | |
865 printf("1) Got read() of %d. Server dead\n", count); | |
866 perror(""); | |
867 #endif /* RWATCH */ | |
868 serverDead = 1; | |
869 return (0); | |
870 } | |
871 bufptr = buf; | |
872 while (bufptr < buf + count) { | |
873 #ifdef SHORT_PACKETS | |
874 computesize: | |
875 if ((*bufptr == SP_S_MESSAGE && (buf + count - bufptr <= 4)) | |
876 || (buf + count - bufptr < 4)) { /* last part may only be | |
877 needed for DNet...I'm not | |
878 so sure any more. | |
879 certainly doesn't hurt to | |
880 have it.-JR */ | |
881 /* | |
882 printf("buf+count-bufptr=%d, *bufptr=%d\n",buf + count - | |
883 bufptr,*bufptr); | |
884 */ | |
885 size = 0; /* problem with reads breaking before size | |
886 byte for SP_S_MESSAGE has been read. Only | |
887 a problem for messages because reads break | |
888 on 4 byte boundaries, other size bytes | |
889 are always in the first 4. -JR */ | |
890 } else | |
891 #endif | |
892 { | |
893 size = size_of_spacket(bufptr); | |
894 if (size < 1) { | |
895 #if 1 | |
896 fprintf(stderr, "Unknown packet %d. Faking it.\n", | |
897 *bufptr); | |
898 size = 4; | |
899 #else | |
900 fprintf(stderr, "Unknown packet %d. Aborting.\n", | |
901 *bufptr); | |
902 return (0); | |
903 #endif | |
904 } | |
905 #ifdef SHOW_RECEIVED | |
906 printf("recieved packet type %d, size %d\n", *bufptr, size); | |
907 #endif /* SHOW_RECEIVED */ | |
908 #ifdef PACKET_LIGHTS | |
909 light_receive(); | |
910 #endif /* PACKET_LIGHTS */ | |
911 #ifdef SIZE_LOGGING | |
912 receive_total += size; | |
913 #endif /* SIZE_LOGGING */ | |
914 } | |
915 while (size > count + (buf - bufptr) || size == 0) { | |
916 /* | |
917 We wait for up to ten seconds for rest of packet. If we don't | |
918 get it, we assume the server died. | |
919 */ | |
920 /* | |
921 printf("er, possible packet fragment, waiting for the | |
922 rest...\n"); | |
923 */ | |
924 #ifdef RECORDER | |
925 if (!playback) | |
926 #endif | |
927 { | |
928 #ifdef DNET | |
929 temp = DNetServerPause(20, 0, asock); | |
930 #else /* DNET */ | |
931 timeout.tv_sec = 20; | |
932 timeout.tv_usec = 0; | |
933 FD_ZERO(&readfds); | |
934 FD_SET(asock, &readfds); | |
935 /* readfds=1<<asock; */ | |
936 temp = select(32, &readfds, 0, 0, &timeout); | |
937 #endif | |
938 if (temp == 0) { | |
939 printf("Packet fragment. Server must be dead\n"); | |
940 serverDead = 1; | |
941 return (0); | |
942 } | |
943 } | |
944 #ifdef SHORT_PACKETS | |
945 if (size == 0) | |
946 /* 84=largest short packet message - the 4 we have */ | |
947 temp = sock_read(asock, buf + count, 84); | |
948 else | |
949 #endif | |
950 temp = sock_read(asock, buf + count, size - (count + (buf - bufptr))); | |
951 count += temp; | |
952 #ifdef DNET | |
953 if (temp < 0) | |
954 #else | |
955 if (temp <= 0) | |
956 #endif /* DNET */ | |
957 { | |
958 #ifndef RWATCH | |
959 printf("2) Got read() of %d. Server is dead\n", temp); | |
960 #endif /* RWATCH */ | |
961 serverDead = 1; | |
962 return (0); | |
963 } | |
964 #ifdef SHORT_PACKETS | |
965 if (size == 0) /* for the SP_S_MESSAGE problem */ | |
966 goto computesize; | |
967 #endif | |
968 } | |
969 #ifdef UPDATE_SIZES | |
970 totalbytes += size; | |
971 packetbytes[*bufptr] += size; | |
972 #endif | |
973 #ifdef RECORDER | |
974 if (playback && (*bufptr == REC_UPDATE)) { | |
975 pb_update++; | |
976 me->p_tractor = bufptr[1]; | |
977 if (me->p_flags & PFPLOCK) | |
978 me->p_playerl = bufptr[2]; | |
979 else | |
980 me->p_planet = bufptr[2]; | |
981 /* printf("Read REC_UPDATE pseudo-packet!\n");*/ | |
982 } else | |
983 #endif | |
984 if (*bufptr >= 1 && | |
985 *bufptr < NUM_HANDLERS && | |
986 handlers[(int) *bufptr].handler != NULL) { | |
987 if (asock != udpSock || | |
988 (!drop_flag || *bufptr == SP_SEQUENCE || *bufptr == SP_SC_SEQUENCE)) { | |
989 if (asock == udpSock) | |
990 packets_received++; /* ping stuff */ | |
991 #ifdef RECORDER | |
992 if (recordGame) | |
993 recordPacket(bufptr, size); | |
994 #endif | |
995 #ifdef HANDLER_TIMES | |
996 gettimeofday(&htpre,0); | |
997 #endif | |
998 (*(handlers[(unsigned char)*bufptr].handler)) (bufptr); | |
999 #ifdef HANDLER_TIMES | |
1000 gettimeofday(&htpost,0); | |
1001 log_time(*bufptr, &htpre, &htpost); | |
1002 #endif | |
1003 /* printf("handled packet %d\n", (unsigned char)*bufptr); */ | |
1004 } else | |
1005 UDPDIAG(("Ignored type %d\n", *bufptr)); | |
1006 } else { | |
1007 printf("Handler for packet %d not installed...\n", *bufptr); | |
1008 } | |
1009 | |
1010 bufptr += size; | |
1011 if (bufptr > buf + BUFSIZ) { | |
1012 bcopy(buf + BUFSIZ, buf, BUFSIZ); | |
1013 if (count == BUFSIZ * 2) { | |
1014 #ifdef RECORDER | |
1015 if (playback) | |
1016 temp = 0; | |
1017 else | |
1018 #endif | |
1019 { | |
1020 #ifdef DNET | |
1021 temp = DNetServerPause(3, 0, asock); | |
1022 #else | |
1023 FD_ZERO(&readfds); | |
1024 FD_SET(asock, &readfds); | |
1025 /* readfds = 1<<asock; */ | |
1026 temp = select(32, &readfds, 0, 0, &timeout); | |
1027 #endif /* DNET */ | |
1028 } | |
1029 if (temp != 0) { | |
1030 temp = sock_read(asock, buf + BUFSIZ, BUFSIZ); | |
1031 count = BUFSIZ + temp; | |
1032 #ifdef DNET | |
1033 if (temp < 0) | |
1034 #else | |
1035 if (temp <= 0) | |
1036 #endif /* DNET */ | |
1037 { | |
1038 #ifndef RWATCH | |
1039 printf("3) Got read() of %d. Server is dead\n", temp); | |
1040 #endif /* RWATCH */ | |
1041 serverDead = 1; | |
1042 return (0); | |
1043 } | |
1044 } else { | |
1045 count = BUFSIZ; | |
1046 } | |
1047 } else { | |
1048 count -= BUFSIZ; | |
1049 } | |
1050 bufptr -= BUFSIZ; | |
1051 } | |
1052 } | |
1053 return (1); | |
1054 } | |
1055 | |
1056 #define SANITY_TORPNUM(idx) \ | |
1057 if ( (unsigned)(idx) >= ntorps*nplayers) { \ | |
1058 fprintf(stderr, "torp index %d out of bounds\n", (idx)); \ | |
1059 return; \ | |
1060 } | |
1061 | |
1062 #define SANITY_PNUM(idx) \ | |
1063 if ( (unsigned)(idx) >= nplayers) { \ | |
1064 fprintf(stderr, "player number %d out of bounds\n", (idx)); \ | |
1065 return; \ | |
1066 } | |
1067 | |
1068 #define SANITY_PHASNUM(idx) \ | |
1069 if ( (unsigned)(idx) >= nplayers*nphasers) { \ | |
1070 fprintf(stderr, "phaser number %d out of bounds\n", (idx)); \ | |
1071 return; \ | |
1072 } | |
1073 | |
1074 #define SANITY_PLASNUM(idx) \ | |
1075 if ( (unsigned)(idx) >= nplayers*nplasmas) { \ | |
1076 fprintf(stderr, "plasma number %d out of bounds\n", (idx)); \ | |
1077 return; \ | |
1078 } | |
1079 | |
1080 #define SANITY_THINGYNUM(idx) \ | |
1081 if ( (unsigned)(idx) >= npthingies*nplayers + ngthingies) { \ | |
1082 fprintf(stderr, "thingy index %x out of bounds\n", (idx)); \ | |
1083 return; \ | |
1084 } | |
1085 | |
1086 #define SANITY_PLANNUM(idx) \ | |
1087 if ( (unsigned)(idx) >= nplanets) { \ | |
1088 fprintf(stderr, "planet index %d out of bounds\n", (idx)); \ | |
1089 return; \ | |
1090 } | |
1091 | |
1092 #define SANITY_SHIPNUM(idx) \ | |
1093 if ( (unsigned)(idx) >= nshiptypes) { \ | |
1094 fprintf(stderr, "ship type %d out of bounds\n", (idx)); \ | |
1095 return; \ | |
1096 } | |
1097 | |
1098 | |
1099 static void | |
1100 handleTorp(packet) | |
1101 struct torp_spacket *packet; | |
1102 { | |
1103 struct torp *thetorp; | |
1104 | |
1105 SANITY_TORPNUM(ntohs(packet->tnum)); | |
1106 | |
1107 thetorp = &torps[ntohs(packet->tnum)]; | |
1108 thetorp->t_x = ntohl(packet->x); | |
1109 thetorp->t_y = ntohl(packet->y); | |
1110 thetorp->t_dir = packet->dir; | |
1111 | |
1112 #ifdef ROTATERACE | |
1113 if (rotate) { | |
1114 rotate_gcenter(&thetorp->t_x, &thetorp->t_y); | |
1115 rotate_dir(&thetorp->t_dir, rotate_deg); | |
1116 #endif | |
1117 #ifdef BORGTEST | |
1118 if (bd) | |
1119 bd_test_torp(ntohs(packet->tnum), thetorp); | |
1120 #endif | |
1121 } | |
1122 } | |
1123 | |
1124 | |
1125 static void | |
1126 handleTorpInfo(packet) | |
1127 struct torp_info_spacket *packet; | |
1128 { | |
1129 struct torp *thetorp; | |
1130 | |
1131 SANITY_TORPNUM(ntohs(packet->tnum)); | |
1132 | |
1133 thetorp = &torps[ntohs(packet->tnum)]; | |
1134 | |
1135 if (packet->status == TEXPLODE && thetorp->t_status == TFREE) { | |
1136 /* FAT: redundant explosion; don't update p_ntorp */ | |
1137 /* | |
1138 printf("texplode ignored\n"); | |
1139 */ | |
1140 return; | |
1141 } | |
1142 | |
1143 if (thetorp->t_status == TFREE && packet->status) { | |
1144 players[thetorp->t_owner].p_ntorp++; | |
1145 thetorp->frame = 0; | |
1146 #ifdef BORGTEST | |
1147 if (bd) | |
1148 bd_new_torp(ntohs(packet->tnum), thetorp); | |
1149 #endif | |
1150 | |
1151 } | |
1152 if (thetorp->t_status && packet->status == TFREE) { | |
1153 players[thetorp->t_owner].p_ntorp--; | |
1154 } | |
1155 thetorp->t_war = packet->war; | |
1156 | |
1157 if (packet->status != thetorp->t_status) { | |
1158 /* FAT: prevent explosion reset */ | |
1159 thetorp->t_status = packet->status; | |
1160 if (thetorp->t_status == TEXPLODE) { | |
1161 thetorp->t_fuse = NUMDETFRAMES; | |
1162 } | |
1163 } | |
1164 } | |
1165 | |
1166 static void | |
1167 handleStatus(packet) | |
1168 struct status_spacket *packet; | |
1169 { | |
1170 status->tourn = packet->tourn; | |
1171 status->armsbomb = ntohl(packet->armsbomb); | |
1172 status->planets = ntohl(packet->planets); | |
1173 status->kills = ntohl(packet->kills); | |
1174 status->losses = ntohl(packet->losses); | |
1175 status->time = ntohl(packet->time); | |
1176 status->timeprod = ntohl(packet->timeprod); | |
1177 } | |
1178 | |
1179 static void | |
1180 handleSelf(packet) | |
1181 struct you_spacket *packet; | |
1182 { | |
1183 SANITY_PNUM(packet->pnum); | |
1184 me = (ghoststart ? &players[ghost_pno] : &players[packet->pnum]); | |
1185 myship = (me->p_ship); | |
1186 mystats = &(me->p_stats); | |
1187 me->p_hostile = packet->hostile; | |
1188 me->p_swar = packet->swar; | |
1189 me->p_armies = packet->armies; | |
1190 me->p_flags = ntohl(packet->flags); | |
1191 me->p_damage = ntohl(packet->damage); | |
1192 me->p_shield = ntohl(packet->shield); | |
1193 me->p_fuel = ntohl(packet->fuel); | |
1194 me->p_etemp = ntohs(packet->etemp); | |
1195 me->p_wtemp = ntohs(packet->wtemp); | |
1196 me->p_whydead = ntohs(packet->whydead); | |
1197 me->p_whodead = ntohs(packet->whodead); | |
1198 status2->clock = (unsigned long) packet->pad2; | |
1199 status2->clock += ((unsigned long) packet->pad3) << 8; | |
1200 #ifdef INCLUDE_VISTRACT | |
1201 if (packet->tractor & 0x40) | |
1202 me->p_tractor = (short) packet->tractor & (~0x40); /* ATM - visible trac | |
1203 tors */ | |
1204 #ifdef nodef /* tmp */ | |
1205 else | |
1206 me->p_tractor = -1; | |
1207 #endif /* nodef */ | |
1208 #endif | |
1209 #ifdef SOUND | |
1210 S_HandlePFlags(); | |
1211 #endif | |
1212 | |
1213 } | |
1214 | |
1215 static void | |
1216 handlePlayer(packet) | |
1217 struct player_spacket *packet; | |
1218 { | |
1219 register struct player *pl; | |
1220 unsigned char newdir; | |
1221 | |
1222 SANITY_PNUM(packet->pnum); | |
1223 | |
1224 | |
1225 pl = &players[packet->pnum]; | |
1226 newdir = packet->dir; | |
1227 #ifdef ROTATERACE | |
1228 if (rotate) | |
1229 rotate_dir(&newdir, rotate_deg); | |
1230 #endif | |
1231 #ifdef CHECK_DROPPED | |
1232 /* Kludge to fix lost uncloak packets! [3/94] -JR */ | |
1233 if (pl->p_flags & PFCLOAK && pl->p_cloakphase >= (CLOAK_PHASES - 1)) { | |
1234 if (pl->p_dir != newdir) { /* always sends the same direction | |
1235 when cloaked! */ | |
1236 int i, plocked = 0; | |
1237 | |
1238 /* | |
1239 nplayers is for paradise, probably want MAX_PLAYERS for other | |
1240 clients | |
1241 */ | |
1242 for (i = 0; i < nplayers; i++) { /* except when someone has | |
1243 this person phasered :( */ | |
1244 if ((phasers[i].ph_status & PHHIT) && (phasers[i].ph_target == packet->pnum)) { | |
1245 plocked = 1; | |
1246 break; | |
1247 } | |
1248 } | |
1249 if (!plocked) { | |
1250 pl->p_flags &= ~(PFCLOAK); | |
1251 if (reportDroppedPackets) | |
1252 printf("Uncloak kludge, player %d\n", pl->p_no); | |
1253 } | |
1254 } | |
1255 } | |
1256 #endif | |
1257 pl->p_dir = newdir; | |
1258 pl->p_speed = packet->speed; | |
1259 pl->p_x = ntohl(packet->x); | |
1260 pl->p_y = ntohl(packet->y); | |
1261 if (pl == me) { | |
1262 extern int my_x, my_y; /* from shortcomm.c */ | |
1263 my_x = me->p_x; | |
1264 my_y = me->p_y; | |
1265 } | |
1266 redrawPlayer[packet->pnum] = 1; | |
1267 | |
1268 if (me == pl) { | |
1269 extern int my_x, my_y; /* short packets need unrotated co-ords! */ | |
1270 my_x = pl->p_x; | |
1271 my_y = pl->p_y; | |
1272 } | |
1273 #ifdef ROTATERACE | |
1274 if (rotate) { | |
1275 rotate_gcenter(&pl->p_x, &pl->p_y); | |
1276 } | |
1277 #endif | |
1278 | |
1279 } | |
1280 | |
1281 | |
1282 static void | |
1283 handleWarning(packet) | |
1284 struct warning_spacket *packet; | |
1285 { | |
1286 warning((char *) packet->mesg); | |
1287 } | |
1288 | |
1289 static void | |
1290 handleThingy(packet) | |
1291 struct thingy_spacket *packet; | |
1292 { | |
1293 struct thingy *thetorp; | |
1294 | |
1295 SANITY_THINGYNUM(ntohs(packet->tnum)); | |
1296 | |
1297 thetorp = &thingies[ntohs(packet->tnum)]; | |
1298 thetorp->t_x = ntohl(packet->x); | |
1299 thetorp->t_y = ntohl(packet->y); | |
1300 /* printf("drone at %d, %d\n", thetorp->t_x, thetorp->t_y); */ | |
1301 thetorp->t_dir = packet->dir; | |
1302 | |
1303 | |
1304 #ifdef ROTATERACE | |
1305 if (rotate) { | |
1306 rotate_gcenter(&thetorp->t_x, &thetorp->t_y); | |
1307 rotate_dir(&thetorp->t_dir, rotate_deg); | |
1308 } | |
1309 #endif | |
1310 | |
1311 if (thetorp->t_shape == SHP_WARP_BEACON) | |
1312 redrawall = 1; /* shoot, route has changed */ | |
1313 | |
1314 } | |
1315 | |
1316 static void | |
1317 handleThingyInfo(packet) | |
1318 struct thingy_info_spacket *packet; | |
1319 { | |
1320 struct thingy *thetorp; | |
1321 | |
1322 SANITY_THINGYNUM(ntohs(packet->tnum)); | |
1323 | |
1324 thetorp = &thingies[ntohs(packet->tnum)]; | |
1325 | |
1326 #if 1 | |
1327 thetorp->t_owner = ntohs(packet->owner); | |
1328 #else | |
1329 /* we have the gameparam packet now */ | |
1330 #endif | |
1331 | |
1332 if (thetorp->t_shape == SHP_WARP_BEACON) | |
1333 redrawall = 1; /* redraw the lines, I guess */ | |
1334 | |
1335 if (ntohs(packet->shape) == SHP_BOOM && thetorp->t_shape == SHP_BLANK) { | |
1336 /* FAT: redundant explosion; don't update p_ntorp */ | |
1337 /* | |
1338 printf("texplode ignored\n"); | |
1339 */ | |
1340 return; | |
1341 } | |
1342 | |
1343 if (thetorp->t_shape == SHP_BLANK && ntohs(packet->shape) != SHP_BLANK) { | |
1344 players[thetorp->t_owner].p_ndrone++; /* TSH */ | |
1345 } | |
1346 if (thetorp->t_shape != SHP_BLANK && ntohs(packet->shape) == SHP_BLANK) { | |
1347 players[thetorp->t_owner].p_ndrone--; /* TSH */ | |
1348 } | |
1349 thetorp->t_war = packet->war; | |
1350 | |
1351 if (ntohs(packet->shape) != thetorp->t_shape) { | |
1352 /* FAT: prevent explosion reset */ | |
1353 thetorp->t_shape = ntohs(packet->shape); | |
1354 if (thetorp->t_shape == SHP_BOOM || | |
1355 thetorp->t_shape == SHP_PBOOM) { | |
1356 thetorp->t_fuse = NUMDETFRAMES; | |
1357 } | |
1358 } | |
1359 } | |
1360 | |
1361 void | |
1362 sendShortPacket(type, state) | |
1363 char type, state; | |
1364 { | |
1365 struct speed_cpacket speedReq; | |
1366 | |
1367 speedReq.type = type; | |
1368 speedReq.speed = state; | |
1369 #ifdef UNIX_SOUND | |
1370 if (type == CP_SHIELD) play_sound (SND_SHIELD); /* Shields */ | |
1371 #endif | |
1372 sendServerPacket((struct player_spacket *) & speedReq); | |
1373 /* printf("Sending packet #%d\n",type); */ | |
1374 | |
1375 /* if we're sending in UDP mode, be prepared to force it */ | |
1376 if (commMode == COMM_UDP && udpClientSend >= 2) { | |
1377 switch (type) { | |
1378 case CP_SPEED: | |
1379 fSpeed = state | 0x100; | |
1380 break; | |
1381 case CP_DIRECTION: | |
1382 fDirection = state | 0x100; | |
1383 break; | |
1384 case CP_SHIELD: | |
1385 fShield = state | 0xa00; | |
1386 break; | |
1387 case CP_ORBIT: | |
1388 fOrbit = state | 0xa00; | |
1389 break; | |
1390 case CP_REPAIR: | |
1391 fRepair = state | 0xa00; | |
1392 break; | |
1393 case CP_CLOAK: | |
1394 fCloak = state | 0xa00; | |
1395 break; | |
1396 case CP_BOMB: | |
1397 fBomb = state | 0xa00; | |
1398 break; | |
1399 case CP_DOCKPERM: | |
1400 fDockperm = state | 0xa00; | |
1401 break; | |
1402 case CP_PLAYLOCK: | |
1403 fPlayLock = state | 0xa00; | |
1404 break; | |
1405 case CP_PLANLOCK: | |
1406 fPlanLock = state | 0xa00; | |
1407 break; | |
1408 case CP_BEAM: | |
1409 if (state == 1) | |
1410 fBeamup = 1 | 0x500; | |
1411 else | |
1412 fBeamdown = 2 | 0x500; | |
1413 break; | |
1414 } | |
1415 | |
1416 /* force weapons too? */ | |
1417 if (udpClientSend >= 3) { | |
1418 switch (type) { | |
1419 case CP_PHASER: | |
1420 fPhaser = state | 0x100; | |
1421 break; | |
1422 case CP_PLASMA: | |
1423 fPlasma = state | 0x100; | |
1424 break; | |
1425 } | |
1426 } | |
1427 } | |
1428 } | |
1429 | |
1430 void | |
1431 sendServerPacket(packet) | |
1432 /* Pick a random type for the packet */ | |
1433 struct player_spacket *packet; | |
1434 { | |
1435 int size; | |
1436 | |
1437 #ifdef RWATCH | |
1438 return; | |
1439 #endif /* RWATCH */ | |
1440 | |
1441 if (serverDead) | |
1442 return; | |
1443 size = size_of_cpacket(packet); | |
1444 if (size < 1) { | |
1445 printf("Attempt to send strange packet %d!\n", packet->type); | |
1446 return; | |
1447 } | |
1448 #ifdef SHOW_SEND | |
1449 printf("sending packet type %d, size %d\n", packet->type, | |
1450 size); | |
1451 #endif /* SHOW_SEND */ | |
1452 #ifdef PACKET_LIGHTS | |
1453 light_send(); | |
1454 #endif /* PACKET_LIGHTS */ | |
1455 #ifdef SIZE_LOGGING | |
1456 send_total += size; | |
1457 #endif /* SIZE_LOGGING */ | |
1458 if (commMode == COMM_UDP) { | |
1459 /* for now, just sent everything via TCP */ | |
1460 } | |
1461 if (commMode == COMM_TCP || !udpClientSend) { | |
1462 /* special case for verify packet */ | |
1463 if (packet->type == CP_UDP_REQ) { | |
1464 if (((struct udp_req_cpacket *) packet)->request == COMM_VERIFY) | |
1465 goto send_udp; | |
1466 } | |
1467 /* | |
1468 business as usual (or player has turned off UDP transmission) | |
1469 */ | |
1470 if (gwrite(sock, (char *) packet, size) != size) { | |
1471 printf("gwrite failed. Server must be dead\n"); | |
1472 serverDead = 1; | |
1473 } | |
1474 } else { | |
1475 /* | |
1476 UDP stuff | |
1477 */ | |
1478 switch (packet->type) { | |
1479 case CP_SPEED: | |
1480 case CP_DIRECTION: | |
1481 case CP_PHASER: | |
1482 case CP_PLASMA: | |
1483 case CP_TORP: | |
1484 case CP_QUIT: | |
1485 case CP_PRACTR: | |
1486 case CP_REPAIR: | |
1487 case CP_ORBIT: | |
1488 case CP_BOMB: | |
1489 case CP_BEAM: | |
1490 case CP_DET_TORPS: | |
1491 case CP_DET_MYTORP: | |
1492 case CP_TRACTOR: | |
1493 case CP_REPRESS: | |
1494 case CP_COUP: | |
1495 case CP_DOCKPERM: | |
1496 case CP_SCAN: | |
1497 case CP_PING_RESPONSE: | |
1498 case CP_CLOAK: | |
1499 case CP_SHIELD: | |
1500 case CP_PLANLOCK: | |
1501 /* | |
1502 these are non-critical but don't expire, send with TCP | |
1503 [BDyess] | |
1504 */ | |
1505 /* case CP_REFIT: */ | |
1506 /* case CP_PLAYLOCK: */ | |
1507 /* non-critical stuff, use UDP */ | |
1508 send_udp: | |
1509 packets_sent++; /* ping stuff */ | |
1510 | |
1511 V_UDPDIAG(("Sent %d on UDP port\n", packet->type)); | |
1512 if (gwrite(udpSock, (char *) packet, size) != size) { | |
1513 UDPDIAG(("gwrite on UDP failed. Closing UDP connection\n")); | |
1514 warning("UDP link severed"); | |
1515 /* serverDead=1; */ | |
1516 commModeReq = commMode = COMM_TCP; | |
1517 commStatus = STAT_CONNECTED; | |
1518 commSwitchTimeout = 0; | |
1519 if (udpWin) { | |
1520 udprefresh(UDP_STATUS); | |
1521 udprefresh(UDP_CURRENT); | |
1522 } | |
1523 if (udpSock >= 0) | |
1524 closeUdpConn(); | |
1525 } | |
1526 break; | |
1527 | |
1528 default: | |
1529 /* critical stuff, use TCP */ | |
1530 if (gwrite(sock, (char *) packet, size) != size) { | |
1531 printf("gwrite failed. Server must be dead\n"); | |
1532 serverDead = 1; | |
1533 } | |
1534 } | |
1535 } | |
1536 } | |
1537 | |
1538 static void | |
1539 handlePlanet(packet) | |
1540 struct planet_spacket *packet; | |
1541 { | |
1542 struct planet *plan; | |
1543 /* FAT: prevent excessive redraw */ | |
1544 int redraw = 0; | |
1545 #ifdef HOCKEY | |
1546 int hockey_update = 0; | |
1547 #endif /*HOCKEY*/ | |
1548 | |
1549 SANITY_PLANNUM(packet->pnum); | |
1550 | |
1551 plan = &planets[packet->pnum]; | |
1552 if (plan->pl_owner != packet->owner) { | |
1553 redraw = 1; | |
1554 #ifdef HOCKEY | |
1555 hockey_update = 1; | |
1556 #endif | |
1557 } | |
1558 plan->pl_owner = packet->owner; | |
1559 | |
1560 if (plan->pl_owner < (1 << 0) || plan->pl_owner > (1 << (number_of_teams - 1))) | |
1561 plan->pl_owner = NOBODY; | |
1562 | |
1563 if (plan->pl_info != packet->info) | |
1564 redraw = 1; | |
1565 plan->pl_info = packet->info; | |
1566 /* Redraw the planet because it was updated by server */ | |
1567 | |
1568 if (plan->pl_flags != (int) ntohs(packet->flags)) | |
1569 redraw = 1; | |
1570 plan->pl_flags = (unsigned short) ntohs(packet->flags); | |
1571 | |
1572 if (plan->pl_armies != ntohl(packet->armies)) | |
1573 redraw = 1; | |
1574 | |
1575 plan->pl_armies = ntohl(packet->armies); | |
1576 if (plan->pl_info == 0) { | |
1577 plan->pl_owner = NOBODY; | |
1578 } | |
1579 if (redraw) { | |
1580 plan->pl_flags |= PLREDRAW; | |
1581 pl_update[packet->pnum].plu_update = 1; /* used to mean the planet | |
1582 had moved, now set as a | |
1583 sign we need to erase AND | |
1584 redraw. -JR */ | |
1585 pl_update[packet->pnum].plu_x = planets[packet->pnum].pl_x; | |
1586 pl_update[packet->pnum].plu_y = planets[packet->pnum].pl_y; | |
1587 if (infomapped && infotype == PLANETTYPE && | |
1588 ((struct planet *) infothing)->pl_no == packet->pnum) | |
1589 infoupdate = 1; | |
1590 #ifdef HOCKEY | |
1591 if(hockey_update && hockey) hockeyInit(); | |
1592 #endif /*HOCKEY*/ | |
1593 } | |
1594 } | |
1595 | |
1596 static void | |
1597 handlePhaser(packet) | |
1598 struct phaser_spacket *packet; | |
1599 { | |
1600 struct phaser *phas; | |
1601 | |
1602 SANITY_PHASNUM(packet->pnum); | |
1603 | |
1604 phas = &phasers[packet->pnum]; | |
1605 #ifdef CHECK_DROPPED | |
1606 /* can't fire weapons cloaked, this guy must be uncloaked.. */ | |
1607 /* applying this to torps is trickier... -JR */ | |
1608 if (packet->status != PHFREE) { | |
1609 if (reportDroppedPackets && (players[packet->pnum].p_flags & PFCLOAK)) | |
1610 printf("Dropped uncloak, player %d. (fired phaser)\n", packet->pnum); | |
1611 players[packet->pnum].p_flags &= ~(PFCLOAK); | |
1612 } else { | |
1613 if (longest_ph_fuse < phas->ph_fuse) | |
1614 longest_ph_fuse = phas->ph_fuse; | |
1615 } | |
1616 #endif | |
1617 phas->ph_status = packet->status; | |
1618 phas->ph_dir = packet->dir; | |
1619 phas->ph_x = ntohl(packet->x); | |
1620 phas->ph_y = ntohl(packet->y); | |
1621 phas->ph_target = ntohl(packet->target); | |
1622 phas->ph_fuse = 0; | |
1623 | |
1624 #ifdef ROTATERACE | |
1625 if (rotate) { | |
1626 rotate_gcenter(&phas->ph_x, &phas->ph_y); | |
1627 rotate_dir(&phas->ph_dir, rotate_deg); | |
1628 } | |
1629 #endif | |
1630 #ifdef SOUND | |
1631 if ((me->p_no == packet->pnum) && (packet->status != PHFREE)) { | |
1632 S_PlaySound(S_PHASER); | |
1633 } | |
1634 #endif | |
1635 #ifdef UNIX_SOUND | |
1636 if ((me->p_no == packet->pnum) && (packet->status != PHFREE)) { | |
1637 play_sound(SND_PHASER); /* Phasers */ | |
1638 } | |
1639 #endif | |
1640 } | |
1641 | |
1642 void | |
1643 handleMessage(packet) | |
1644 struct mesg_spacket *packet; | |
1645 { | |
1646 if ((int) packet->m_from >= nplayers) | |
1647 packet->m_from = 255; | |
1648 dmessage(packet->mesg, packet->m_flags, packet->m_from, packet->m_recpt); | |
1649 } | |
1650 | |
1651 | |
1652 static void | |
1653 handleQueue(packet) | |
1654 struct queue_spacket *packet; | |
1655 { | |
1656 queuePos = ntohs(packet->pos); | |
1657 /* printf("Receiving queue position %d\n",queuePos); */ | |
1658 } | |
1659 | |
1660 static void | |
1661 handleEmpty(ptr) | |
1662 char *ptr; | |
1663 { | |
1664 printf("Unknown packet type: %d\n", *ptr); | |
1665 return; | |
1666 } | |
1667 | |
1668 void | |
1669 sendTeamReq(team, ship) | |
1670 int team, ship; | |
1671 { | |
1672 struct outfit_cpacket outfitReq; | |
1673 | |
1674 outfitReq.type = CP_OUTFIT; | |
1675 outfitReq.team = team; | |
1676 outfitReq.ship = ship; | |
1677 sendServerPacket((struct player_spacket *) & outfitReq); | |
1678 } | |
1679 | |
1680 static void | |
1681 handlePickok(packet) | |
1682 struct pickok_spacket *packet; | |
1683 { | |
1684 pickOk = packet->state; | |
1685 #ifdef RECORDER | |
1686 if (playback) { /* added when the packet is recorded. */ | |
1687 extern int lastTeamReq; | |
1688 lastTeamReq = packet->pad2; | |
1689 } | |
1690 #endif | |
1691 } | |
1692 | |
1693 void | |
1694 sendLoginReq(name, pass, login, query) | |
1695 char *name, *pass; | |
1696 char *login; | |
1697 char query; | |
1698 { | |
1699 struct login_cpacket packet; | |
1700 | |
1701 strcpy(packet.name, name); | |
1702 strcpy(packet.password, pass); | |
1703 if (strlen(login) > 15) | |
1704 login[15] = 0; | |
1705 strcpy(packet.login, login); | |
1706 packet.type = CP_LOGIN; | |
1707 packet.query = query; | |
1708 packet.pad2 = 0x69; /* added 1/19/93 KAO */ | |
1709 packet.pad3 = 0x43; /* added 1/19/93 KAO *//* was 0x42 3/2/93 */ | |
1710 sendServerPacket((struct player_spacket *) & packet); | |
1711 } | |
1712 | |
1713 static void | |
1714 handleLogin(packet) | |
1715 struct login_spacket *packet; | |
1716 { | |
1717 | |
1718 | |
1719 loginAccept = packet->accept; | |
1720 if ((packet->pad2 == 69) && (packet->pad3 == 42)) | |
1721 paradise = 1; | |
1722 else { | |
1723 /*nshiptypes = 8;*/ | |
1724 nplayers=20; | |
1725 nplanets=40; | |
1726 } | |
1727 if (packet->accept) { | |
1728 | |
1729 /* we no longer accept keymaps from the server */ | |
1730 | |
1731 mystats->st_flags = ntohl(packet->flags); | |
1732 keeppeace = (me->p_stats.st_flags / ST_KEEPPEACE) & 1; | |
1733 } | |
1734 } | |
1735 | |
1736 void | |
1737 sendTractorReq(state, pnum) | |
1738 char state; | |
1739 char pnum; | |
1740 { | |
1741 struct tractor_cpacket tractorReq; | |
1742 | |
1743 tractorReq.type = CP_TRACTOR; | |
1744 tractorReq.state = state; | |
1745 tractorReq.pnum = pnum; | |
1746 sendServerPacket((struct player_spacket *) & tractorReq); | |
1747 | |
1748 if (state) | |
1749 fTractor = pnum | 0x40; | |
1750 else | |
1751 fTractor = 0; | |
1752 } | |
1753 | |
1754 void | |
1755 sendRepressReq(state, pnum) | |
1756 char state; | |
1757 char pnum; | |
1758 { | |
1759 struct repress_cpacket repressReq; | |
1760 | |
1761 repressReq.type = CP_REPRESS; | |
1762 repressReq.state = state; | |
1763 repressReq.pnum = pnum; | |
1764 sendServerPacket((struct player_spacket *) & repressReq); | |
1765 | |
1766 if (state) | |
1767 fRepress = pnum | 0x40; | |
1768 else | |
1769 fRepress = 0; | |
1770 } | |
1771 | |
1772 void | |
1773 sendDetMineReq(torp) | |
1774 short torp; | |
1775 { | |
1776 struct det_mytorp_cpacket detReq; | |
1777 | |
1778 detReq.type = CP_DET_MYTORP; | |
1779 detReq.tnum = htons(torp); | |
1780 sendServerPacket((struct player_spacket *) & detReq); | |
1781 } | |
1782 | |
1783 static void | |
1784 handlePlasmaInfo(packet) | |
1785 struct plasma_info_spacket *packet; | |
1786 { | |
1787 struct plasmatorp *thetorp; | |
1788 | |
1789 SANITY_PLASNUM(ntohs(packet->pnum)); | |
1790 | |
1791 thetorp = &plasmatorps[ntohs(packet->pnum)]; | |
1792 if (packet->status == PTEXPLODE && thetorp->pt_status == PTFREE) { | |
1793 /* FAT: redundant explosion; don't update p_nplasmatorp */ | |
1794 return; | |
1795 } | |
1796 if (!thetorp->pt_status && packet->status) { | |
1797 players[thetorp->pt_owner].p_nplasmatorp++; | |
1798 #ifdef UNIX_SOUND | |
1799 play_sound (SND_PLASMA); /* Plasma */ | |
1800 #endif | |
1801 } | |
1802 if (thetorp->pt_status && !packet->status) { | |
1803 players[thetorp->pt_owner].p_nplasmatorp--; | |
1804 } | |
1805 thetorp->pt_war = packet->war; | |
1806 if (thetorp->pt_status != packet->status) { | |
1807 /* FAT: prevent explosion timer from being reset */ | |
1808 thetorp->pt_status = packet->status; | |
1809 if (thetorp->pt_status == PTEXPLODE) { | |
1810 thetorp->pt_fuse = NUMDETFRAMES; | |
1811 } | |
1812 } | |
1813 } | |
1814 | |
1815 static void | |
1816 handlePlasma(packet) | |
1817 struct plasma_spacket *packet; | |
1818 { | |
1819 struct plasmatorp *thetorp; | |
1820 | |
1821 SANITY_PLASNUM(ntohs(packet->pnum)); | |
1822 | |
1823 thetorp = &plasmatorps[ntohs(packet->pnum)]; | |
1824 thetorp->pt_x = ntohl(packet->x); | |
1825 thetorp->pt_y = ntohl(packet->y); | |
1826 | |
1827 #ifdef ROTATERACE | |
1828 if (rotate) { | |
1829 rotate_gcenter(&thetorp->pt_x, &thetorp->pt_y); | |
1830 } | |
1831 #endif | |
1832 } | |
1833 | |
1834 static void | |
1835 handleFlags(packet) | |
1836 struct flags_spacket *packet; | |
1837 { | |
1838 SANITY_PNUM(packet->pnum); | |
1839 | |
1840 if (players[packet->pnum].p_flags != ntohl(packet->flags) || | |
1841 players[packet->pnum].p_tractor != ((short) packet->tractor & (~0x40))) { | |
1842 /* FAT: prevent redundant player update */ | |
1843 redrawPlayer[packet->pnum] = 1; | |
1844 } else | |
1845 return; | |
1846 | |
1847 #ifdef CHECK_DROPPED | |
1848 /* TEST */ | |
1849 /* For the dropped uncloak kludge, completely ignore uncloaks :-) */ | |
1850 /* if(players[packet->pnum].p_flags & PFCLOAK) packet->flags |= htonl(PFCLOAK);*/ | |
1851 /* TEST */ | |
1852 /* when a player cloaks, clear his phaser */ | |
1853 if (ntohl(packet->flags) & PFCLOAK) { | |
1854 if (phasers[packet->pnum].ph_status != PFREE) { | |
1855 if (reportDroppedPackets) | |
1856 printf("Lost phaser free packet, player %d. (cloaked)\n", packet->pnum); | |
1857 phasers[packet->pnum].ph_status = PHFREE; | |
1858 phasers[packet->pnum].ph_fuse = 0; | |
1859 } | |
1860 } | |
1861 #endif | |
1862 | |
1863 players[packet->pnum].p_flags = ntohl(packet->flags); | |
1864 #ifdef INCLUDE_VISTRACT | |
1865 if (packet->tractor & 0x40) | |
1866 players[packet->pnum].p_tractor = (short) packet->tractor & (~0x40); /* ATM - visible | |
1867 tractors */ | |
1868 else | |
1869 #endif /* INCLUDE_VISTRACT */ | |
1870 players[packet->pnum].p_tractor = -1; | |
1871 } | |
1872 | |
1873 static void | |
1874 handleKills(packet) | |
1875 struct kills_spacket *packet; | |
1876 { | |
1877 | |
1878 SANITY_PNUM(packet->pnum); | |
1879 | |
1880 if (players[packet->pnum].p_kills != ntohl(packet->kills) / 100.0) { | |
1881 players[packet->pnum].p_kills = ntohl(packet->kills) / 100.0; | |
1882 /* FAT: prevent redundant player update */ | |
1883 updatePlayer[packet->pnum] |= ALL_UPDATE; | |
1884 if (infomapped && infotype == PLAYERTYPE && | |
1885 ((struct player *) infothing)->p_no == packet->pnum) | |
1886 infoupdate = 1; | |
1887 #ifdef PLPROF | |
1888 printf("Got handleKills for %d\n", packet->pnum); | |
1889 #endif /* PLPROF */ | |
1890 #ifdef ARMY_SLIDER | |
1891 if (me == &players[packet->pnum]) { | |
1892 calibrate_stats(); | |
1893 redrawStats(); | |
1894 } | |
1895 #endif /* ARMY_SLIDER */ | |
1896 } | |
1897 } | |
1898 | |
1899 static void | |
1900 handlePStatus(packet) | |
1901 struct pstatus_spacket *packet; | |
1902 { | |
1903 SANITY_PNUM(packet->pnum); | |
1904 | |
1905 if (packet->status == PEXPLODE) { | |
1906 players[packet->pnum].p_explode = 0; | |
1907 } | |
1908 /* | |
1909 Ignore DEAD status. Instead, we treat it as PEXPLODE. This gives us | |
1910 time to animate all the frames necessary for the explosions at our own | |
1911 pace. | |
1912 */ | |
1913 if (packet->status == PDEAD) { | |
1914 packet->status = PEXPLODE; | |
1915 } | |
1916 if (players[packet->pnum].p_status != packet->status) { | |
1917 players[packet->pnum].p_status = packet->status; | |
1918 redrawPlayer[packet->pnum] = 1; | |
1919 #ifdef PLPROF | |
1920 printf("Got handlePStatus for %d\n", packet->pnum); | |
1921 #endif /* PLPROF */ | |
1922 updatePlayer[packet->pnum] |= ALL_UPDATE; | |
1923 if (infomapped && infotype == PLAYERTYPE && | |
1924 ((struct player *) infothing)->p_no == packet->pnum) | |
1925 infoupdate = 1; | |
1926 #ifdef CHECK_DROPPED | |
1927 if (players[packet->pnum].p_status == POUTFIT) { | |
1928 int i; | |
1929 /* clear phasers on this guy */ | |
1930 #if 0 | |
1931 for (i = 0; i < nplayers; i++) { | |
1932 if (phasers[i].ph_target == packet->pnum && phasers[i].ph_status == PHHIT) { | |
1933 if (reportDroppedPackets) | |
1934 printf("Lost phaser free packet, player %d->player %d (target not alive)\n", | |
1935 i, packet->pnum); | |
1936 phasers[i].ph_status = PHFREE; | |
1937 } | |
1938 } | |
1939 #endif | |
1940 if (phasers[packet->pnum].ph_status != PHFREE) { | |
1941 if (reportDroppedPackets) | |
1942 printf("Lost phaser free packet, player %d (outfitting)\n", packet->pnum); | |
1943 phasers[packet->pnum].ph_status = PHFREE; /* and his own */ | |
1944 } | |
1945 if (reportDroppedPackets && players[packet->pnum].p_ntorp > 1) | |
1946 /* only report it on 2 or more left, always clear it. */ | |
1947 printf("Lost torp free packet, (%d torps) player %d (outfitting)\n", | |
1948 players[packet->pnum].p_ntorp, packet->pnum); | |
1949 players[packet->pnum].p_ntorp = 0; | |
1950 for (i = packet->pnum * ntorps; i < (packet->pnum + 1) * ntorps; i++) { | |
1951 torps[i].t_status = TFREE; | |
1952 } | |
1953 } | |
1954 #endif | |
1955 } | |
1956 } | |
1957 | |
1958 static void | |
1959 handleMotd(packet) | |
1960 struct motd_spacket *packet; | |
1961 { | |
1962 newMotdLine((char *) packet->line); | |
1963 } | |
1964 | |
1965 void | |
1966 sendMessage(mes, group, indiv) | |
1967 char *mes; | |
1968 int group, indiv; | |
1969 { | |
1970 struct mesg_cpacket mesPacket; | |
1971 | |
1972 #ifdef SHORT_PACKETS | |
1973 if (recv_short) { | |
1974 int size; | |
1975 size = strlen(mes); | |
1976 size += 5; /* 1 for '\0', 4 packetheader */ | |
1977 if ((size % 4) != 0) | |
1978 size += (4 - (size % 4)); | |
1979 mesPacket.pad1 = (char) size; | |
1980 | |
1981 /* | |
1982 OH SHIT!!!! sizes[CP_S_MESSAGE] = size; | |
1983 */ | |
1984 | |
1985 mesPacket.type = CP_S_MESSAGE; | |
1986 } else | |
1987 #endif | |
1988 mesPacket.type = CP_MESSAGE; | |
1989 mesPacket.group = group; | |
1990 mesPacket.indiv = indiv; | |
1991 strcpy(mesPacket.mesg, mes); | |
1992 sendServerPacket((struct player_spacket *) & mesPacket); | |
1993 } | |
1994 | |
1995 static void | |
1996 handleMask(packet) | |
1997 struct mask_spacket *packet; | |
1998 { | |
1999 tournMask = packet->mask; | |
2000 } | |
2001 | |
2002 void | |
2003 sendOptionsPacket() | |
2004 { | |
2005 struct options_cpacket optPacket; | |
2006 register int i; | |
2007 long flags; | |
2008 | |
2009 optPacket.type = CP_OPTIONS; | |
2010 flags = ( | |
2011 ST_NOBITMAPS * (!sendmotdbitmaps) + | |
2012 ST_KEEPPEACE * keeppeace + | |
2013 0 | |
2014 ); | |
2015 optPacket.flags = htonl(flags); | |
2016 /* copy the keymap and make sure no ctrl chars are sent [BDyess] */ | |
2017 for (i = 32; i < 128; i++) { | |
2018 optPacket.keymap[i - 32] = | |
2019 (myship->s_keymap[i] & 128) ? i : myship->s_keymap[i]; | |
2020 } | |
2021 /* bcopy(mystats->st_keymap+32, optPacket.keymap,96); */ | |
2022 sendServerPacket((struct player_spacket *) & optPacket); | |
2023 } | |
2024 | |
2025 static void | |
2026 pickSocket(old) | |
2027 int old; | |
2028 { | |
2029 int newsocket; | |
2030 struct socket_cpacket sockPack; | |
2031 #ifdef RWATCH | |
2032 nextSocket = old; | |
2033 #else | |
2034 newsocket = (getpid() & 32767); | |
2035 if (ghoststart) | |
2036 nextSocket = old; | |
2037 while (newsocket < 2048 || newsocket == old) { | |
2038 newsocket = (newsocket + 10687) & 32767; | |
2039 } | |
2040 sockPack.type = CP_SOCKET; | |
2041 sockPack.socket = htonl(newsocket); | |
2042 sockPack.version = (char) SOCKVERSION; | |
2043 sockPack.udp_version = (char) UDPVERSION; | |
2044 sendServerPacket((struct player_spacket *) & sockPack); | |
2045 /* Did we get new socket # sent? */ | |
2046 if (serverDead) | |
2047 return; | |
2048 nextSocket = newsocket; | |
2049 #endif /* RWATCH */ | |
2050 } | |
2051 | |
2052 static void | |
2053 handleBadVersion(packet) | |
2054 struct badversion_spacket *packet; | |
2055 { | |
2056 switch (packet->why) { | |
2057 case 0: | |
2058 printf("Sorry, this is an invalid client version.\n"); | |
2059 printf("You need a new version of the client code.\n"); | |
2060 break; | |
2061 default: | |
2062 printf("Sorry, but you cannot play xtrek now.\n"); | |
2063 printf("Try again later.\n"); | |
2064 break; | |
2065 } | |
2066 EXIT(1); | |
2067 } | |
2068 | |
2069 int | |
2070 gwrite(fd, buf, bytes) | |
2071 int fd; | |
2072 char *buf; | |
2073 register int bytes; | |
2074 { | |
2075 long orig = bytes; | |
2076 register long n; | |
2077 #ifdef RECORDER | |
2078 if (playback) /* pretend all is well */ | |
2079 return (bytes); | |
2080 #endif | |
2081 while (bytes) { | |
2082 n = sock_write(fd, buf, bytes); | |
2083 if (n < 0) { | |
2084 if (fd == udpSock) { | |
2085 fprintf(stderr, "Tried to write %d, 0x%x, %d\n", | |
2086 fd, (unsigned int) buf, bytes); | |
2087 perror("write"); | |
2088 printUdpInfo(); | |
2089 } | |
2090 return (-1); | |
2091 } | |
2092 bytes -= n; | |
2093 buf += n; | |
2094 } | |
2095 return (orig); | |
2096 } | |
2097 | |
2098 int | |
2099 sock_read(sock, data, size) | |
2100 int sock, size; | |
2101 char *data; | |
2102 { | |
2103 #ifdef RECORDER | |
2104 if (playback) | |
2105 return readRecorded(sock, data, size); | |
2106 #endif | |
2107 | |
2108 #ifndef AMIGA | |
2109 return read(sock, data, size); | |
2110 #else | |
2111 #ifdef DNET | |
2112 return DNet_Read(sock, data, size); | |
2113 #else | |
2114 /* NET_SOCKETS code here */ | |
2115 /* No idea if this works, old version had it: */ | |
2116 return recv(sock, data, size, 0); | |
2117 #endif /* DNET */ | |
2118 #endif /* AMIGA */ | |
2119 } | |
2120 | |
2121 static void | |
2122 handleHostile(packet) | |
2123 struct hostile_spacket *packet; | |
2124 { | |
2125 register struct player *pl; | |
2126 | |
2127 SANITY_PNUM(packet->pnum); | |
2128 | |
2129 pl = &players[packet->pnum]; | |
2130 if (pl->p_swar != packet->war || | |
2131 pl->p_hostile != packet->hostile) { | |
2132 /* FAT: prevent redundant player update & redraw */ | |
2133 pl->p_swar = packet->war; | |
2134 pl->p_hostile = packet->hostile; | |
2135 /* updatePlayer[packet->pnum]=1; why? */ | |
2136 redrawPlayer[packet->pnum] = 1; | |
2137 } | |
2138 } | |
2139 | |
2140 static void | |
2141 handlePlyrLogin(packet) | |
2142 struct plyr_login_spacket *packet; | |
2143 { | |
2144 register struct player *pl; | |
2145 | |
2146 SANITY_PNUM(packet->pnum); | |
2147 | |
2148 #ifdef PLPROF | |
2149 printf("Got handlPlyrLogin for %d\n", packet->pnum); | |
2150 #endif /* PLPROF */ | |
2151 updatePlayer[packet->pnum] |= ALL_UPDATE; | |
2152 pl = &players[packet->pnum]; | |
2153 | |
2154 strcpy(pl->p_name, packet->name); | |
2155 strcpy(pl->p_monitor, packet->monitor); | |
2156 strcpy(pl->p_login, packet->login); | |
2157 pl->p_stats.st_rank = packet->rank; | |
2158 if (packet->pnum == me->p_no) { | |
2159 /* This is me. Set some stats */ | |
2160 if (lastRank == -1) { | |
2161 if (loggedIn) { | |
2162 lastRank = packet->rank; | |
2163 } | |
2164 } else { | |
2165 if (lastRank != packet->rank) { | |
2166 lastRank = packet->rank; | |
2167 promoted = 1; | |
2168 } | |
2169 } | |
2170 } | |
2171 } | |
2172 | |
2173 static void | |
2174 handleStats(packet) | |
2175 struct stats_spacket *packet; | |
2176 { | |
2177 register struct player *pl; | |
2178 | |
2179 SANITY_PNUM(packet->pnum); | |
2180 | |
2181 #ifdef PLPROF | |
2182 printf("Got handleStats for %d\n", packet->pnum); | |
2183 #endif /* PLPROF */ | |
2184 updatePlayer[packet->pnum] |= LARGE_UPDATE; | |
2185 if (infomapped && infotype == PLAYERTYPE && | |
2186 ((struct player *) infothing)->p_no == packet->pnum) | |
2187 infoupdate = 1; | |
2188 pl = &players[packet->pnum]; | |
2189 pl->p_stats.st_tkills = ntohl(packet->tkills); | |
2190 pl->p_stats.st_tlosses = ntohl(packet->tlosses); | |
2191 pl->p_stats.st_kills = ntohl(packet->kills); | |
2192 pl->p_stats.st_losses = ntohl(packet->losses); | |
2193 pl->p_stats.st_tticks = ntohl(packet->tticks); | |
2194 pl->p_stats.st_tplanets = ntohl(packet->tplanets); | |
2195 pl->p_stats.st_tarmsbomb = ntohl(packet->tarmies); | |
2196 pl->p_stats.st_sbkills = ntohl(packet->sbkills); | |
2197 pl->p_stats.st_sblosses = ntohl(packet->sblosses); | |
2198 pl->p_stats.st_armsbomb = ntohl(packet->armies); | |
2199 pl->p_stats.st_planets = ntohl(packet->planets); | |
2200 pl->p_stats.st_maxkills = ntohl(packet->maxkills) / 100.0; | |
2201 pl->p_stats.st_sbmaxkills = ntohl(packet->sbmaxkills) / 100.0; | |
2202 } | |
2203 | |
2204 static void | |
2205 handlePlyrInfo(packet) | |
2206 struct plyr_info_spacket *packet; | |
2207 { | |
2208 register struct player *pl; | |
2209 static int lastship = -1; | |
2210 | |
2211 SANITY_PNUM(packet->pnum); | |
2212 | |
2213 #ifdef PLPROF | |
2214 printf("Got PlyrInfo for %d\n", packet->pnum); | |
2215 #endif /* PLPROF */ | |
2216 updatePlayer[packet->pnum] |= ALL_UPDATE; | |
2217 if (infomapped && infotype == PLAYERTYPE && | |
2218 ((struct player *) infothing)->p_no == packet->pnum) | |
2219 infoupdate = 1; | |
2220 pl = &players[packet->pnum]; | |
2221 pl->p_ship = getship(packet->shiptype); | |
2222 if (packet->pnum == me->p_no && currentship != packet->shiptype) { | |
2223 currentship = packet->shiptype; | |
2224 /* sendOptionsPacket(); */ | |
2225 } | |
2226 pl->p_teami = mask_to_idx(packet->team); | |
2227 pl->p_mapchars[0] = teaminfo[pl->p_teami].letter; | |
2228 /* printf("team: %d, letter: %c\n",pl->p_teami,pl->p_mapchars[0]); */ | |
2229 pl->p_mapchars[1] = shipnos[pl->p_no]; | |
2230 if (me == pl && lastship != currentship) { | |
2231 lastship = currentship; | |
2232 redrawTstats(); | |
2233 calibrate_stats(); | |
2234 redrawStats(); /* tsh */ | |
2235 } | |
2236 redrawPlayer[packet->pnum] = 1; | |
2237 } | |
2238 | |
2239 void | |
2240 sendUpdatePacket(speed) | |
2241 long speed; | |
2242 { | |
2243 struct updates_cpacket packet; | |
2244 | |
2245 packet.type = CP_UPDATES; | |
2246 timerDelay = speed; | |
2247 packet.usecs = htonl(speed); | |
2248 sendServerPacket((struct player_spacket *) & packet); | |
2249 #ifdef DEBUG | |
2250 printf("sent request for an update every %d microseconds (%d/sec)\n",speed,1000000/speed); | |
2251 #endif | |
2252 } | |
2253 | |
2254 static void | |
2255 handlePlanetLoc(packet) | |
2256 struct planet_loc_spacket *packet; | |
2257 { | |
2258 struct planet *pl; | |
2259 | |
2260 SANITY_PLANNUM(packet->pnum); | |
2261 | |
2262 pl = &planets[packet->pnum]; | |
2263 pl_update[packet->pnum].plu_x = pl->pl_x; | |
2264 pl_update[packet->pnum].plu_y = pl->pl_y; | |
2265 | |
2266 if (pl_update[packet->pnum].plu_update != -1) { | |
2267 pl_update[packet->pnum].plu_update = 1; | |
2268 /* | |
2269 printf("update: %s, old (%d,%d) new (%d,%d)\n", pl->pl_name, | |
2270 pl->pl_x, pl->pl_y, ntohl(packet->x),ntohl(packet->y)); | |
2271 */ | |
2272 } else { | |
2273 pl_update[packet->pnum].plu_update = 0; | |
2274 pl_update[packet->pnum].plu_x = ntohl(packet->x); | |
2275 pl_update[packet->pnum].plu_y = ntohl(packet->y); | |
2276 } | |
2277 pl->pl_x = ntohl(packet->x); | |
2278 pl->pl_y = ntohl(packet->y); | |
2279 strcpy(pl->pl_name, packet->name); | |
2280 pl->pl_namelen = strlen(packet->name); | |
2281 pl->pl_flags |= PLREDRAW; | |
2282 if (infomapped && infotype == PLANETTYPE && | |
2283 ((struct planet *) infothing)->pl_no == packet->pnum) | |
2284 infoupdate = 1; | |
2285 reinitPlanets = 1; | |
2286 if (pl->pl_x > blk_gwidth) { | |
2287 blk_gwidth = 200000; | |
2288 blk_windgwidth = ((float) WINSIDE) / blk_gwidth; | |
2289 } | |
2290 #ifdef ROTATERACE | |
2291 if (rotate) { | |
2292 rotate_gcenter(&pl->pl_x, &pl->pl_y); | |
2293 } | |
2294 #endif | |
2295 } | |
2296 | |
2297 #if 0 | |
2298 | |
2299 static void | |
2300 handleReserved(packet) | |
2301 struct reserved_spacket *packet; | |
2302 { | |
2303 struct reserved_cpacket response; | |
2304 | |
2305 #ifndef RWATCH | |
2306 encryptReservedPacket(packet, &response, serverName, me->p_no); | |
2307 sendServerPacket((struct player_spacket *) & response); | |
2308 #endif /* RWATCH */ | |
2309 } | |
2310 | |
2311 #else | |
2312 | |
2313 | |
2314 static void | |
2315 handleReserved(packet) | |
2316 struct reserved_spacket *packet; | |
2317 { | |
2318 #ifdef AUTHORIZE | |
2319 struct reserved_cpacket response; | |
2320 | |
2321 response.type = CP_RESERVED; | |
2322 if (RSA_Client) { /* can use -o option for old blessing */ | |
2323 warning(RSA_VERSION); | |
2324 strncpy((char *)response.resp, RSA_VERSION, RESERVED_SIZE); | |
2325 memcpy(response.data, packet->data, RESERVED_SIZE); | |
2326 } else { | |
2327 #if 0 | |
2328 /* | |
2329 if we ever go back to reserved.c checking, we'll reactivate this | |
2330 code. However, our reserved.c module hasn't done any real | |
2331 computation since paradise 1. | |
2332 */ | |
2333 encryptReservedPacket(packet, &response, serverName, me->p_no); | |
2334 #else | |
2335 memcpy(response.data, packet->data, 16); | |
2336 memcpy(response.resp, packet->data, 16); | |
2337 #endif | |
2338 } | |
2339 sendServerPacket((struct player_spacket *) & response); | |
2340 #endif | |
2341 } | |
2342 | |
2343 static void | |
2344 handleRSAKey(packet) | |
2345 struct rsa_key_spacket *packet; | |
2346 { | |
2347 #ifdef AUTHORIZE | |
2348 struct rsa_key_cpacket response; | |
2349 #ifndef DNET | |
2350 struct sockaddr_in saddr; | |
2351 #endif | |
2352 unsigned char *data; | |
2353 int len; | |
2354 | |
2355 #ifdef GATEWAY | |
2356 extern unsigned long netaddr; | |
2357 extern int serv_port; | |
2358 #endif | |
2359 | |
2360 #ifndef DNET | |
2361 #ifdef GATEWAY | |
2362 /* if we didn't get it from -H, go ahead and query the socket */ | |
2363 if (netaddr == 0) { | |
2364 len = sizeof(saddr); | |
2365 if (getpeername(sock, (struct sockaddr *) & saddr, &len) < 0) { | |
2366 perror("getpeername(sock)"); | |
2367 exit(1); | |
2368 } | |
2369 } else { | |
2370 saddr.sin_addr.s_addr = netaddr; | |
2371 saddr.sin_port = htons(serv_port); | |
2372 } | |
2373 #else /* GATEWAY */ | |
2374 /* query the socket to determine the remote host (ATM) */ | |
2375 len = sizeof(saddr); | |
2376 if (getpeername(sock, (struct sockaddr *) & saddr, &len) < 0) { | |
2377 perror("getpeername(sock)"); | |
2378 exit(1); | |
2379 } | |
2380 #endif /* GATEWAY */ | |
2381 | |
2382 data = packet->data; | |
2383 bcopy(&saddr.sin_addr.s_addr, data, sizeof(saddr.sin_addr.s_addr)); | |
2384 data += sizeof(saddr.sin_addr.s_addr); | |
2385 bcopy(&saddr.sin_port, data, sizeof(saddr.sin_port)); | |
2386 #else /* DNET */ | |
2387 { | |
2388 extern long netrek_server_addr; | |
2389 extern unsigned short netrek_server_port; | |
2390 | |
2391 data = packet->data; | |
2392 bcopy(&netrek_server_addr, data, sizeof(netrek_server_addr)); | |
2393 data += sizeof(netrek_server_addr); | |
2394 bcopy(&netrek_server_port, data, sizeof(netrek_server_port)); | |
2395 } | |
2396 #endif /* DNET */ | |
2397 | |
2398 #ifdef DEBUG | |
2399 { | |
2400 struct timeval start, end; | |
2401 gettimeofday(&start, NULL); | |
2402 #endif | |
2403 rsa_black_box(response.resp, packet->data, | |
2404 response.public, response.global); | |
2405 #ifdef DEBUG | |
2406 gettimeofday(&end, NULL); | |
2407 printf("rsa_black_box took %d ms.\n", | |
2408 (1000 * (end.tv_sec - start.tv_sec) + | |
2409 (end.tv_usec - start.tv_usec) / 1000)); | |
2410 } | |
2411 #endif | |
2412 response.type = CP_RSA_KEY; | |
2413 | |
2414 sendServerPacket((struct player_spacket *) & response); | |
2415 #ifdef DEBUG | |
2416 printf("RSA verification requested.\n"); | |
2417 #endif | |
2418 #endif /* AUTHORIZE */ | |
2419 } | |
2420 | |
2421 #endif | |
2422 | |
2423 #ifdef INCLUDE_SCAN | |
2424 static void | |
2425 handleScan(packet) | |
2426 struct scan_spacket *packet; | |
2427 { | |
2428 struct player *pp; | |
2429 | |
2430 SANITY_PNUM(packet->pnum); | |
2431 | |
2432 if (packet->success) { | |
2433 pp = &players[packet->pnum]; | |
2434 pp->p_fuel = ntohl(packet->p_fuel); | |
2435 pp->p_armies = ntohl(packet->p_armies); | |
2436 pp->p_shield = ntohl(packet->p_shield); | |
2437 pp->p_damage = ntohl(packet->p_damage); | |
2438 pp->p_etemp = ntohl(packet->p_etemp); | |
2439 pp->p_wtemp = ntohl(packet->p_wtemp); | |
2440 informScan(packet->pnum); | |
2441 } | |
2442 } | |
2443 | |
2444 static void | |
2445 informScan(p) | |
2446 int p; | |
2447 { | |
2448 } | |
2449 | |
2450 #endif /* INCLUDE_SCAN */ | |
2451 | |
2452 /* | |
2453 * UDP stuff | |
2454 */ | |
2455 void | |
2456 sendUdpReq(req) | |
2457 int req; | |
2458 { | |
2459 struct udp_req_cpacket packet; | |
2460 #ifdef RWATCH | |
2461 return; | |
2462 #endif /* RWATCH */ | |
2463 | |
2464 packet.type = CP_UDP_REQ; | |
2465 packet.request = req; | |
2466 | |
2467 if (req >= COMM_MODE) { | |
2468 packet.request = COMM_MODE; | |
2469 packet.connmode = req - COMM_MODE; | |
2470 sendServerPacket((struct player_spacket *) & packet); | |
2471 return; | |
2472 } | |
2473 if (req == COMM_UPDATE) { | |
2474 #ifdef SHORT_PACKETS | |
2475 if (recv_short) { /* not necessary */ | |
2476 /* Let the client do the work, and not the network :-) */ | |
2477 register int i; | |
2478 for (i = 0; i < nplayers * ntorps; i++) | |
2479 torps[i].t_status = TFREE; | |
2480 | |
2481 for (i = 0; i < nplayers * nplasmas; i++) | |
2482 plasmatorps[i].pt_status = PTFREE; | |
2483 | |
2484 for (i = 0; i < nplayers; i++) { | |
2485 players[i].p_ntorp = 0; | |
2486 players[i].p_nplasmatorp = 0; | |
2487 phasers[i].ph_status = PHFREE; | |
2488 } | |
2489 } | |
2490 #endif | |
2491 sendServerPacket((struct player_spacket *) & packet); | |
2492 warning("Sent request for full update"); | |
2493 return; | |
2494 } | |
2495 if (req == commModeReq) { | |
2496 warning("Request is in progress, do not disturb"); | |
2497 return; | |
2498 } | |
2499 if (req == COMM_UDP) { | |
2500 /* open UDP port */ | |
2501 if (openUdpConn() >= 0) { | |
2502 UDPDIAG(("Bound to local port %d on fd %d\n", udpLocalPort, udpSock)); | |
2503 } else { | |
2504 UDPDIAG(("Bind to local port %d failed\n", udpLocalPort)); | |
2505 commModeReq = COMM_TCP; | |
2506 commStatus = STAT_CONNECTED; | |
2507 commSwitchTimeout = 0; | |
2508 if (udpWin) | |
2509 udprefresh(UDP_STATUS); | |
2510 warning("Unable to establish UDP connection"); | |
2511 | |
2512 return; | |
2513 } | |
2514 } | |
2515 /* send the request */ | |
2516 packet.type = CP_UDP_REQ; | |
2517 packet.request = req; | |
2518 packet.port = htonl(udpLocalPort); | |
2519 #ifdef GATEWAY | |
2520 if (!strcmp(serverName, gw_mach)) { | |
2521 packet.port = htons(gw_serv_port); /* gw port that server should | |
2522 call */ | |
2523 UDPDIAG(("+ Telling server to contact us on %d\n", gw_serv_port)); | |
2524 } | |
2525 #endif | |
2526 #ifdef USE_PORTSWAP | |
2527 packet.connmode = CONNMODE_PORT; /* have him send his port */ | |
2528 #else | |
2529 packet.connmode = CONNMODE_PACKET; /* we get addr from packet */ | |
2530 #endif | |
2531 sendServerPacket((struct player_spacket *) & packet); | |
2532 | |
2533 /* update internal state stuff */ | |
2534 commModeReq = req; | |
2535 if (req == COMM_TCP) | |
2536 commStatus = STAT_SWITCH_TCP; | |
2537 else | |
2538 commStatus = STAT_SWITCH_UDP; | |
2539 commSwitchTimeout = 25; /* wait 25 updates (about five seconds) */ | |
2540 | |
2541 UDPDIAG(("Sent request for %s mode\n", (req == COMM_TCP) ? | |
2542 "TCP" : "UDP")); | |
2543 | |
2544 #ifndef USE_PORTSWAP | |
2545 if ((req == COMM_UDP) && recvUdpConn() < 0) { | |
2546 UDPDIAG(("Sending TCP reset message\n")); | |
2547 packet.request = COMM_TCP; | |
2548 packet.port = 0; | |
2549 commModeReq = COMM_TCP; | |
2550 sendServerPacket((struct player_spacket *) & packet); | |
2551 /* we will likely get a SWITCH_UDP_OK later; better ignore it */ | |
2552 commModeReq = COMM_TCP; | |
2553 commStatus = STAT_CONNECTED; | |
2554 commSwitchTimeout = 0; | |
2555 closeUdpConn(); | |
2556 } | |
2557 #endif | |
2558 | |
2559 if (udpWin) | |
2560 udprefresh(UDP_STATUS); | |
2561 } | |
2562 | |
2563 static void | |
2564 handleUdpReply(packet) | |
2565 struct udp_reply_spacket *packet; | |
2566 { | |
2567 struct udp_req_cpacket response; | |
2568 | |
2569 UDPDIAG(("Received UDP reply %d\n", packet->reply)); | |
2570 commSwitchTimeout = 0; | |
2571 | |
2572 response.type = CP_UDP_REQ; | |
2573 | |
2574 switch (packet->reply) { | |
2575 case SWITCH_TCP_OK: | |
2576 if (commMode == COMM_TCP) { | |
2577 UDPDIAG(("Got SWITCH_TCP_OK while in TCP mode; ignoring\n")); | |
2578 } else { | |
2579 commMode = COMM_TCP; | |
2580 commStatus = STAT_CONNECTED; | |
2581 warning("Switched to TCP-only connection"); | |
2582 closeUdpConn(); | |
2583 UDPDIAG(("UDP port closed\n")); | |
2584 if (udpWin) { | |
2585 udprefresh(UDP_STATUS); | |
2586 udprefresh(UDP_CURRENT); | |
2587 } | |
2588 } | |
2589 break; | |
2590 case SWITCH_UDP_OK: | |
2591 if (commMode == COMM_UDP) { | |
2592 UDPDIAG(("Got SWITCH_UDP_OK while in UDP mode; ignoring\n")); | |
2593 } else { | |
2594 /* the server is forcing UDP down our throat? */ | |
2595 if (commModeReq != COMM_UDP) { | |
2596 UDPDIAG(("Got unsolicited SWITCH_UDP_OK; ignoring\n")); | |
2597 } else { | |
2598 #ifdef USE_PORTSWAP | |
2599 udpServerPort = ntohl(packet->port); | |
2600 #ifdef nodef /* simulate calvin error */ | |
2601 /* XXX TMP */ | |
2602 udpServerPort = 3333; | |
2603 #endif | |
2604 if (connUdpConn() < 0) { | |
2605 UDPDIAG(("Unable to connect, resetting\n")); | |
2606 warning("Connection attempt failed"); | |
2607 commModeReq = COMM_TCP; | |
2608 commStatus = STAT_CONNECTED; | |
2609 if (udpSock >= 0) | |
2610 closeUdpConn(); | |
2611 if (udpWin) { | |
2612 udprefresh(UDP_STATUS); | |
2613 udprefresh(UDP_CURRENT); | |
2614 } | |
2615 response.request = COMM_TCP; | |
2616 response.port = 0; | |
2617 goto send; | |
2618 } | |
2619 #else | |
2620 /* this came down UDP, so we MUST be connected */ | |
2621 /* (do the verify thing anyway just for kicks) */ | |
2622 #endif | |
2623 UDPDIAG(("Connected to server's UDP port\n")); | |
2624 commStatus = STAT_VERIFY_UDP; | |
2625 if (udpWin) | |
2626 udprefresh(UDP_STATUS); | |
2627 response.request = COMM_VERIFY; /* send verify request on UDP */ | |
2628 response.port = 0; | |
2629 commSwitchTimeout = 25; /* wait 25 updates */ | |
2630 #ifdef USE_PORTSWAP | |
2631 send: | |
2632 #endif /* USE_PORTSWAP */ | |
2633 sendServerPacket((struct player_spacket *) & response); | |
2634 } | |
2635 } | |
2636 break; | |
2637 case SWITCH_DENIED: | |
2638 if (ntohs(packet->port)) { | |
2639 UDPDIAG(("Switch to UDP failed (different version)\n")); | |
2640 warning("UDP protocol request failed (bad version)"); | |
2641 } else { | |
2642 UDPDIAG(("Switch to UDP denied\n")); | |
2643 warning("UDP protocol request denied"); | |
2644 } | |
2645 commModeReq = commMode; | |
2646 commStatus = STAT_CONNECTED; | |
2647 commSwitchTimeout = 0; | |
2648 if (udpWin) | |
2649 udprefresh(UDP_STATUS); | |
2650 if (udpSock >= 0) | |
2651 closeUdpConn(); | |
2652 break; | |
2653 case SWITCH_VERIFY: | |
2654 UDPDIAG(("Received UDP verification\n")); | |
2655 break; | |
2656 default: | |
2657 fprintf(stderr, "netrek: Got funny reply (%d) in UDP_REPLY packet\n", | |
2658 packet->reply); | |
2659 break; | |
2660 } | |
2661 } | |
2662 | |
2663 #define MAX_PORT_RETRY 10 | |
2664 static int | |
2665 openUdpConn() | |
2666 { | |
2667 #ifndef DNET | |
2668 struct sockaddr_in addr; | |
2669 struct hostent *hp; | |
2670 int attempts; | |
2671 | |
2672 #ifdef RECORDER | |
2673 if (playback) | |
2674 return 0; | |
2675 #endif | |
2676 if (udpSock >= 0) { | |
2677 fprintf(stderr, "netrek: tried to open udpSock twice\n"); | |
2678 return (0); /* pretend we succeeded (this could be bad) */ | |
2679 } | |
2680 if ((udpSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | |
2681 perror("netrek: unable to create DGRAM socket"); | |
2682 return (-1); | |
2683 } | |
2684 #ifdef nodef | |
2685 set_udp_opts(udpSock); | |
2686 #endif /* nodef */ | |
2687 | |
2688 if(UdpLocalPort == 0) { | |
2689 UdpLocalPort = intDefault("baseUdpLocalPort", 0); | |
2690 UDPDIAG(("using base port %d\n", UdpLocalPort)); | |
2691 } | |
2692 | |
2693 addr.sin_addr.s_addr = INADDR_ANY; | |
2694 addr.sin_family = AF_INET; | |
2695 | |
2696 errno = 0; | |
2697 udpLocalPort = (getpid() & 32767) + (random() % 256); | |
2698 for (attempts = 0; attempts < MAX_PORT_RETRY; attempts++) { | |
2699 if(UdpLocalPort){ | |
2700 /* force UDP to be starting at a base address */ | |
2701 udpLocalPort = UdpLocalPort + attempts; | |
2702 } else while (udpLocalPort < 2048) { | |
2703 udpLocalPort = (udpLocalPort + 10687) & 32767; | |
2704 } | |
2705 #ifdef GATEWAY | |
2706 /* we need the gateway to know where to find us */ | |
2707 if (!strcmp(serverName, gw_mach)) { | |
2708 UDPDIAG(("+ gateway test: binding to %d\n", gw_local_port)); | |
2709 udpLocalPort = gw_local_port; | |
2710 } | |
2711 #endif | |
2712 addr.sin_port = htons(udpLocalPort); | |
2713 if (bind(udpSock, (struct sockaddr *) & addr, sizeof(addr)) >= 0) | |
2714 break; | |
2715 } | |
2716 if (attempts == MAX_PORT_RETRY) { | |
2717 perror("netrek: bind"); | |
2718 UDPDIAG(("Unable to find a local port to bind to\n")); | |
2719 close(udpSock); | |
2720 udpSock = -1; | |
2721 return (-1); | |
2722 } | |
2723 UDPDIAG(("Local port is %d\n", udpLocalPort)); | |
2724 if(UdpLocalPort) { | |
2725 fprintf(stdout, "Local UDP port is %d\n", udpLocalPort); | |
2726 } | |
2727 | |
2728 /* determine the address of the server */ | |
2729 if (!serveraddr) { | |
2730 if ((addr.sin_addr.s_addr = inet_addr(serverName)) == -1) { | |
2731 if ((hp = gethostbyname(serverName)) == NULL) { | |
2732 printf("Who is %s?\n", serverName); | |
2733 #ifdef AUTOKEY | |
2734 if (autoKey) | |
2735 W_AutoRepeatOn(); | |
2736 #endif | |
2737 | |
2738 EXIT(0); | |
2739 } else { | |
2740 addr.sin_addr.s_addr = *(long *) hp->h_addr; | |
2741 } | |
2742 } | |
2743 serveraddr = addr.sin_addr.s_addr; | |
2744 UDPDIAG(("Found serveraddr == 0x%x\n", (unsigned int) serveraddr)); | |
2745 } | |
2746 return (0); | |
2747 #else /* DNET */ | |
2748 #ifdef RECORDER | |
2749 if (playback) | |
2750 return 0; | |
2751 #endif | |
2752 return DNetOpenUDPConn(serverName); | |
2753 #endif /* DNET */ | |
2754 } | |
2755 | |
2756 #ifdef USE_PORTSWAP | |
2757 static int | |
2758 connUdpConn() | |
2759 { | |
2760 #ifndef DNET | |
2761 struct sockaddr_in addr; | |
2762 int len; | |
2763 | |
2764 #ifdef RECORDER | |
2765 if (playback) | |
2766 return 0; | |
2767 #endif | |
2768 addr.sin_addr.s_addr = serveraddr; | |
2769 addr.sin_family = AF_INET; | |
2770 addr.sin_port = htons(udpServerPort); | |
2771 | |
2772 UDPDIAG(("Connecting to host 0x%x on port %d\n", serveraddr, udpServerPort)); | |
2773 if (connect(udpSock, &addr, sizeof(addr)) < 0) { | |
2774 fprintf(stderr, "Error %d: "); | |
2775 perror("netrek: unable to connect UDP socket"); | |
2776 printUdpInfo(); /* debug */ | |
2777 return (-1); | |
2778 } | |
2779 #ifdef nodef | |
2780 len = sizeof(addr); | |
2781 if (getsockname(udpSock, &addr, &len) < 0) { | |
2782 perror("netrek: unable to getsockname(UDP)"); | |
2783 UDPDIAG(("Can't get our own socket; connection failed\n")); | |
2784 close(udpSock); | |
2785 udpSock = -1; | |
2786 return -1; | |
2787 } | |
2788 printf("udpLocalPort %d, getsockname port %d\n", | |
2789 udpLocalPort, addr.sin_port); | |
2790 #endif | |
2791 | |
2792 return (0); | |
2793 #endif /* DNET */ | |
2794 } | |
2795 #endif | |
2796 | |
2797 #ifndef USE_PORTSWAP | |
2798 static int | |
2799 recvUdpConn() | |
2800 { | |
2801 #ifndef DNET | |
2802 fd_set readfds; | |
2803 struct timeval to; | |
2804 struct sockaddr_in from; | |
2805 int fromlen, res; | |
2806 | |
2807 #ifdef RECORDER | |
2808 if (playback) | |
2809 return 0; | |
2810 #endif | |
2811 bzero(&from, sizeof(from)); /* don't get garbage if really broken */ | |
2812 | |
2813 /* we patiently wait until the server sends a packet to us */ | |
2814 /* (note that we silently eat the first one) */ | |
2815 UDPDIAG(("Issuing recvfrom() call\n")); | |
2816 printUdpInfo(); | |
2817 fromlen = sizeof(from); | |
2818 FD_ZERO(&readfds); | |
2819 FD_SET(udpSock, &readfds); | |
2820 to.tv_sec = 6; /* wait 3 seconds, then abort */ | |
2821 to.tv_usec = 0; | |
2822 if ((res = select(32, &readfds, 0, 0, &to)) <= 0) { | |
2823 if (!res) { | |
2824 UDPDIAG(("timed out waiting for response")); | |
2825 warning("UDP connection request timed out"); | |
2826 return (-1); | |
2827 } else { | |
2828 perror("select() before recvfrom()"); | |
2829 return (-1); | |
2830 } | |
2831 } | |
2832 if (recvfrom(udpSock, buf, BUFSIZ, 0, (struct sockaddr *) & from, &fromlen) < 0) { | |
2833 perror("recvfrom"); | |
2834 UDPDIAG(("recvfrom failed, aborting UDP attempt")); | |
2835 return (-1); | |
2836 } | |
2837 if (from.sin_addr.s_addr != serveraddr) { | |
2838 /* safe? */ | |
2839 serveraddr = from.sin_addr.s_addr; | |
2840 UDPDIAG(("Warning: from 0x%x, but server is 0x%x\n", | |
2841 (unsigned int) from.sin_addr.s_addr, (unsigned int) serveraddr)); | |
2842 } | |
2843 if (from.sin_family != AF_INET) { | |
2844 UDPDIAG(("Warning: not AF_INET (%d)\n", from.sin_family)); | |
2845 } | |
2846 udpServerPort = ntohs(from.sin_port); | |
2847 UDPDIAG(("recvfrom() succeeded; will use server port %d\n", udpServerPort)); | |
2848 #ifdef GATEWAY | |
2849 if (!strcmp(serverName, gw_mach)) { | |
2850 UDPDIAG(("+ actually, I'm going to use %d\n", gw_port)); | |
2851 udpServerPort = gw_port; | |
2852 from.sin_port = htons(udpServerPort); | |
2853 } | |
2854 #endif | |
2855 | |
2856 if (connect(udpSock, (struct sockaddr *) & from, sizeof(from)) < 0) { | |
2857 perror("netrek: unable to connect UDP socket after recvfrom()"); | |
2858 close(udpSock); | |
2859 udpSock = -1; | |
2860 return (-1); | |
2861 } | |
2862 return (0); | |
2863 #else /* DNET */ | |
2864 #ifdef RECORDER | |
2865 if (playback) | |
2866 return 0; | |
2867 #endif | |
2868 return DNetRecvUDPConn(); | |
2869 #endif /* DNET */ | |
2870 } | |
2871 #endif | |
2872 | |
2873 int | |
2874 closeUdpConn() | |
2875 { | |
2876 V_UDPDIAG(("Closing UDP socket\n")); | |
2877 #ifdef RECORDER | |
2878 if (playback) | |
2879 return 0; | |
2880 #endif | |
2881 | |
2882 #ifdef DNET | |
2883 DNetCloseUDP(); | |
2884 return 0; | |
2885 #else | |
2886 if (udpSock < 0) { | |
2887 fprintf(stderr, "netrek: tried to close a closed UDP socket\n"); | |
2888 return (-1); | |
2889 } | |
2890 shutdown(udpSock, 2); | |
2891 close(udpSock); | |
2892 udpSock = -1; | |
2893 return 0; | |
2894 #endif /* DNET */ | |
2895 } | |
2896 | |
2897 static void | |
2898 printUdpInfo() | |
2899 { | |
2900 #ifndef DNET | |
2901 struct sockaddr_in addr; | |
2902 int len; | |
2903 | |
2904 len = sizeof(addr); | |
2905 if (getsockname(udpSock, (struct sockaddr *) & addr, &len) < 0) { | |
2906 /* perror("printUdpInfo: getsockname");*/ | |
2907 return; | |
2908 } | |
2909 UDPDIAG(("LOCAL: addr=0x%x, family=%d, port=%d\n", | |
2910 (unsigned int) addr.sin_addr.s_addr, | |
2911 addr.sin_family, ntohs(addr.sin_port))); | |
2912 | |
2913 if (getpeername(udpSock, (struct sockaddr *) & addr, &len) < 0) { | |
2914 /* perror("printUdpInfo: getpeername");*/ | |
2915 return; | |
2916 } | |
2917 UDPDIAG(("PEER : addr=0x%x, family=%d, port=%d\n", | |
2918 (unsigned int) addr.sin_addr.s_addr, | |
2919 addr.sin_family, ntohs(addr.sin_port))); | |
2920 #endif | |
2921 } | |
2922 | |
2923 static void | |
2924 handleSequence(packet) | |
2925 struct sequence_spacket *packet; | |
2926 { | |
2927 static int recent_count = 0, recent_dropped = 0; | |
2928 long newseq; | |
2929 | |
2930 drop_flag = 0; | |
2931 if (chan != udpSock) | |
2932 return; /* don't pay attention to TCP sequence #s */ | |
2933 udpTotal++; | |
2934 recent_count++; | |
2935 | |
2936 /* update percent display every 256 updates (~50 seconds usually) */ | |
2937 if (!(udpTotal & 0xff)) | |
2938 if (udpWin) | |
2939 udprefresh(UDP_DROPPED); | |
2940 | |
2941 newseq = (long) ntohs(packet->sequence); | |
2942 /* printf("read %d - ", newseq);*/ | |
2943 | |
2944 if (((unsigned short) sequence) > 65000 && | |
2945 ((unsigned short) newseq) < 1000) { | |
2946 /* we rolled, set newseq = 65536+sequence and accept it */ | |
2947 sequence = ((sequence + 65536) & 0xffff0000) | newseq; | |
2948 } else { | |
2949 /* adjust newseq and do compare */ | |
2950 newseq |= (sequence & 0xffff0000); | |
2951 | |
2952 if (!udpSequenceChk) { /* put this here so that turning seq check */ | |
2953 sequence = newseq; /* on and off doesn't make us think we lost */ | |
2954 return; /* a whole bunch of packets. */ | |
2955 } | |
2956 if (newseq > sequence) { | |
2957 /* accept */ | |
2958 if (newseq != sequence + 1) { | |
2959 udpDropped += (newseq - sequence) - 1; | |
2960 udpTotal += (newseq - sequence) - 1; /* want TOTAL packets */ | |
2961 recent_dropped += (newseq - sequence) - 1; | |
2962 recent_count += (newseq - sequence) - 1; | |
2963 if (udpWin) | |
2964 udprefresh(UDP_DROPPED); | |
2965 UDPDIAG(("sequence=%ld, newseq=%ld, we lost some\n", | |
2966 sequence, newseq)); | |
2967 } | |
2968 sequence = newseq; | |
2969 } else { | |
2970 /* reject */ | |
2971 if (packet->type == SP_SC_SEQUENCE) { | |
2972 V_UDPDIAG(("(ignoring repeat %ld)\n", newseq)); | |
2973 } else { | |
2974 UDPDIAG(("sequence=%ld, newseq=%ld, ignoring transmission\n", | |
2975 sequence, newseq)); | |
2976 } | |
2977 /* | |
2978 the remaining packets will be dropped and we shouldn't count | |
2979 the SP_SEQUENCE packet either | |
2980 */ | |
2981 packets_received--; | |
2982 drop_flag = 1; | |
2983 } | |
2984 } | |
2985 /* printf("newseq %d, sequence %d\n", newseq, sequence);*/ | |
2986 if (recent_count > UDP_RECENT_INTR) { | |
2987 /* once a minute (at 5 upd/sec), report on how many were dropped */ | |
2988 /* during the last UDP_RECENT_INTR updates */ | |
2989 udpRecentDropped = recent_dropped; | |
2990 recent_count = recent_dropped = 0; | |
2991 if (udpWin) | |
2992 udprefresh(UDP_DROPPED); | |
2993 } | |
2994 } | |
2995 | |
2996 | |
2997 /* | |
2998 static void dumpShip(shipp) | |
2999 struct ship *shipp; | |
3000 { | |
3001 printf("ship stats:\n"); | |
3002 printf("phaser range = %d\n", shipp->s_phaserrange); | |
3003 printf("max speed = %d\n", shipp->s_maxspeed); | |
3004 printf("max shield = %d\n", shipp->s_maxshield); | |
3005 printf("max damage = %d\n", shipp->s_maxdamage); | |
3006 printf("max egntemp = %d\n", shipp->s_maxegntemp); | |
3007 printf("max wpntemp = %d\n", shipp->s_maxwpntemp); | |
3008 printf("max armies = %d\n", shipp->s_maxarmies); | |
3009 printf("type = %d\n", shipp->s_type); | |
3010 printf("torp speed = %d\n", shipp->s_torpspeed); | |
3011 printf("letter = %c\n", shipp->s_letter); | |
3012 printf("desig = %2.2s\n", shipp->s_desig); | |
3013 printf("bitmap = %d\n\n", shipp->s_bitmap); | |
3014 } | |
3015 */ | |
3016 | |
3017 static void | |
3018 handleShipCap(packet) /* SP_SHIP_CAP */ | |
3019 struct ship_cap_spacket *packet; | |
3020 { | |
3021 struct shiplist *temp; | |
3022 | |
3023 /* | |
3024 What are we supposed to do? | |
3025 */ | |
3026 | |
3027 SANITY_SHIPNUM(ntohs(packet->s_type)); | |
3028 | |
3029 if (packet->operation) { /* remove ship from list */ | |
3030 temp = shiptypes; | |
3031 if (temp->ship->s_type == (int) ntohs(packet->s_type)) { | |
3032 shiptypes = temp->next; | |
3033 shiptypes->prev = NULL; | |
3034 } | |
3035 while (temp->next != NULL) { | |
3036 if (temp->next->ship->s_type == (int) ntohs(packet->s_type)) { | |
3037 temp = temp->next; | |
3038 temp->prev->next = temp->next; | |
3039 if (temp->next) | |
3040 temp->next->prev = temp->prev; | |
3041 free(temp->ship); | |
3042 free(temp); | |
3043 return; | |
3044 } else { | |
3045 temp = temp->next; | |
3046 } | |
3047 } | |
3048 } | |
3049 /* | |
3050 Since we're adding the ship, we need to find out if we already have | |
3051 that ship, and if so, replace it. | |
3052 */ | |
3053 | |
3054 temp = shiptypes; | |
3055 while (temp != NULL) { | |
3056 if (temp->ship->s_type == (int) ntohs(packet->s_type)) { | |
3057 temp->ship->s_type = ntohs(packet->s_type); | |
3058 temp->ship->s_torpspeed = ntohs(packet->s_torpspeed); | |
3059 temp->ship->s_phaserrange = ntohs(packet->s_phaserrange); | |
3060 if (temp->ship->s_phaserrange < 200) /* backward | |
3061 compatibility */ | |
3062 temp->ship->s_phaserrange *= PHASEDIST / 100; | |
3063 temp->ship->s_maxspeed = ntohl(packet->s_maxspeed); | |
3064 temp->ship->s_maxfuel = ntohl(packet->s_maxfuel); | |
3065 temp->ship->s_maxshield = ntohl(packet->s_maxshield); | |
3066 temp->ship->s_maxdamage = ntohl(packet->s_maxdamage); | |
3067 temp->ship->s_maxwpntemp = ntohl(packet->s_maxwpntemp); | |
3068 temp->ship->s_maxegntemp = ntohl(packet->s_maxegntemp); | |
3069 temp->ship->s_maxarmies = ntohs(packet->s_maxarmies); | |
3070 temp->ship->s_letter = packet->s_letter; | |
3071 temp->ship->s_desig[0] = packet->s_desig1; | |
3072 temp->ship->s_desig[1] = packet->s_desig2; | |
3073 temp->ship->s_bitmap = ntohs(packet->s_bitmap); | |
3074 buildShipKeymap(temp->ship); | |
3075 /*dumpShip(temp->ship);*/ | |
3076 return; | |
3077 } | |
3078 temp = temp->next; | |
3079 } | |
3080 | |
3081 /* | |
3082 Not there, so we need to make a new entry in the list for it. | |
3083 */ | |
3084 temp = (struct shiplist *) malloc(sizeof(struct shiplist)); | |
3085 temp->next = shiptypes; | |
3086 temp->prev = NULL; | |
3087 if (shiptypes) | |
3088 shiptypes->prev = temp; | |
3089 shiptypes = temp; | |
3090 temp->ship = (struct ship *) malloc(sizeof(struct ship)); | |
3091 temp->ship->s_type = ntohs(packet->s_type); | |
3092 temp->ship->s_torpspeed = ntohs(packet->s_torpspeed); | |
3093 temp->ship->s_phaserrange = ntohs(packet->s_phaserrange); | |
3094 temp->ship->s_maxspeed = ntohl(packet->s_maxspeed); | |
3095 temp->ship->s_maxfuel = ntohl(packet->s_maxfuel); | |
3096 temp->ship->s_maxshield = ntohl(packet->s_maxshield); | |
3097 temp->ship->s_maxdamage = ntohl(packet->s_maxdamage); | |
3098 temp->ship->s_maxwpntemp = ntohl(packet->s_maxwpntemp); | |
3099 temp->ship->s_maxegntemp = ntohl(packet->s_maxegntemp); | |
3100 temp->ship->s_maxarmies = ntohs(packet->s_maxarmies); | |
3101 temp->ship->s_letter = packet->s_letter; | |
3102 temp->ship->s_desig[0] = packet->s_desig1; | |
3103 temp->ship->s_desig[1] = packet->s_desig2; | |
3104 temp->ship->s_bitmap = ntohs(packet->s_bitmap); | |
3105 buildShipKeymap(temp->ship); | |
3106 /* dumpShip(temp->ship);*/ | |
3107 } | |
3108 | |
3109 static void | |
3110 handleMotdPic(packet) /* SP_SHIP_CAP */ | |
3111 struct motd_pic_spacket *packet; | |
3112 { | |
3113 int x, y, page, width, height; | |
3114 | |
3115 x = ntohs(packet->x); | |
3116 y = ntohs(packet->y); | |
3117 width = ntohs(packet->width); | |
3118 height = ntohs(packet->height); | |
3119 page = ntohs(packet->page); | |
3120 | |
3121 newMotdPic(x, y, width, height, (char *) packet->bits, page); | |
3122 } | |
3123 | |
3124 static void | |
3125 handleStats2(packet) | |
3126 struct stats_spacket2 *packet; | |
3127 { | |
3128 struct stats2 *p; /* to hold packet's player's stats2 struct */ | |
3129 | |
3130 SANITY_PNUM(packet->pnum); | |
3131 | |
3132 updatePlayer[packet->pnum] |= LARGE_UPDATE; | |
3133 if (infomapped && infotype == PLAYERTYPE && | |
3134 ((struct player *) infothing)->p_no == packet->pnum) | |
3135 infoupdate = 1; | |
3136 p = &(players[packet->pnum].p_stats2); /* get player's stats2 struct */ | |
3137 p->st_genocides = ntohl(packet->genocides); | |
3138 p->st_tmaxkills = (float) ntohl(packet->maxkills) / 100.0; | |
3139 p->st_di = (float) ntohl(packet->di) / 100.0; | |
3140 p->st_tkills = (int) ntohl(packet->kills); | |
3141 p->st_tlosses = (int) ntohl(packet->losses); | |
3142 p->st_tarmsbomb = (int) ntohl(packet->armsbomb); | |
3143 p->st_tresbomb = (int) ntohl(packet->resbomb); | |
3144 p->st_tdooshes = (int) ntohl(packet->dooshes); | |
3145 p->st_tplanets = (int) ntohl(packet->planets); | |
3146 p->st_tticks = (int) ntohl(packet->tticks); | |
3147 p->st_sbkills = (int) ntohl(packet->sbkills); | |
3148 p->st_sblosses = (int) ntohl(packet->sblosses); | |
3149 p->st_sbticks = (int) ntohl(packet->sbticks); | |
3150 p->st_sbmaxkills = (float) ntohl(packet->sbmaxkills) / 100.0; | |
3151 p->st_wbkills = (int) ntohl(packet->wbkills); | |
3152 p->st_wblosses = (int) ntohl(packet->wblosses); | |
3153 p->st_wbticks = (int) ntohl(packet->wbticks); | |
3154 p->st_wbmaxkills = (float) ntohl(packet->wbmaxkills) / 100.0; | |
3155 p->st_jsplanets = (int) ntohl(packet->jsplanets); | |
3156 p->st_jsticks = (int) ntohl(packet->jsticks); | |
3157 if (p->st_rank != (int) ntohl(packet->rank) || | |
3158 p->st_royal != (int) ntohl(packet->royal)) { | |
3159 p->st_rank = (int) ntohl(packet->rank); | |
3160 p->st_royal = (int) ntohl(packet->royal); | |
3161 updatePlayer[packet->pnum] |= ALL_UPDATE; | |
3162 } | |
3163 } | |
3164 | |
3165 static void | |
3166 handleStatus2(packet) | |
3167 struct status_spacket2 *packet; | |
3168 { | |
3169 updatePlayer[me->p_no] |= LARGE_UPDATE; | |
3170 if (infomapped && infotype == PLAYERTYPE && | |
3171 ((struct player *) infothing)->p_no == me->p_no) | |
3172 infoupdate = 1; | |
3173 status2->tourn = packet->tourn; | |
3174 status2->dooshes = ntohl(packet->dooshes); | |
3175 status2->armsbomb = ntohl(packet->armsbomb); | |
3176 status2->resbomb = ntohl(packet->resbomb); | |
3177 status2->planets = ntohl(packet->planets); | |
3178 status2->kills = ntohl(packet->kills); | |
3179 status2->losses = ntohl(packet->losses); | |
3180 status2->sbkills = ntohl(packet->sbkills); | |
3181 status2->sblosses = ntohl(packet->sblosses); | |
3182 status2->sbtime = ntohl(packet->sbtime); | |
3183 status2->wbkills = ntohl(packet->wbkills); | |
3184 status2->wblosses = ntohl(packet->wblosses); | |
3185 status2->wbtime = ntohl(packet->wbtime); | |
3186 status2->jsplanets = ntohl(packet->jsplanets); | |
3187 status2->jstime = ntohl(packet->jstime); | |
3188 status2->time = ntohl(packet->time); | |
3189 status2->timeprod = ntohl(packet->timeprod); | |
3190 } | |
3191 | |
3192 static void | |
3193 handlePlanet2(packet) | |
3194 struct planet_spacket2 *packet; | |
3195 { | |
3196 SANITY_PLANNUM(packet->pnum); | |
3197 | |
3198 planets[packet->pnum].pl_owner = packet->owner; | |
3199 planets[packet->pnum].pl_info = packet->info; | |
3200 planets[packet->pnum].pl_flags = ntohl(packet->flags); | |
3201 planets[packet->pnum].pl_timestamp = ntohl(packet->timestamp); | |
3202 planets[packet->pnum].pl_armies = ntohl(packet->armies); | |
3203 planets[packet->pnum].pl_flags |= PLREDRAW; | |
3204 pl_update[packet->pnum].plu_update = 1; | |
3205 pl_update[packet->pnum].plu_x = planets[packet->pnum].pl_x; | |
3206 pl_update[packet->pnum].plu_y = planets[packet->pnum].pl_y; | |
3207 if (infomapped && infotype == PLANETTYPE && | |
3208 ((struct planet *) infothing)->pl_no == packet->pnum) | |
3209 infoupdate = 1; | |
3210 } | |
3211 | |
3212 static void | |
3213 handleTerrainInfo2(pkt) | |
3214 struct terrain_info_packet2 *pkt; | |
3215 { | |
3216 #ifdef ZDIAG2 | |
3217 fprintf( stderr, "Receiving terrain info packet\n" ); | |
3218 fprintf( stderr, "Terrain dims: %d x %d\n", ntohs(pkt->xdim), ntohs(pkt->ydim) ); | |
3219 #endif | |
3220 received_terrain_info = TERRAIN_STARTED; | |
3221 terrain_x = ntohs(pkt->xdim); | |
3222 terrain_y = ntohs(pkt->ydim); | |
3223 } | |
3224 | |
3225 static void | |
3226 handleTerrain2(pkt) | |
3227 struct terrain_packet2 *pkt; | |
3228 { | |
3229 static int curseq = 0, totbytes = 0, done = 0; | |
3230 int i, status; | |
3231 unsigned long dlen; | |
3232 #ifdef ZDIAG2 | |
3233 static unsigned char sum = 0; | |
3234 static unsigned numnz = 0; | |
3235 #endif | |
3236 static unsigned char *gzipTerrain = NULL, *orgTerrain = NULL; | |
3237 | |
3238 #ifdef ZDIAG2 | |
3239 fprintf( stderr, "Receiving Terrain packet. This should be %d.\n", curseq+1 ); | |
3240 #endif | |
3241 | |
3242 if( (done == TERRAIN_DONE) && (received_terrain_info == TERRAIN_STARTED ) ){ | |
3243 /* receiving new terrain info */ | |
3244 free( gzipTerrain ); | |
3245 free( orgTerrain ); | |
3246 free( terrainInfo ); | |
3247 gzipTerrain = orgTerrain = NULL; | |
3248 terrainInfo = NULL; | |
3249 curseq = done = totbytes = 0; | |
3250 } | |
3251 | |
3252 curseq++; | |
3253 if( (curseq != pkt->sequence) || !(received_terrain_info) ){ | |
3254 /* Should fill in a list of all packets missed */ | |
3255 /* or request header packet from server */ | |
3256 fprintf( stderr, "Blech! Received terrain packet before terrain_info\n" ); | |
3257 return; | |
3258 } | |
3259 #ifdef ZDIAG2 | |
3260 fprintf( stderr, "Receiving packet %d out of %d\n", curseq, pkt->total_pkts ); | |
3261 #endif | |
3262 if( !gzipTerrain ){ | |
3263 gzipTerrain = (unsigned char *)malloc( pkt->total_pkts << 7 ); | |
3264 #if defined(ZDIAG) || defined(ZDIAG2) | |
3265 fprintf( stderr, "Allocating %d bytes for gzipTerrain.\n", pkt->total_pkts << 7 ); | |
3266 #endif | |
3267 /* another yukko constant */ | |
3268 } | |
3269 if( !orgTerrain ){ | |
3270 orgTerrain = (unsigned char *)malloc( terrain_x*terrain_y ); | |
3271 dlen = terrain_x * terrain_y; | |
3272 #if defined(ZDIAG) || defined(ZDIAG2) | |
3273 fprintf( stderr, "Allocating %d bytes for orgTerrain.\n", dlen ); | |
3274 #endif | |
3275 } | |
3276 for( i = 0; i < pkt->length; i++ ){ | |
3277 #ifdef ZDIAG2 | |
3278 if( !(i%10) ){ | |
3279 fprintf( stderr, "Params: %d, %d\n", ((curseq-1)<<7)+i, i ); | |
3280 } | |
3281 #endif | |
3282 gzipTerrain[((curseq-1)<<7)+i] = pkt->terrain_type[i]; | |
3283 } | |
3284 totbytes += pkt->length; | |
3285 if( curseq == pkt->total_pkts ){ | |
3286 #if defined(ZDIAG) || defined(ZDIAG2) | |
3287 status = uncompress( orgTerrain, &dlen, gzipTerrain, totbytes ); | |
3288 if( status != Z_OK ){ | |
3289 if( status == Z_BUF_ERROR ){ | |
3290 fprintf( stderr, "Unable to uncompress -- Z_BUF_ERROR.\n" ); | |
3291 } | |
3292 if( status == Z_MEM_ERROR ){ | |
3293 fprintf( stderr, "Unable to uncompress -- Z_MEM_ERROR.\n" ); | |
3294 } | |
3295 if( status = Z_DATA_ERROR ){ | |
3296 fprintf( stderr, "Unable to uncompress -- Z_DATA_ERROR!\n" ); | |
3297 } | |
3298 } | |
3299 else{ | |
3300 fprintf( stderr, "Total zipped terrain received: %d bytes\n", totbytes ); | |
3301 } | |
3302 #else | |
3303 uncompress( orgTerrain, &dlen, gzipTerrain, totbytes ); | |
3304 #endif | |
3305 terrainInfo = (struct t_unit *)malloc( dlen * sizeof( struct t_unit ) ); | |
3306 for( i = 0; i < dlen; i++ ){ | |
3307 terrainInfo[i].types = orgTerrain[i]; | |
3308 #ifdef ZDIAG2 | |
3309 sum |= orgTerrain[i]; | |
3310 if( orgTerrain[i] != 0 ){ | |
3311 numnz++; | |
3312 } | |
3313 #endif | |
3314 } | |
3315 done = received_terrain_info = TERRAIN_DONE; | |
3316 #ifdef ZDIAG2 | |
3317 fprintf( stderr, "Sum = %d, numnz = %d\n", sum, numnz ); | |
3318 #endif | |
3319 } | |
3320 } | |
3321 | |
3322 static void | |
3323 handleTempPack(packet) /* SP_SHIP_CAP */ | |
3324 struct obvious_packet *packet; | |
3325 { | |
3326 struct obvious_packet reply; | |
3327 /* printf("New MOTD info available\n"); */ | |
3328 erase_motd(); | |
3329 reply.type = CP_ASK_MOTD; | |
3330 sendServerPacket((struct player_spacket *) & reply); | |
3331 } | |
3332 | |
3333 /* handlers for the extension1 packet */ | |
3334 | |
3335 int | |
3336 compute_extension1_size(pkt) | |
3337 char *pkt; | |
3338 { | |
3339 if (pkt[0] != SP_PARADISE_EXT1) | |
3340 return -1; | |
3341 | |
3342 switch (pkt[1]) { | |
3343 case SP_PE1_MISSING_BITMAP: | |
3344 return sizeof(struct pe1_missing_bitmap_spacket); | |
3345 case SP_PE1_NUM_MISSILES: | |
3346 return sizeof(struct pe1_num_missiles_spacket); | |
3347 default: | |
3348 return -1; | |
3349 } | |
3350 } | |
3351 | |
3352 static void | |
3353 handleExtension1(packet) | |
3354 struct paradiseext1_spacket *packet; | |
3355 { | |
3356 switch (packet->subtype) { | |
3357 case SP_PE1_MISSING_BITMAP: | |
3358 { | |
3359 struct pe1_missing_bitmap_spacket *pkt = | |
3360 (struct pe1_missing_bitmap_spacket *) packet; | |
3361 | |
3362 newMotdPic(ntohs(pkt->x), | |
3363 ntohs(pkt->y), | |
3364 ntohs(pkt->width), | |
3365 ntohs(pkt->height), | |
3366 0, | |
3367 ntohs(pkt->page)); | |
3368 } | |
3369 break; | |
3370 case SP_PE1_NUM_MISSILES: | |
3371 me->p_totmissiles = ntohs(((struct pe1_num_missiles_spacket *) packet)->num); | |
3372 /* printf("updated totmissiles to %d\n",me->p_totmissiles); */ | |
3373 if (me->p_totmissiles < 0) | |
3374 me->p_totmissiles = 0; /* SB/WB have -1 */ | |
3375 break; | |
3376 default: | |
3377 printf("unknown paradise extension packet 1 subtype = %d\n", | |
3378 packet->subtype); | |
3379 } | |
3380 } |