1 /* $Id: netserver.c,v 5.33 2002/08/21 14:22:31 bertg Exp $
2 *
3 * XPilot, a multiplayer gravity war game. Copyright (C) 1991-2001 by
4 *
5 * Bj�rn Stabell <bjoern@xpilot.org>
6 * Ken Ronny Schouten <ken@xpilot.org>
7 * Bert Gijsbers <bert@xpilot.org>
8 * Dick Balaska <dick@xpilot.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 /*
26 * This is the server side of the network connnection stuff.
27 *
28 * We try very hard to not let the game be disturbed by
29 * players logging in. Therefore a new connection
30 * passes through several states before it is actively
31 * playing.
32 * First we make a new connection structure available
33 * with a new socket to listen on. This socket port
34 * number is told to the client via the pack mechanism.
35 * In this state the client has to send a packet to this
36 * newly created socket with its name and playing parameters.
37 * If this succeeds the connection advances to its second state.
38 * In this second state the essential server configuration
39 * like the map and so on is transmitted to the client.
40 * If the client has acknowledged all this data then it
41 * advances to the third state, which is the
42 * ready-but-not-playing-yet state. In this state the client
43 * has some time to do its final initializations, like mapping
44 * its user interface windows and so on.
45 * When the client is ready to accept frame updates and process
46 * keyboard events then it sends the start-play packet.
47 * This play packet advances the connection state into the
48 * actively-playing state. A player structure is allocated and
49 * initialized and the other human players are told about this new player.
50 * The newly started client is told about the already playing players and
51 * play has begun.
52 * Apart from these four states there are also two intermediate states.
53 * These intermediate states are entered when the previous state
54 * has filled the reliable data buffer and the client has not
55 * acknowledged all the data yet that is in this reliable data buffer.
56 * They are so called output drain states. Not doing anything else
57 * then waiting until the buffer is empty.
58 * The difference between these two intermediate states is tricky.
59 * The second intermediate state is entered after the
60 * ready-but-not-playing-yet state and before the actively-playing state.
61 * The difference being that in this second intermediate state the client
62 * is already considered an active player by the rest of the server
63 * but should not get frame updates yet until it has acknowledged its last
64 * reliable data.
65 *
66 * Communication between the server and the clients is only done
67 * using UDP datagrams. The first client/serverized version of XPilot
68 * was using TCP only, but this was too unplayable across the Internet,
69 * because TCP is a data stream always sending the next byte.
70 * If a packet gets lost then the server has to wait for a
71 * timeout before a retransmission can occur. This is too slow
72 * for a real-time program like this game, which is more interested
73 * in recent events than in sequenced/reliable events.
74 * Therefore UDP is now used which gives more network control to the
75 * program.
76 * Because some data is considered crucial, like the names of
77 * new players and so on, there also had to be a mechanism which
78 * enabled reliable data transmission. Here this is done by creating
79 * a data stream which is piggybacked on top of the unreliable data
80 * packets. The client acknowledges this reliable data by sending
81 * its byte position in the reliable data stream. So if the client gets
82 * a new reliable data packet and it has not had this data before and
83 * there is also no data packet missing inbetween, then it advances
84 * its byte position and acknowledges this new position to the server.
85 * Otherwise it discards the packet and sends its old byte position
86 * to the server meaning that it detected a packet loss.
87 * The server maintains an acknowledgement timeout timer for each
88 * connection so that it can retransmit a reliable data packet
89 * if the acknowledgement timer expires.
90 */
91
92 #include <stdlib.h>
93 #include <stdio.h>
94 #include <string.h>
95 #include <errno.h>
96 #include <ctype.h>
97 #include <fcntl.h>
98 #include <time.h>
99 #include <sys/types.h>
100 #include <sys/stat.h>
101
102 #ifndef _WINDOWS
103 # include <unistd.h>
104 # include <sys/param.h>
105 # ifdef _AIX
106 # ifndef _BSD_INCLUDES
107 # define _BSD_INCLUDES
108 # endif
109 # endif
110 # ifndef __hpux
111 # include <sys/time.h>
112 # endif
113 # include <sys/socket.h>
114 # include <netinet/in.h>
115 # include <netdb.h>
116 #endif
117
118 #ifdef _WINDOWS
119 # include "NT/winServer.h"
120 # include <io.h>
121 #endif
122
123 #define SERVER
124 #include "version.h"
125 #include "config.h"
126 #include "serverconst.h"
127 #include "global.h"
128 #include "proto.h"
129 #include "map.h"
130 #include "pack.h"
131 #include "bit.h"
132 #include "types.h"
133 #include "socklib.h"
134 #include "sched.h"
135 #include "net.h"
136 #include "error.h"
137 #define NETSERVER_C
138 #include "netserver.h"
139 #include "packet.h"
140 #include "setup.h"
141 #include "connection.h"
142 #undef NETSERVER_C
143 #include "saudio.h"
144 #include "checknames.h"
145 #include "server.h"
146 #include "commonproto.h"
147 #include "asteroid.h"
148 #include "score.h"
149
150 char netserver_version[] = VERSION;
151
152 #define MAX_SELECT_FD (sizeof(int) * 8 - 1)
153 #define MAX_RELIABLE_DATA_PACKET_SIZE 1024
154
155 #define MAX_MOTD_CHUNK 512
156 #define MAX_MOTD_SIZE (30*1024)
157 #define MAX_MOTD_LOOPS (10*FPS)
158
159 static connection_t *Conn = NULL;
160 static int max_connections = 0;
161 static setup_t *Setup = NULL;
162 static int (*playing_receive[256])(int ind),
163 (*login_receive[256])(int ind),
164 (*drain_receive[256])(int ind);
165 int compress_maps = 1;
166 int login_in_progress;
167 static int num_logins, num_logouts;
168
169
170 /*
171 * Compress the map data using a simple Run Length Encoding algorithm.
172 * If there is more than one consecutive byte with the same type
173 * then we set the high bit of the byte and then the next byte
174 * gives the number of repetitions.
175 * This works well for most maps which have lots of series of the
176 * same map object and is simple enough to got implemented quickly.
177 */
Compress_map(unsigned char * map,int size)178 static int Compress_map(unsigned char *map, int size)
179 {
180 int i, j, k;
181
182 for (i = j = 0; i < size; i++, j++) {
183 if (i + 1 < size
184 && map[i] == map[i + 1]) {
185 for (k = 2; i + k < size; k++) {
186 if (map[i] != map[i + k]) {
187 break;
188 }
189 if (k == 255) {
190 break;
191 }
192 }
193 map[j] = (map[i] | SETUP_COMPRESSED);
194 map[++j] = k;
195 i += k - 1;
196 } else {
197 map[j] = map[i];
198 }
199 }
200 return j;
201 }
202
203 /*
204 * Initialize the structure that gives the client information
205 * about our setup. Like the map and playing rules.
206 * We only setup this structure once to save time when new
207 * players log in during play.
208 */
Init_setup(void)209 static int Init_setup(void)
210 {
211 int i, x, y, team, type, size,
212 wormhole = 0,
213 treasure = 0,
214 target = 0,
215 base = 0,
216 cannon = 0;
217 unsigned char *mapdata, *mapptr;
218
219 if ((mapdata = (unsigned char *) malloc(World.x * World.y)) == NULL) {
220 error("No memory for mapdata");
221 return -1;
222 }
223 memset(mapdata, SETUP_SPACE, World.x * World.y);
224 mapptr = mapdata;
225 errno = 0;
226 for (x = 0; x < World.x; x++) {
227 for (y = 0; y < World.y; y++, mapptr++) {
228 type = World.block[x][y];
229 switch (type) {
230 case ACWISE_GRAV:
231 case CWISE_GRAV:
232 case POS_GRAV:
233 case NEG_GRAV:
234 case UP_GRAV:
235 case DOWN_GRAV:
236 case RIGHT_GRAV:
237 case LEFT_GRAV:
238 if (!gravityVisible)
239 type = SPACE;
240 break;
241 case WORMHOLE:
242 if (!wormholeVisible)
243 type = SPACE;
244 break;
245 case ITEM_CONCENTRATOR:
246 if (!itemConcentratorVisible)
247 type = SPACE;
248 break;
249 case ASTEROID_CONCENTRATOR:
250 if (!asteroidConcentratorVisible)
251 type = SPACE;
252 break;
253 case FRICTION:
254 if (!blockFrictionVisible)
255 type = SPACE;
256 else
257 type = DECOR_FILLED;
258 break;
259 default:
260 break;
261 }
262 switch (type) {
263 case SPACE: *mapptr = SETUP_SPACE; break;
264 case FILLED: *mapptr = SETUP_FILLED; break;
265 case REC_RU: *mapptr = SETUP_REC_RU; break;
266 case REC_RD: *mapptr = SETUP_REC_RD; break;
267 case REC_LU: *mapptr = SETUP_REC_LU; break;
268 case REC_LD: *mapptr = SETUP_REC_LD; break;
269 case FUEL: *mapptr = SETUP_FUEL; break;
270 case ACWISE_GRAV: *mapptr = SETUP_ACWISE_GRAV; break;
271 case CWISE_GRAV: *mapptr = SETUP_CWISE_GRAV; break;
272 case POS_GRAV: *mapptr = SETUP_POS_GRAV; break;
273 case NEG_GRAV: *mapptr = SETUP_NEG_GRAV; break;
274 case UP_GRAV: *mapptr = SETUP_UP_GRAV; break;
275 case DOWN_GRAV: *mapptr = SETUP_DOWN_GRAV; break;
276 case RIGHT_GRAV: *mapptr = SETUP_RIGHT_GRAV; break;
277 case LEFT_GRAV: *mapptr = SETUP_LEFT_GRAV; break;
278 case ITEM_CONCENTRATOR: *mapptr = SETUP_ITEM_CONCENTRATOR; break;
279 case ASTEROID_CONCENTRATOR: *mapptr = SETUP_ASTEROID_CONCENTRATOR; break;
280 case DECOR_FILLED: *mapptr = SETUP_DECOR_FILLED; break;
281 case DECOR_RU: *mapptr = SETUP_DECOR_RU; break;
282 case DECOR_RD: *mapptr = SETUP_DECOR_RD; break;
283 case DECOR_LU: *mapptr = SETUP_DECOR_LU; break;
284 case DECOR_LD: *mapptr = SETUP_DECOR_LD; break;
285 case WORMHOLE:
286 switch (World.wormHoles[wormhole++].type) {
287 case WORM_NORMAL: *mapptr = SETUP_WORM_NORMAL; break;
288 case WORM_IN: *mapptr = SETUP_WORM_IN; break;
289 case WORM_OUT: *mapptr = SETUP_WORM_OUT; break;
290 default:
291 error("Bad wormhole (%d,%d).", x, y);
292 free(mapdata);
293 return -1;
294 }
295 break;
296 case TREASURE:
297 *mapptr = SETUP_TREASURE + World.treasures[treasure++].team;
298 break;
299 case TARGET:
300 *mapptr = SETUP_TARGET + World.targets[target++].team;
301 break;
302 case BASE:
303 if (World.base[base].team == TEAM_NOT_SET) {
304 team = 0;
305 } else {
306 team = World.base[base].team;
307 }
308 switch (World.base[base++].dir) {
309 case DIR_UP: *mapptr = SETUP_BASE_UP + team; break;
310 case DIR_RIGHT: *mapptr = SETUP_BASE_RIGHT + team; break;
311 case DIR_DOWN: *mapptr = SETUP_BASE_DOWN + team; break;
312 case DIR_LEFT: *mapptr = SETUP_BASE_LEFT + team; break;
313 default:
314 error("Bad base at (%d,%d).", x, y);
315 free(mapdata);
316 return -1;
317 }
318 break;
319 case CANNON:
320 switch (World.cannon[cannon++].dir) {
321 case DIR_UP: *mapptr = SETUP_CANNON_UP; break;
322 case DIR_RIGHT: *mapptr = SETUP_CANNON_RIGHT; break;
323 case DIR_DOWN: *mapptr = SETUP_CANNON_DOWN; break;
324 case DIR_LEFT: *mapptr = SETUP_CANNON_LEFT; break;
325 default:
326 error("Bad cannon at (%d,%d).", x, y);
327 free(mapdata);
328 return -1;
329 }
330 break;
331 case CHECK:
332 for (i = 0; i < World.NumChecks; i++) {
333 if (x != World.check[i].x
334 || y != World.check[i].y) {
335 continue;
336 }
337 *mapptr = SETUP_CHECK + i;
338 break;
339 }
340 if (i >= World.NumChecks) {
341 error("Bad checkpoint at (%d,%d).", x, y);
342 free(mapdata);
343 return -1;
344 }
345 break;
346 default:
347 error("Unknown map type (%d) at (%d,%d).", type, x, y);
348 *mapptr = SETUP_SPACE;
349 break;
350 }
351 }
352 }
353 if (compress_maps == 0) {
354 type = SETUP_MAP_UNCOMPRESSED;
355 size = World.x * World.y;
356 } else {
357 type = SETUP_MAP_ORDER_XY;
358 size = Compress_map(mapdata, World.x * World.y);
359 if (size <= 0 || size > World.x * World.y) {
360 errno = 0;
361 error("Map compression error (%d)", size);
362 free(mapdata);
363 return -1;
364 }
365 if ((mapdata = (unsigned char *)realloc(mapdata, size)) == NULL) {
366 error("Cannot reallocate mapdata");
367 return -1;
368 }
369 }
370
371 #ifndef SILENT
372 if (type != SETUP_MAP_UNCOMPRESSED) {
373 xpprintf("%s Map compression ratio is %-4.2f%%\n", showtime(),
374 100.0 * size / (World.x * World.y));
375 }
376 #endif
377 if ((Setup = (setup_t *) malloc(sizeof(setup_t) + size)) == NULL) {
378 error("No memory to hold setup");
379 free(mapdata);
380 return -1;
381 }
382 memset(Setup, 0, sizeof(setup_t) + size);
383 memcpy(Setup->map_data, mapdata, size);
384 free(mapdata);
385 Setup->setup_size = ((char *) &Setup->map_data[0] - (char *) Setup) + size;
386 Setup->map_data_len = size;
387 Setup->map_order = type;
388 Setup->frames_per_second = FPS;
389 Setup->lives = World.rules->lives;
390 Setup->mode = World.rules->mode;
391 Setup->x = World.x;
392 Setup->y = World.y;
393 strlcpy(Setup->name, World.name, sizeof(Setup->name));
394 strlcpy(Setup->author, World.author, sizeof(Setup->author));
395
396 return 0;
397 }
398
399 /*
400 * Initialize the function dispatch tables for the various client
401 * connection states. Some states use the same table.
402 */
Init_receive(void)403 static void Init_receive(void)
404 {
405 int i;
406
407 for (i = 0; i < 256; i++) {
408 login_receive[i] = Receive_undefined;
409 playing_receive[i] = Receive_undefined;
410 drain_receive[i] = Receive_undefined;
411 }
412
413 drain_receive[PKT_QUIT] = Receive_quit;
414 drain_receive[PKT_ACK] = Receive_ack;
415 drain_receive[PKT_VERIFY] = Receive_discard;
416 drain_receive[PKT_PLAY] = Receive_discard;
417 drain_receive[PKT_SHAPE] = Receive_discard;
418
419 login_receive[PKT_PLAY] = Receive_play;
420 login_receive[PKT_QUIT] = Receive_quit;
421 login_receive[PKT_ACK] = Receive_ack;
422 login_receive[PKT_VERIFY] = Receive_discard;
423 login_receive[PKT_POWER] = Receive_power;
424 login_receive[PKT_POWER_S] = Receive_power;
425 login_receive[PKT_TURNSPEED] = Receive_power;
426 login_receive[PKT_TURNSPEED_S] = Receive_power;
427 login_receive[PKT_TURNRESISTANCE] = Receive_power;
428 login_receive[PKT_TURNRESISTANCE_S] = Receive_power;
429 login_receive[PKT_DISPLAY] = Receive_display;
430 login_receive[PKT_MODIFIERBANK] = Receive_modifier_bank;
431 login_receive[PKT_MOTD] = Receive_motd;
432 login_receive[PKT_SHAPE] = Receive_shape;
433 login_receive[PKT_REQUEST_AUDIO] = Receive_audio_request;
434 login_receive[PKT_ASYNC_FPS] = Receive_fps_request;
435
436 playing_receive[PKT_ACK] = Receive_ack;
437 playing_receive[PKT_VERIFY] = Receive_discard;
438 playing_receive[PKT_PLAY] = Receive_play;
439 playing_receive[PKT_QUIT] = Receive_quit;
440 playing_receive[PKT_KEYBOARD] = Receive_keyboard;
441 playing_receive[PKT_POWER] = Receive_power;
442 playing_receive[PKT_POWER_S] = Receive_power;
443 playing_receive[PKT_TURNSPEED] = Receive_power;
444 playing_receive[PKT_TURNSPEED_S] = Receive_power;
445 playing_receive[PKT_TURNRESISTANCE] = Receive_power;
446 playing_receive[PKT_TURNRESISTANCE_S] = Receive_power;
447 playing_receive[PKT_ACK_CANNON] = Receive_ack_cannon;
448 playing_receive[PKT_ACK_FUEL] = Receive_ack_fuel;
449 playing_receive[PKT_ACK_TARGET] = Receive_ack_target;
450 playing_receive[PKT_TALK] = Receive_talk;
451 playing_receive[PKT_DISPLAY] = Receive_display;
452 playing_receive[PKT_MODIFIERBANK] = Receive_modifier_bank;
453 playing_receive[PKT_MOTD] = Receive_motd;
454 playing_receive[PKT_SHAPE] = Receive_shape;
455 playing_receive[PKT_POINTER_MOVE] = Receive_pointer_move;
456 playing_receive[PKT_REQUEST_AUDIO] = Receive_audio_request;
457 playing_receive[PKT_ASYNC_FPS] = Receive_fps_request;
458 }
459
460 /*
461 * Initialize the connection structures.
462 */
Setup_net_server(void)463 int Setup_net_server(void)
464 {
465 size_t size;
466
467 Init_receive();
468
469 if (Init_setup() == -1) {
470 return -1;
471 }
472 /*
473 * The number of connections is limited by the number of bases
474 * and the max number of possible file descriptors to use in
475 * the select(2) call minus those for stdin, stdout, stderr,
476 * the contact socket, and the socket for the resolver library routines.
477 */
478 max_connections = MIN(MAX_SELECT_FD - 5, World.NumBases);
479 size = max_connections * sizeof(*Conn);
480 if ((Conn = (connection_t *) malloc(size)) == NULL) {
481 error("Cannot allocate memory for connections");
482 return -1;
483 }
484 memset(Conn, 0, size);
485
486 return 0;
487 }
488
Conn_set_state(connection_t * connp,int state,int drain_state)489 static void Conn_set_state(connection_t *connp, int state, int drain_state)
490 {
491 static int num_conn_busy;
492 static int num_conn_playing;
493
494 if ((connp->state & (CONN_PLAYING | CONN_READY)) != 0) {
495 num_conn_playing--;
496 }
497 else if (connp->state == CONN_FREE) {
498 num_conn_busy++;
499 }
500
501 connp->state = state;
502 connp->drain_state = drain_state;
503 connp->start = main_loops;
504
505 if (connp->state == CONN_PLAYING) {
506 num_conn_playing++;
507 connp->timeout = IDLE_TIMEOUT;
508 }
509 else if (connp->state == CONN_READY) {
510 num_conn_playing++;
511 connp->timeout = READY_TIMEOUT;
512 }
513 else if (connp->state == CONN_LOGIN) {
514 connp->timeout = LOGIN_TIMEOUT;
515 }
516 else if (connp->state == CONN_SETUP) {
517 connp->timeout = SETUP_TIMEOUT;
518 }
519 else if (connp->state == CONN_LISTENING) {
520 connp->timeout = LISTEN_TIMEOUT;
521 }
522 else if (connp->state == CONN_FREE) {
523 num_conn_busy--;
524 connp->timeout = IDLE_TIMEOUT;
525 }
526
527 login_in_progress = num_conn_busy - num_conn_playing;
528 }
529
530 /*
531 * Cleanup a connection. The client may not know yet that
532 * it is thrown out of the game so we send it a quit packet.
533 * We send it twice because of UDP it could get lost.
534 * Since 3.0.6 the client receives a short message
535 * explaining why the connection was terminated.
536 */
Destroy_connection(int ind,const char * reason)537 void Destroy_connection(int ind, const char *reason)
538 {
539 connection_t *connp = &Conn[ind];
540 int id,
541 len;
542 sock_t *sock;
543 char pkt[MAX_CHARS];
544
545 if (connp->state == CONN_FREE) {
546 errno = 0;
547 error("Cannot destroy empty connection (\"%s\")", reason);
548 return;
549 }
550
551 sock = &connp->w.sock;
552 remove_input(sock->fd);
553
554 pkt[0] = PKT_QUIT;
555 strlcpy(&pkt[1], reason, sizeof(pkt) - 1);
556 len = strlen(pkt) + 1;
557 if (sock_write(sock, pkt, len) != len) {
558 sock_get_error(sock);
559 sock_write(sock, pkt, len);
560 }
561 #ifndef SILENT
562 xpprintf("%s Goodbye %s=%s@%s|%s (\"%s\")\n",
563 showtime(),
564 connp->nick ? connp->nick : "",
565 connp->real ? connp->real : "",
566 connp->host ? connp->host : "",
567 connp->dpy ? connp->dpy : "",
568 reason);
569 #endif
570
571 Conn_set_state(connp, CONN_FREE, CONN_FREE);
572
573 if (connp->id != NO_ID) {
574 id = connp->id;
575 connp->id = NO_ID;
576 Players[GetInd[id]]->conn = NOT_CONNECTED;
577 Delete_player(GetInd[id]);
578 }
579 if (connp->real != NULL) {
580 free(connp->real);
581 }
582 if (connp->nick != NULL) {
583 free(connp->nick);
584 }
585 if (connp->dpy != NULL) {
586 free(connp->dpy);
587 }
588 if (connp->addr != NULL) {
589 free(connp->addr);
590 }
591 if (connp->host != NULL) {
592 free(connp->host);
593 }
594 Sockbuf_cleanup(&connp->w);
595 Sockbuf_cleanup(&connp->r);
596 Sockbuf_cleanup(&connp->c);
597
598 num_logouts++;
599
600 if (sock_write(sock, pkt, len) != len) {
601 sock_get_error(sock);
602 sock_write(sock, pkt, len);
603 }
604 sock_close(sock);
605
606 memset(connp, 0, sizeof(*connp));
607 }
608
Check_connection(char * real,char * nick,char * dpy,char * addr)609 int Check_connection(char *real, char *nick, char *dpy, char *addr)
610 {
611 int i;
612 connection_t *connp;
613
614 for (i = 0; i < max_connections; i++) {
615 connp = &Conn[i];
616 if (connp->state == CONN_LISTENING) {
617 if (strcasecmp(connp->nick, nick) == 0) {
618 if (!strcmp(real, connp->real)
619 && !strcmp(dpy, connp->dpy)
620 && !strcmp(addr, connp->addr)) {
621 return connp->my_port;
622 }
623 return -1;
624 }
625 }
626 }
627 return -1;
628 }
629
630 /*
631 * A client has requested a playing connection with this server.
632 * See if we have room for one more player and if his name is not
633 * already in use by some other player. Because the confirmation
634 * may get lost we are willing to send it another time if the
635 * client connection is still in the CONN_LISTENING state.
636 */
Setup_connection(char * real,char * nick,char * dpy,int team,char * addr,char * host,unsigned version)637 int Setup_connection(char *real, char *nick, char *dpy, int team,
638 char *addr, char *host, unsigned version)
639 {
640 int i,
641 free_conn_index = max_connections,
642 my_port;
643 sock_t sock;
644 connection_t *connp;
645
646 for (i = 0; i < max_connections; i++) {
647 connp = &Conn[i];
648 if (connp->state == CONN_FREE) {
649 if (free_conn_index == max_connections) {
650 free_conn_index = i;
651 }
652 continue;
653 }
654 if (strcasecmp(connp->nick, nick) == 0) {
655 if (connp->state == CONN_LISTENING
656 && strcmp(real, connp->real) == 0
657 && strcmp(dpy, connp->dpy) == 0
658 && version == connp->version) {
659 /*
660 * May happen for multi-homed hosts
661 * and if previous packet got lost.
662 */
663 return connp->my_port;
664 } else {
665 /*
666 * Nick already in use.
667 */
668 return -1;
669 }
670 }
671 }
672
673 if (free_conn_index >= max_connections) {
674 #ifndef SILENT
675 xpprintf("%s Full house for %s(%s)@%s(%s)\n",
676 showtime(), real, nick, host, dpy);
677 #endif
678 return -1;
679 }
680 connp = &Conn[free_conn_index];
681 if (clientPortStart && (!clientPortEnd || clientPortEnd > 65535)) {
682 clientPortEnd = 65535;
683 }
684 if (clientPortEnd && (!clientPortStart || clientPortStart < 1024)) {
685 clientPortStart = 1024;
686 }
687
688 if (!clientPortStart || !clientPortEnd ||
689 (clientPortStart > clientPortEnd)) {
690
691 if (sock_open_udp(&sock, serverAddr, 0) == SOCK_IS_ERROR) {
692 error("Cannot create datagram socket (%d)", sock.error.error);
693 return -1;
694 }
695 }
696 else {
697 int found_socket = 0;
698 for (i = clientPortStart; i <= clientPortEnd; i++) {
699 if (sock_open_udp(&sock, serverAddr, i) != SOCK_IS_ERROR) {
700 found_socket = 1;
701 break;
702 }
703 }
704 if (found_socket == 0) {
705 error("Could not find a usable port in given port range");
706 return -1;
707 }
708 }
709
710 if ((my_port = sock_get_port(&sock)) == -1) {
711 error("Cannot get port from socket");
712 sock_close(&sock);
713 return -1;
714 }
715 if (sock_set_non_blocking(&sock, 1) == -1) {
716 error("Cannot make client socket non-blocking");
717 sock_close(&sock);
718 return -1;
719 }
720 if (sock_set_receive_buffer_size(&sock, SERVER_RECV_SIZE + 256) == -1) {
721 error("Cannot set receive buffer size to %d", SERVER_RECV_SIZE + 256);
722 }
723 if (sock_set_send_buffer_size(&sock, SERVER_SEND_SIZE + 256) == -1) {
724 error("Cannot set send buffer size to %d", SERVER_SEND_SIZE + 256);
725 }
726
727 Sockbuf_init(&connp->w, &sock, SERVER_SEND_SIZE,
728 SOCKBUF_WRITE | SOCKBUF_DGRAM);
729
730 Sockbuf_init(&connp->r, &sock, SERVER_RECV_SIZE,
731 SOCKBUF_READ | SOCKBUF_DGRAM);
732
733 Sockbuf_init(&connp->c, (sock_t *) NULL, MAX_SOCKBUF_SIZE,
734 SOCKBUF_WRITE | SOCKBUF_READ | SOCKBUF_LOCK);
735
736 connp->my_port = my_port;
737 connp->real = xp_strdup(real);
738 connp->nick = xp_strdup(nick);
739 connp->dpy = xp_strdup(dpy);
740 connp->addr = xp_strdup(addr);
741 connp->host = xp_strdup(host);
742 connp->ship = NULL;
743 connp->team = team;
744 connp->version = version;
745 connp->start = main_loops;
746 connp->magic = randomMT() + my_port + sock.fd + team + main_loops;
747 connp->id = NO_ID;
748 connp->timeout = LISTEN_TIMEOUT;
749 connp->last_key_change = 0;
750 connp->reliable_offset = 0;
751 connp->reliable_unsent = 0;
752 connp->last_send_loops = 0;
753 connp->retransmit_at_loop = 0;
754 connp->rtt_retransmit = DEFAULT_RETRANSMIT;
755 connp->rtt_smoothed = 0;
756 connp->rtt_dev = 0;
757 connp->rtt_timeouts = 0;
758 connp->acks = 0;
759 connp->setup = 0;
760 connp->motd_offset = -1;
761 connp->motd_stop = 0;
762 connp->view_width = DEF_VIEW_SIZE;
763 connp->view_height = DEF_VIEW_SIZE;
764 connp->debris_colors = 0;
765 connp->spark_rand = DEF_SPARK_RAND;
766 Conn_set_state(connp, CONN_LISTENING, CONN_FREE);
767 if (connp->w.buf == NULL
768 || connp->r.buf == NULL
769 || connp->c.buf == NULL
770 || connp->real == NULL
771 || connp->nick == NULL
772 || connp->dpy == NULL
773 || connp->addr == NULL
774 || connp->host == NULL
775 ) {
776 error("Not enough memory for connection");
777 /* socket is not yet connected, but it doesn't matter much. */
778 Destroy_connection(free_conn_index, "no memory");
779 return -1;
780 }
781
782 install_input(Handle_input, sock.fd, (void *)free_conn_index);
783
784 return my_port;
785 }
786
787 /*
788 * Handle a connection that is in the listening state.
789 */
Handle_listening(int ind)790 static int Handle_listening(int ind)
791 {
792 connection_t *connp = &Conn[ind];
793 unsigned char type;
794 int n;
795 char nick[MAX_CHARS],
796 real[MAX_CHARS];
797
798 if (connp->state != CONN_LISTENING) {
799 Destroy_connection(ind, "not listening");
800 return -1;
801 }
802 Sockbuf_clear(&connp->r);
803 errno = 0;
804 n = sock_receive_any(&connp->r.sock, connp->r.buf, connp->r.size);
805 if (n <= 0) {
806 if (n == 0
807 || errno == EWOULDBLOCK
808 || errno == EAGAIN) {
809 n = 0;
810 }
811 else if (n != 0) {
812 Destroy_connection(ind, "read first packet error");
813 }
814 return n;
815 }
816 connp->r.len = n;
817 connp->his_port = sock_get_last_port(&connp->r.sock);
818 if (sock_connect(&connp->w.sock, connp->addr, connp->his_port) == -1) {
819 error("Cannot connect datagram socket (%s,%d,%d,%d,%d)",
820 connp->addr, connp->his_port,
821 connp->w.sock.error.error,
822 connp->w.sock.error.call,
823 connp->w.sock.error.line);
824 if (sock_get_error(&connp->w.sock)) {
825 error("sock_get_error fails too, giving up");
826 Destroy_connection(ind, "connect error");
827 return -1;
828 }
829 errno = 0;
830 if (sock_connect(&connp->w.sock, connp->addr, connp->his_port) == -1) {
831 error("Still cannot connect datagram socket (%s,%d,%d,%d,%d)",
832 connp->addr, connp->his_port,
833 connp->w.sock.error.error,
834 connp->w.sock.error.call,
835 connp->w.sock.error.line);
836 Destroy_connection(ind, "connect error");
837 return -1;
838 }
839 }
840 #ifndef SILENT
841 xpprintf("%s Welcome %s=%s@%s|%s (%s/%d)", showtime(), connp->nick,
842 connp->real, connp->host, connp->dpy, connp->addr, connp->his_port);
843 if (connp->version != MY_VERSION) {
844 xpprintf(" (version %04x)\n", connp->version);
845 } else {
846 xpprintf("\n");
847 }
848 #endif
849 if (connp->r.ptr[0] != PKT_VERIFY) {
850 Send_reply(ind, PKT_VERIFY, PKT_FAILURE);
851 Send_reliable(ind);
852 Destroy_connection(ind, "not connecting");
853 return -1;
854 }
855 if ((n = Packet_scanf(&connp->r, "%c%s%s",
856 &type, real, nick)) <= 0) {
857 Send_reply(ind, PKT_VERIFY, PKT_FAILURE);
858 Send_reliable(ind);
859 Destroy_connection(ind, "verify incomplete");
860 return -1;
861 }
862 Fix_real_name(real);
863 Fix_nick_name(nick);
864 if (strcmp(real, connp->real)) {
865 #ifndef SILENT
866 xpprintf("%s Client verified incorrectly (%s,%s)(%s,%s)\n",
867 showtime(), real, nick, connp->real, connp->nick);
868 #endif
869 Send_reply(ind, PKT_VERIFY, PKT_FAILURE);
870 Send_reliable(ind);
871 Destroy_connection(ind, "verify incorrect");
872 return -1;
873 }
874 Sockbuf_clear(&connp->w);
875 if (Send_reply(ind, PKT_VERIFY, PKT_SUCCESS) == -1
876 || Packet_printf(&connp->c, "%c%u", PKT_MAGIC, connp->magic) <= 0
877 || Send_reliable(ind) <= 0) {
878 Destroy_connection(ind, "confirm failed");
879 return -1;
880 }
881
882 Conn_set_state(connp, CONN_DRAIN, CONN_SETUP);
883
884 return 1; /* success! */
885 }
886
887 /*
888 * Handle a connection that is in the transmit-server-configuration-data state.
889 */
Handle_setup(int ind)890 static int Handle_setup(int ind)
891 {
892 connection_t *connp = &Conn[ind];
893 char *buf;
894 int n,
895 len;
896
897 if (connp->state != CONN_SETUP) {
898 Destroy_connection(ind, "not setup");
899 return -1;
900 }
901
902 if (connp->setup == 0) {
903 n = Packet_printf(&connp->c,
904 "%ld" "%ld%hd" "%hd%hd" "%hd%hd" "%s%s",
905 Setup->map_data_len,
906 Setup->mode, Setup->lives,
907 Setup->x, Setup->y,
908 Setup->frames_per_second, Setup->map_order,
909 Setup->name, Setup->author);
910 if (n <= 0) {
911 Destroy_connection(ind, "setup 0 write error");
912 return -1;
913 }
914 connp->setup = (char *) &Setup->map_data[0] - (char *) Setup;
915 }
916 else if (connp->setup < Setup->setup_size) {
917 if (connp->c.len > 0) {
918 /* If there is still unacked reliable data test for acks. */
919 Handle_input(-1, (void *) ind);
920 if (connp->state == CONN_FREE) {
921 return -1;
922 }
923 }
924 }
925 if (connp->setup < Setup->setup_size) {
926 len = MIN(connp->c.size, 4096) - connp->c.len;
927 if (len <= 0) {
928 /* Wait for acknowledgement of previously transmitted data. */
929 return 0;
930 }
931 if (len > Setup->setup_size - connp->setup) {
932 len = Setup->setup_size - connp->setup;
933 }
934 buf = (char *) Setup;
935 if (Sockbuf_write(&connp->c, &buf[connp->setup], len) != len) {
936 Destroy_connection(ind, "sockbuf write setup error");
937 return -1;
938 }
939 connp->setup += len;
940 if (len >= 512) {
941 connp->start += (len * FPS) / (8 * 512) + 1;
942 }
943 }
944 if (connp->setup >= Setup->setup_size) {
945 Conn_set_state(connp, CONN_DRAIN, CONN_LOGIN);
946 }
947
948 return 0;
949 }
950
951 /*
952 * A client has requested to start active play.
953 * See if we can allocate a player structure for it
954 * and if this succeeds update the player information
955 * to all connected players.
956 */
Handle_login(int ind,char * errmsg,int errsize)957 static int Handle_login(int ind, char *errmsg, int errsize)
958 {
959 connection_t *connp = &Conn[ind];
960 player *pl;
961 int i,
962 war_on_id,
963 conn_bit;
964 char msg[MSG_LEN];
965
966 if (NumPlayers - NumPseudoPlayers >= World.NumBases) {
967 errno = 0;
968 strlcpy(errmsg, "Not enough bases for players", errsize);
969 error("%s", errmsg);
970 return -1;
971 }
972 if (BIT(World.rules->mode, TEAM_PLAY)) {
973 if (connp->team < 0 || connp->team >= MAX_TEAMS
974 || (reserveRobotTeam && (connp->team == robotTeam))) {
975 connp->team = TEAM_NOT_SET;
976 }
977 else if (World.teams[connp->team].NumBases <= 0) {
978 connp->team = TEAM_NOT_SET;
979 }
980 else {
981 Check_team_members(connp->team);
982 if (World.teams[connp->team].NumMembers
983 - World.teams[connp->team].NumRobots
984 >= World.teams[connp->team].NumBases) {
985 connp->team = TEAM_NOT_SET;
986 }
987 }
988 if (connp->team == TEAM_NOT_SET) {
989 connp->team = Pick_team(PickForHuman);
990 if (connp->team == TEAM_NOT_SET ||
991 (connp->team == robotTeam && reserveRobotTeam)) {
992 errno = 0;
993 strlcpy(errmsg, "Can't pick team", errsize);
994 error("%s", errmsg);
995 return -1;
996 }
997 }
998 } else {
999 connp->team = TEAM_NOT_SET;
1000 }
1001 for (i = 0; i < NumPlayers; i++) {
1002 if (strcasecmp(Players[i]->name, connp->nick) == 0) {
1003 errno = 0;
1004 error("Name already in use %s", connp->nick);
1005 strlcpy(errmsg, "Name already in use", errsize);
1006 return -1;
1007 }
1008 }
1009 if (Init_player(NumPlayers, connp->ship) <= 0) {
1010 strlcpy(errmsg, "Init_player failed: no free ID", errsize);
1011 return -1;
1012 }
1013 pl = Players[NumPlayers];
1014 strlcpy(pl->name, connp->nick, MAX_CHARS);
1015 strlcpy(pl->realname, connp->real, MAX_CHARS);
1016 strlcpy(pl->hostname, connp->host, MAX_CHARS);
1017 pl->isowner = (!strcmp(pl->realname, Server.owner) &&
1018 !strcmp(connp->addr, "127.0.0.1"));
1019 if (connp->team != TEAM_NOT_SET) {
1020 pl->team = connp->team;
1021 }
1022 pl->version = connp->version;
1023
1024 Pick_startpos(NumPlayers);
1025 Go_home(NumPlayers);
1026 if (pl->team != TEAM_NOT_SET) {
1027 World.teams[pl->team].NumMembers++;
1028 if (teamShareScore) {
1029 if (World.teams[pl->team].NumMembers == 1) {
1030 /* reset team score on first player */
1031 World.teams[pl->team].score = 0;
1032 }
1033 TEAM_SCORE(pl->team, 0);
1034 }
1035 }
1036 NumPlayers++;
1037 request_ID();
1038 connp->id = pl->id;
1039 pl->conn = ind;
1040 memset(pl->last_keyv, 0, sizeof(pl->last_keyv));
1041 memset(pl->prev_keyv, 0, sizeof(pl->prev_keyv));
1042
1043 Conn_set_state(connp, CONN_READY, CONN_PLAYING);
1044
1045 if (Send_reply(ind, PKT_PLAY, PKT_SUCCESS) <= 0) {
1046 strlcpy(errmsg, "Cannot send play reply", errsize);
1047 error("%s", errmsg);
1048 return -1;
1049 }
1050
1051 #ifndef SILENT
1052 xpprintf("%s %s (%d) starts at startpos %d.\n", showtime(),
1053 pl->name, NumPlayers, pl->home_base);
1054 #endif
1055
1056 /*
1057 * Tell him about himself first.
1058 */
1059 Send_player(pl->conn, pl->id);
1060 Send_score(pl->conn, pl->id, pl->score,
1061 pl->life, pl->mychar, pl->alliance);
1062 Send_base(pl->conn, pl->id, pl->home_base);
1063 /*
1064 * And tell him about all the others.
1065 */
1066 for (i = 0; i < NumPlayers - 1; i++) {
1067 Send_player(pl->conn, Players[i]->id);
1068 Send_score(pl->conn, Players[i]->id, Players[i]->score,
1069 Players[i]->life, Players[i]->mychar, Players[i]->alliance);
1070 if (!IS_TANK_IND(i)) {
1071 Send_base(pl->conn, Players[i]->id, Players[i]->home_base);
1072 }
1073 }
1074 /*
1075 * And about all the teams.
1076 */
1077 if (BIT(World.rules->mode, TEAM_PLAY)) {
1078 for (i = 0; i < MAX_TEAMS; i++) {
1079 if (World.teams[i].NumMembers > 0) {
1080 Send_team_score(pl->conn, i, World.teams[i].score);
1081 }
1082 }
1083 }
1084 /*
1085 * And tell all the others about him.
1086 */
1087 for (i = 0; i < NumPlayers - 1; i++) {
1088 if (Players[i]->conn != NOT_CONNECTED) {
1089 Send_player(Players[i]->conn, pl->id);
1090 Send_score(Players[i]->conn, pl->id, pl->score,
1091 pl->life, pl->mychar, pl->alliance);
1092 Send_base(Players[i]->conn, pl->id, pl->home_base);
1093 }
1094 /*
1095 * And tell him about the relationships others have with eachother.
1096 */
1097 else if (IS_ROBOT_IND(i)) {
1098 if ((war_on_id = Robot_war_on_player(i)) != NO_ID) {
1099 Send_war(pl->conn, Players[i]->id, war_on_id);
1100 }
1101 }
1102 }
1103
1104 if (NumPlayers == 1) {
1105 sprintf(msg, "Welcome to \"%s\", made by %s.",
1106 World.name, World.author);
1107 } else if (BIT(World.rules->mode, TEAM_PLAY)) {
1108 sprintf(msg, "%s (%s, team %d) has entered \"%s\", made by %s.",
1109 pl->name, pl->realname, pl->team, World.name, World.author);
1110 } else {
1111 sprintf(msg, "%s (%s) has entered \"%s\", made by %s.",
1112 pl->name, pl->realname, World.name, World.author);
1113 }
1114 Set_message(msg);
1115
1116 if (connp->version < MY_VERSION) {
1117 const char sender[] = "[*Server notice*]";
1118 sprintf(msg, "Server runs version %s. %s", VERSION, sender);
1119 Set_player_message(pl, msg);
1120 if (connp->version < 0x4401) {
1121 sprintf(msg,
1122 "Your client does not support the fast radar packet. %s",
1123 sender);
1124 Set_player_message(pl, msg);
1125 }
1126 if (connp->version < 0x4400 && maxAsteroidDensity > 0) {
1127 sprintf(msg,
1128 "Your client will see the %d asteroids as balls. %s",
1129 (int)World.asteroids.max,
1130 sender);
1131 Set_player_message(pl, msg);
1132 }
1133 }
1134
1135 conn_bit = (1 << ind);
1136 for (i = 0; i < World.NumCannons; i++) {
1137 /*
1138 * The client assumes at startup that all cannons are active.
1139 */
1140 if (World.cannon[i].dead_time == 0) {
1141 SET_BIT(World.cannon[i].conn_mask, conn_bit);
1142 } else {
1143 CLR_BIT(World.cannon[i].conn_mask, conn_bit);
1144 }
1145 }
1146 for (i = 0; i < World.NumFuels; i++) {
1147 /*
1148 * The client assumes at startup that all fuelstations are filled.
1149 */
1150 if (World.fuel[i].fuel == MAX_STATION_FUEL) {
1151 SET_BIT(World.fuel[i].conn_mask, conn_bit);
1152 } else {
1153 CLR_BIT(World.fuel[i].conn_mask, conn_bit);
1154 }
1155 }
1156 for (i = 0; i < World.NumTargets; i++) {
1157 /*
1158 * The client assumes at startup that all targets are not damaged.
1159 */
1160 if (World.targets[i].dead_time == 0
1161 && World.targets[i].damage == TARGET_DAMAGE) {
1162 SET_BIT(World.targets[i].conn_mask, conn_bit);
1163 CLR_BIT(World.targets[i].update_mask, conn_bit);
1164 } else {
1165 CLR_BIT(World.targets[i].conn_mask, conn_bit);
1166 SET_BIT(World.targets[i].update_mask, conn_bit);
1167 }
1168 }
1169
1170 sound_player_init(pl);
1171
1172 sound_play_all(START_SOUND);
1173
1174 num_logins++;
1175
1176 if (resetOnHuman > 0
1177 && (NumPlayers - NumPseudoPlayers - NumRobots) <= resetOnHuman
1178 && !round_delay) {
1179 if (BIT(World.rules->mode, TIMING)) {
1180 Race_game_over();
1181 } else if (BIT(World.rules->mode, TEAM_PLAY)) {
1182 Team_game_over(-1, "");
1183 } else if (BIT(World.rules->mode, LIMITED_LIVES)) {
1184 Individual_game_over(-1);
1185 }
1186 }
1187
1188 /* if the next round is delayed, delay it again */
1189 if (round_delay > 0 || NumPlayers == 1) {
1190 round_delay = roundDelaySeconds * FPS;
1191 if (maxRoundTime > 0 && roundDelaySeconds == 0) {
1192 roundtime = maxRoundTime * FPS;
1193 } else {
1194 roundtime = -1;
1195 }
1196 sprintf(msg, "Player entered. Delaying %d seconds until next %s.",
1197 roundDelaySeconds, (BIT(World.rules->mode, TIMING) ?
1198 "race" : "round"));
1199 Set_message(msg);
1200 }
1201
1202 return 0;
1203 }
1204
1205 /*
1206 * Process a client packet.
1207 * The client may be in one of several states,
1208 * therefore we use function dispatch tables for easy processing.
1209 * Some functions may process requests from clients being
1210 * in different states.
1211 */
Handle_input(int fd,void * arg)1212 static void Handle_input(int fd, void *arg)
1213 {
1214 int ind = (int) arg;
1215 connection_t *connp = &Conn[ind];
1216 int type,
1217 result,
1218 (**receive_tbl)(int ind);
1219
1220 if (connp->state & (CONN_PLAYING | CONN_READY)) {
1221 receive_tbl = &playing_receive[0];
1222 }
1223 else if (connp->state == CONN_LOGIN) {
1224 receive_tbl = &login_receive[0];
1225 }
1226 else if (connp->state & (CONN_DRAIN | CONN_SETUP)) {
1227 receive_tbl = &drain_receive[0];
1228 }
1229 else if (connp->state == CONN_LISTENING) {
1230 Handle_listening(ind);
1231 return;
1232 } else {
1233 if (connp->state != CONN_FREE) {
1234 Destroy_connection(ind, "not input");
1235 }
1236 return;
1237 }
1238 connp->num_keyboard_updates = 0;
1239
1240 Sockbuf_clear(&connp->r);
1241 if (Sockbuf_read(&connp->r) == -1) {
1242 Destroy_connection(ind, "input error");
1243 return;
1244 }
1245 if (connp->r.len <= 0) {
1246 /*
1247 * No input.
1248 */
1249 return;
1250 }
1251 while (connp->r.ptr < connp->r.buf + connp->r.len) {
1252 type = (connp->r.ptr[0] & 0xFF);
1253 result = (*receive_tbl[type])(ind);
1254 if (result == -1) {
1255 /*
1256 * Unrecoverable error.
1257 * Connection has been destroyed.
1258 */
1259 return;
1260 }
1261 if (result == 0) {
1262 /*
1263 * Incomplete client packet.
1264 * Drop rest of packet.
1265 */
1266 Sockbuf_clear(&connp->r);
1267 break;
1268 }
1269 if (connp->state == CONN_PLAYING) {
1270 connp->start = main_loops;
1271 }
1272 }
1273 }
1274
Input(void)1275 int Input(void)
1276 {
1277 int i,
1278 ind,
1279 num_reliable = 0,
1280 input_reliable[MAX_SELECT_FD];
1281 connection_t *connp;
1282 char msg[MSG_LEN];
1283
1284 for (i = 0; i < max_connections; i++) {
1285 connp = &Conn[i];
1286 if (connp->state == CONN_FREE) {
1287 continue;
1288 }
1289 if (connp->start + connp->timeout * FPS < main_loops) {
1290 /*
1291 * Timeout this fellow if we have not heard a single thing
1292 * from him for a long time.
1293 */
1294 if (connp->state & (CONN_PLAYING | CONN_READY)) {
1295 sprintf(msg, "%s mysteriously disappeared!?", connp->nick);
1296 Set_message(msg);
1297 }
1298 sprintf(msg, "timeout %02x", connp->state);
1299 Destroy_connection(i, msg);
1300 continue;
1301 }
1302 if (connp->state != CONN_PLAYING) {
1303 input_reliable[num_reliable++] = i;
1304 if (connp->state == CONN_SETUP) {
1305 Handle_setup(i);
1306 continue;
1307 }
1308 }
1309 }
1310
1311 for (i = 0; i < num_reliable; i++) {
1312 ind = input_reliable[i];
1313 connp = &Conn[ind];
1314 if (connp->state & (CONN_DRAIN | CONN_READY | CONN_SETUP
1315 | CONN_LOGIN)) {
1316 if (connp->c.len > 0) {
1317 if (Send_reliable(ind) == -1) {
1318 continue;
1319 }
1320 }
1321 }
1322 }
1323
1324 if (num_logins | num_logouts) {
1325 /* Tell the meta server */
1326 Meta_update(1);
1327 num_logins = 0;
1328 num_logouts = 0;
1329 }
1330
1331 return login_in_progress;
1332 }
1333
1334 /*
1335 * Send a reply to a special client request.
1336 * Not used consistently everywhere.
1337 * It could be used to setup some form of reliable
1338 * communication from the client to the server.
1339 */
Send_reply(int ind,int replyto,int result)1340 int Send_reply(int ind, int replyto, int result)
1341 {
1342 connection_t *connp = &Conn[ind];
1343 int n;
1344
1345 n = Packet_printf(&connp->c, "%c%c%c", PKT_REPLY, replyto, result);
1346 if (n == -1) {
1347 Destroy_connection(ind, "write error");
1348 return -1;
1349 }
1350 return n;
1351 }
1352
Send_modifiers(int ind,char * mods)1353 static int Send_modifiers(int ind, char *mods)
1354 {
1355 return Packet_printf(&Conn[ind].w, "%c%s", PKT_MODIFIERS, mods);
1356 }
1357
1358 /*
1359 * Send items.
1360 * The advantage of this scheme is that it only uses bytes for items
1361 * which the player actually owns. This reduces the packet size.
1362 * Another advantage is that here it doesn't matter if an old client
1363 * receives counts for items it doesn't know about.
1364 * This is new since pack version 4203.
1365 */
Send_self_items(int ind,player * pl)1366 static int Send_self_items(int ind, player *pl)
1367 {
1368 connection_t *connp = &Conn[ind];
1369 unsigned item_mask = 0;
1370 int i, n;
1371 int item_count = 0;
1372
1373 /* older clients should have the items sent as part of the self packet. */
1374 if (connp->version < 0x4203) {
1375 return 1;
1376 }
1377 /* build mask with one bit for each item type which the player owns. */
1378 for (i = 0; i < NUM_ITEMS; i++) {
1379 if (pl->item[i] > 0) {
1380 item_mask |= (1 << i);
1381 item_count++;
1382 }
1383 }
1384 /* don't send anything if there are no items. */
1385 if (item_count == 0) {
1386 return 1;
1387 }
1388 /* check if enough buffer space is available for the complete packet. */
1389 if (connp->w.size - connp->w.len <= 5 + item_count) {
1390 return 0;
1391 }
1392 /* build the header. */
1393 n = Packet_printf(&connp->w, "%c%u", PKT_SELF_ITEMS, item_mask);
1394 if (n <= 0) {
1395 return n;
1396 }
1397 /* build rest of packet containing the per item counts. */
1398 for (i = 0; i < NUM_ITEMS; i++) {
1399 if (item_mask & (1 << i)) {
1400 connp->w.buf[connp->w.len++] = pl->item[i];
1401 }
1402 }
1403 /* return the number of bytes added to the packet. */
1404 return 5 + item_count;
1405 }
1406
1407 /*
1408 * Send all frame data related to the player self and his HUD.
1409 */
Send_self(int ind,player * pl,int lock_id,int lock_dist,int lock_dir,int autopilotlight,long status,char * mods)1410 int Send_self(int ind,
1411 player *pl,
1412 int lock_id,
1413 int lock_dist,
1414 int lock_dir,
1415 int autopilotlight,
1416 long status,
1417 char *mods)
1418 {
1419 connection_t *connp = &Conn[ind];
1420 int n;
1421 u_byte stat = (u_byte)status;
1422 int sbuf_len = connp->w.len;
1423
1424 if (connp->version >= 0x4203) {
1425 n = Packet_printf(&connp->w,
1426 "%c"
1427 "%hd%hd%hd%hd%c"
1428 "%c%c%c"
1429 "%hd%hd%c%c"
1430 "%c%hd%hd"
1431 "%hd%hd%c"
1432 "%c%c"
1433 ,
1434 PKT_SELF,
1435 (int) (pl->pos.x + 0.5), (int) (pl->pos.y + 0.5),
1436 (int) pl->vel.x, (int) pl->vel.y,
1437 pl->dir,
1438 (int) (pl->power + 0.5),
1439 (int) (pl->turnspeed + 0.5),
1440 (int) (pl->turnresistance * 255.0 + 0.5),
1441 lock_id, lock_dist, lock_dir,
1442 pl->check,
1443
1444 pl->fuel.current,
1445 pl->fuel.sum >> FUEL_SCALE_BITS,
1446 pl->fuel.max >> FUEL_SCALE_BITS,
1447
1448 connp->view_width, connp->view_height,
1449 connp->debris_colors,
1450
1451 stat,
1452 autopilotlight
1453
1454 );
1455 if (n <= 0) {
1456 return n;
1457 }
1458 n = Send_self_items(ind, pl);
1459 if (n <= 0) {
1460 return n;
1461 }
1462 return Send_modifiers(ind, mods);
1463 }
1464
1465 n = Packet_printf(&connp->w,
1466 "%c"
1467 "%hd%hd%hd%hd%c"
1468 "%c%c%c"
1469 "%hd%hd%c%c"
1470 "%c%c%c%c%c"
1471 "%c%c%c%c%c"
1472 "%c%c%c%c"
1473 "%c%hd%hd"
1474 "%hd%hd%c"
1475 "%c%c"
1476 ,
1477 PKT_SELF,
1478 (int) (pl->pos.x + 0.5), (int) (pl->pos.y + 0.5),
1479 (int) pl->vel.x, (int) pl->vel.y,
1480 pl->dir,
1481 (int) (pl->power + 0.5),
1482 (int) (pl->turnspeed + 0.5),
1483 (int) (pl->turnresistance * 255.0 + 0.5),
1484 lock_id, lock_dist, lock_dir,
1485 pl->check,
1486
1487 pl->item[ITEM_CLOAK],
1488 pl->item[ITEM_SENSOR],
1489 pl->item[ITEM_MINE],
1490 pl->item[ITEM_MISSILE],
1491 pl->item[ITEM_ECM],
1492
1493 pl->item[ITEM_TRANSPORTER],
1494 pl->item[ITEM_WIDEANGLE],
1495 pl->item[ITEM_REARSHOT],
1496 pl->item[ITEM_AFTERBURNER],
1497 pl->fuel.num_tanks,
1498
1499 pl->item[ITEM_LASER],
1500 pl->item[ITEM_EMERGENCY_THRUST],
1501 pl->item[ITEM_TRACTOR_BEAM],
1502 pl->item[ITEM_AUTOPILOT],
1503
1504 pl->fuel.current,
1505 pl->fuel.sum >> FUEL_SCALE_BITS,
1506 pl->fuel.max >> FUEL_SCALE_BITS,
1507
1508 connp->view_width, connp->view_height,
1509 connp->debris_colors,
1510
1511 stat,
1512 autopilotlight
1513
1514 );
1515 if (n <= 0) {
1516 return n;
1517 }
1518 if (connp->version >= 0x3800) {
1519 n = Packet_printf(&connp->w,
1520 "%c%c%c%c", /* %c", */
1521 pl->item[ITEM_EMERGENCY_SHIELD],
1522 pl->item[ITEM_DEFLECTOR],
1523 pl->item[ITEM_HYPERJUMP],
1524 pl->item[ITEM_PHASING] /* ,
1525 pl->item[ITEM_MIRROR] */
1526 );
1527 if (n <= 0) {
1528 connp->w.len = sbuf_len;
1529 return n;
1530 }
1531 if (connp->version >= 0x4100) {
1532 n = Packet_printf(&connp->w,
1533 "%c",
1534 pl->item[ITEM_MIRROR]
1535 );
1536 if (n <= 0) {
1537 connp->w.len = sbuf_len;
1538 return n;
1539 }
1540 if (connp->version >= 0x4201) {
1541 n = Packet_printf(&connp->w,
1542 "%c",
1543 pl->item[ITEM_ARMOR]
1544 );
1545 if (n <= 0) {
1546 connp->w.len = sbuf_len;
1547 return n;
1548 }
1549 }
1550 }
1551 }
1552 else if (connp->version >= 0x3200) {
1553 n = Packet_printf(&connp->w,
1554 "%c",
1555 pl->item[ITEM_EMERGENCY_SHIELD]);
1556 if (n <= 0) {
1557 connp->w.len = sbuf_len;
1558 return n;
1559 }
1560 }
1561
1562 return Send_modifiers(ind, mods);
1563 }
1564
1565 /*
1566 * Somebody is leaving the game.
1567 */
Send_leave(int ind,int id)1568 int Send_leave(int ind, int id)
1569 {
1570 connection_t *connp = &Conn[ind];
1571
1572 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1573 errno = 0;
1574 error("Connection not ready for leave info (%d,%d)",
1575 connp->state, connp->id);
1576 return 0;
1577 }
1578 return Packet_printf(&connp->c, "%c%hd", PKT_LEAVE, id);
1579 }
1580
1581 /*
1582 * Somebody is declaring war.
1583 */
Send_war(int ind,int robot_id,int killer_id)1584 int Send_war(int ind, int robot_id, int killer_id)
1585 {
1586 connection_t *connp = &Conn[ind];
1587
1588 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1589 errno = 0;
1590 error("Connection not ready for war declaration (%d,%d,%d)",
1591 ind, connp->state, connp->id);
1592 return 0;
1593 }
1594 return Packet_printf(&connp->c, "%c%hd%hd", PKT_WAR,
1595 robot_id, killer_id);
1596 }
1597
1598 /*
1599 * Somebody is programming a robot to seek some player.
1600 */
Send_seek(int ind,int programmer_id,int robot_id,int sought_id)1601 int Send_seek(int ind, int programmer_id, int robot_id, int sought_id)
1602 {
1603 connection_t *connp = &Conn[ind];
1604
1605 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1606 errno = 0;
1607 error("Connection not ready for seek declaration (%d,%d,%d)",
1608 ind, connp->state, connp->id);
1609 return 0;
1610 }
1611 return Packet_printf(&connp->c, "%c%hd%hd%hd", PKT_SEEK,
1612 programmer_id, robot_id, sought_id);
1613 }
1614
1615 /*
1616 * Somebody is joining the game.
1617 */
Send_player(int ind,int id)1618 int Send_player(int ind, int id)
1619 {
1620 connection_t *connp = &Conn[ind];
1621 player *pl = Players[GetInd[id]];
1622 int n;
1623 char buf[MSG_LEN], ext[MSG_LEN];
1624 int sbuf_len = connp->c.len;
1625
1626 if (!BIT(connp->state, CONN_PLAYING|CONN_READY)) {
1627 errno = 0;
1628 error("Connection not ready for player info (%d,%d)",
1629 connp->state, connp->id);
1630 return 0;
1631 }
1632 Convert_ship_2_string(pl->ship, buf, ext,
1633 (connp->version < 0x3200) ? 0x3100 : 0x3200);
1634 n = Packet_printf(&connp->c,
1635 "%c%hd" "%c%c" "%s%s%s" "%S",
1636 PKT_PLAYER, pl->id,
1637 pl->team, pl->mychar,
1638 pl->name, pl->realname, pl->hostname,
1639 buf);
1640 if (connp->version > 0x3200) {
1641 if (n > 0) {
1642 n = Packet_printf(&connp->c, "%S", ext);
1643 if (n <= 0) {
1644 connp->c.len = sbuf_len;
1645 }
1646 }
1647 }
1648 return n;
1649 }
1650
1651 /*
1652 * Send the new score for some player to a client.
1653 */
Send_score(int ind,int id,DFLOAT score,int life,int mychar,int alliance)1654 int Send_score(int ind, int id, DFLOAT score,
1655 int life, int mychar, int alliance)
1656 {
1657 connection_t *connp = &Conn[ind];
1658
1659 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1660 errno = 0;
1661 error("Connection not ready for score(%d,%d)",
1662 connp->state, connp->id);
1663 return 0;
1664 }
1665 if (connp->version < 0x4500) {
1666 /* older clients don't get alliance info or decimals of the score */
1667 return Packet_printf(&connp->c, "%c%hd%hd%hd%c", PKT_SCORE,
1668 id, (int)(score + (score > 0 ? 0.5 : -0.5)),
1669 life, mychar);
1670 } else {
1671 int allchar = ' ';
1672 if (alliance != ALLIANCE_NOT_SET) {
1673 if (announceAlliances) {
1674 allchar = alliance + '0';
1675 } else {
1676 if (Players[GetInd[connp->id]]->alliance == alliance)
1677 allchar = '+';
1678 }
1679 }
1680 return Packet_printf(&connp->c, "%c%hd%d%hd%c%c", PKT_SCORE, id,
1681 (int)(score * 100 + (score > 0 ? 0.5 : -0.5)),
1682 life, mychar, allchar);
1683 }
1684 }
1685
1686 /*
1687 * Send the new score for some team to a client.
1688 */
Send_team_score(int ind,int team,DFLOAT score)1689 int Send_team_score(int ind, int team, DFLOAT score)
1690 {
1691 connection_t *connp = &Conn[ind];
1692
1693 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1694 errno = 0;
1695 error("Connection not ready for team score(%d,%d)",
1696 connp->state, connp->id);
1697 return 0;
1698 }
1699 if (connp->version < 0x4500) {
1700 /* older clients don't know about team scores */
1701 return 0;
1702 }
1703 return Packet_printf(&connp->c, "%c%hd%d", PKT_TEAM_SCORE,
1704 team, (int)(score * 100 + (score > 0 ? 0.5 : -0.5)));
1705 }
1706
1707 /*
1708 * Send the new race info for some player to a client.
1709 */
Send_timing(int ind,int id,int check,int round)1710 int Send_timing(int ind, int id, int check, int round)
1711 {
1712 connection_t *connp = &Conn[ind];
1713
1714 if (connp->version < 0x3261) {
1715 return 1;
1716 }
1717 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1718 errno = 0;
1719 error("Connection not ready for timing(%d,%d)",
1720 connp->state, connp->id);
1721 return 0;
1722 }
1723 return Packet_printf(&connp->c, "%c%hd%hu", PKT_TIMING,
1724 id, round * MAX_CHECKS + check);
1725 }
1726
1727 /*
1728 * Send info about a player having which base.
1729 */
Send_base(int ind,int id,int num)1730 int Send_base(int ind, int id, int num)
1731 {
1732 connection_t *connp = &Conn[ind];
1733
1734 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1735 errno = 0;
1736 error("Connection not ready for base info (%d,%d)",
1737 connp->state, connp->id);
1738 return 0;
1739 }
1740 return Packet_printf(&connp->c, "%c%hd%hu", PKT_BASE, id, num);
1741 }
1742
1743 /*
1744 * Send the amount of fuel in a fuelstation.
1745 */
Send_fuel(int ind,int num,int fuel)1746 int Send_fuel(int ind, int num, int fuel)
1747 {
1748 return Packet_printf(&Conn[ind].w, "%c%hu%hu", PKT_FUEL,
1749 num, fuel >> FUEL_SCALE_BITS);
1750 }
1751
Send_score_object(int ind,DFLOAT score,int x,int y,const char * string)1752 int Send_score_object(int ind, DFLOAT score, int x, int y, const char *string)
1753 {
1754 connection_t *connp = &Conn[ind];
1755
1756 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
1757 errno = 0;
1758 error("Connection not ready for base info (%d,%d)",
1759 connp->state, connp->id);
1760 return 0;
1761 }
1762 if (connp->version < 0x4500) {
1763 /* older clients don't get decimals of the score */
1764 return Packet_printf(&Conn[ind].c, "%c%hd%hu%hu%s",PKT_SCORE_OBJECT,
1765 (int)(score + (score > 0 ? 0.5 : -0.5)),
1766 x, y, string);
1767 } else {
1768 return Packet_printf(&Conn[ind].c, "%c%d%hu%hu%s",PKT_SCORE_OBJECT,
1769 (int)(score * 100 + (score > 0 ? 0.5 : -0.5)),
1770 x, y, string);
1771 }
1772 }
1773
Send_cannon(int ind,int num,int dead_time)1774 int Send_cannon(int ind, int num, int dead_time)
1775 {
1776 return Packet_printf(&Conn[ind].w, "%c%hu%hu", PKT_CANNON,
1777 num, dead_time);
1778 }
1779
Send_destruct(int ind,int count)1780 int Send_destruct(int ind, int count)
1781 {
1782 return Packet_printf(&Conn[ind].w, "%c%hd", PKT_DESTRUCT, count);
1783 }
1784
Send_shutdown(int ind,int count,int delay)1785 int Send_shutdown(int ind, int count, int delay)
1786 {
1787 return Packet_printf(&Conn[ind].w, "%c%hd%hd", PKT_SHUTDOWN,
1788 count, delay);
1789 }
1790
Send_thrusttime(int ind,int count,int max)1791 int Send_thrusttime(int ind, int count, int max)
1792 {
1793 return Packet_printf(&Conn[ind].w, "%c%hd%hd", PKT_THRUSTTIME, count, max);
1794 }
1795
Send_shieldtime(int ind,int count,int max)1796 int Send_shieldtime(int ind, int count, int max)
1797 {
1798 if (Conn[ind].version < 0x3200) {
1799 return 1;
1800 }
1801 return Packet_printf(&Conn[ind].w, "%c%hd%hd", PKT_SHIELDTIME, count, max);
1802 }
1803
Send_phasingtime(int ind,int count,int max)1804 int Send_phasingtime(int ind, int count, int max)
1805 {
1806 if (Conn[ind].version < 0x3800) {
1807 return 1;
1808 }
1809 return Packet_printf(&Conn[ind].w, "%c%hd%hd", PKT_PHASINGTIME, count, max);
1810 }
1811
Send_rounddelay(int ind,int count,int max)1812 int Send_rounddelay(int ind, int count, int max)
1813 {
1814 if (Conn[ind].version < 0x3800) {
1815 return 1;
1816 }
1817 return(Packet_printf(&Conn[ind].w, "%c%hd%hd", PKT_ROUNDDELAY, count, max));
1818 }
1819
Send_debris(int ind,int type,unsigned char * p,int n)1820 int Send_debris(int ind, int type, unsigned char *p, int n)
1821 {
1822 int avail;
1823 sockbuf_t *w = &Conn[ind].w;
1824
1825 if ((n & 0xFF) != n) {
1826 errno = 0;
1827 error("Bad number of debris %d", n);
1828 return 0;
1829 }
1830 avail = w->size - w->len - SOCKBUF_WRITE_SPARE - 2;
1831 if (n * 2 >= avail) {
1832 if (avail > 2) {
1833 n = (avail - 1) / 2;
1834 } else {
1835 return 0;
1836 }
1837 }
1838 w->buf[w->len++] = PKT_DEBRIS + type;
1839 w->buf[w->len++] = n;
1840 memcpy(&w->buf[w->len], p, n * 2);
1841 w->len += n * 2;
1842
1843 return n;
1844 }
1845
Send_wreckage(int ind,int x,int y,u_byte wrtype,u_byte size,u_byte rot)1846 int Send_wreckage(int ind, int x, int y, u_byte wrtype, u_byte size, u_byte rot)
1847 {
1848 if (Conn[ind].version < 0x3800) {
1849 return 1;
1850 }
1851
1852 if (wreckageCollisionMayKill && Conn[ind].version > 0x4201) {
1853 /* Set the highest bit when wreckage is deadly. */
1854 wrtype |= 0x80;
1855 } else {
1856 wrtype &= ~0x80;
1857 }
1858
1859 return Packet_printf(&Conn[ind].w, "%c%hd%hd%c%c%c", PKT_WRECKAGE,
1860 x, y, wrtype, size, rot);
1861 }
1862
Send_asteroid(int ind,int x,int y,u_byte type,u_byte size,u_byte rot)1863 int Send_asteroid(int ind, int x, int y, u_byte type, u_byte size, u_byte rot)
1864 {
1865 u_byte type_size;
1866
1867 if (Conn[ind].version < 0x4400) {
1868 return Send_ecm(ind, x, y, 2 * (int) ASTEROID_RADIUS(size));
1869 }
1870
1871 type_size = ((type & 0x0F) << 4) | (size & 0x0F);
1872
1873 return Packet_printf(&Conn[ind].w, "%c%hd%hd%c%c", PKT_ASTEROID,
1874 x, y, type_size, rot);
1875 }
1876
Send_fastshot(int ind,int type,unsigned char * p,int n)1877 int Send_fastshot(int ind, int type, unsigned char *p, int n)
1878 {
1879 int avail;
1880 sockbuf_t *w = &Conn[ind].w;
1881
1882 if ((n & 0xFF) != n) {
1883 errno = 0;
1884 error("Bad number of fastshot %d", n);
1885 return 0;
1886 }
1887 avail = w->size - w->len - SOCKBUF_WRITE_SPARE - 3;
1888 if (n * 2 >= avail) {
1889 if (avail > 2) {
1890 n = (avail - 1) / 2;
1891 } else {
1892 return 0;
1893 }
1894 }
1895 w->buf[w->len++] = PKT_FASTSHOT;
1896 w->buf[w->len++] = type;
1897 w->buf[w->len++] = n;
1898 memcpy(&w->buf[w->len], p, n * 2);
1899 w->len += n * 2;
1900
1901 return n;
1902 }
1903
Send_missile(int ind,int x,int y,int len,int dir)1904 int Send_missile(int ind, int x, int y, int len, int dir)
1905 {
1906 return Packet_printf(&Conn[ind].w, "%c%hd%hd%c%c",
1907 PKT_MISSILE, x, y, len, dir);
1908 }
1909
Send_ball(int ind,int x,int y,int id)1910 int Send_ball(int ind, int x, int y, int id)
1911 {
1912 return Packet_printf(&Conn[ind].w, "%c%hd%hd%hd", PKT_BALL, x, y, id);
1913 }
1914
Send_mine(int ind,int x,int y,int teammine,int id)1915 int Send_mine(int ind, int x, int y, int teammine, int id)
1916 {
1917 connection_t *connp = &Conn[ind];
1918
1919 return Packet_printf(&connp->w, "%c%hd%hd%c%hd", PKT_MINE, x, y,
1920 teammine, id);
1921 }
1922
Send_target(int ind,int num,int dead_time,int damage)1923 int Send_target(int ind, int num, int dead_time, int damage)
1924 {
1925 return Packet_printf(&Conn[ind].w, "%c%hu%hu%hu", PKT_TARGET,
1926 num, dead_time, damage);
1927 }
1928
Send_wormhole(int ind,int x,int y)1929 int Send_wormhole(int ind, int x, int y)
1930 {
1931 if (Conn[ind].version < 0x4501) {
1932 const int wormStep = 5;
1933 int wormAngle = (frame_loops & 7) * (RES / 8);
1934
1935 return Send_ecm(ind,
1936 x,
1937 y,
1938 BLOCK_SZ - 2) +
1939 Send_ecm(ind,
1940 (int) (x + wormStep * tcos(wormAngle)),
1941 (int) (y + wormStep * tsin(wormAngle)),
1942 BLOCK_SZ - 2 - 2 * wormStep) +
1943 Send_ecm(ind,
1944 (int) (x + 2 * wormStep * tcos(wormAngle)),
1945 (int) (y + 2 * wormStep * tsin(wormAngle)),
1946 BLOCK_SZ - 2 - 4 * wormStep);
1947 }
1948 return Packet_printf(&Conn[ind].w, "%c%hd%hd", PKT_WORMHOLE, x, y);
1949 }
1950
Send_item(int ind,int x,int y,int type)1951 int Send_item(int ind, int x, int y, int type)
1952 {
1953 if (type >= ITEM_EMERGENCY_SHIELD) {
1954 if (Conn[ind].version < 0x3200) {
1955 return 1;
1956 }
1957 }
1958 return Packet_printf(&Conn[ind].w, "%c%hd%hd%c", PKT_ITEM, x, y, type);
1959 }
1960
Send_paused(int ind,int x,int y,int count)1961 int Send_paused(int ind, int x, int y, int count)
1962 {
1963 return Packet_printf(&Conn[ind].w, "%c%hd%hd%hd", PKT_PAUSED, x, y, count);
1964 }
1965
Send_ecm(int ind,int x,int y,int size)1966 int Send_ecm(int ind, int x, int y, int size)
1967 {
1968 return Packet_printf(&Conn[ind].w, "%c%hd%hd%hd", PKT_ECM, x, y, size);
1969 }
1970
Send_trans(int ind,int x1,int y1,int x2,int y2)1971 int Send_trans(int ind, int x1, int y1, int x2, int y2)
1972 {
1973 return Packet_printf(&Conn[ind].w,"%c%hd%hd%hd%hd",
1974 PKT_TRANS, x1, y1, x2, y2);
1975 }
1976
Send_ship(int ind,int x,int y,int id,int dir,int shield,int cloak,int emergency_shield,int phased,int deflector)1977 int Send_ship(int ind, int x, int y, int id, int dir,
1978 int shield, int cloak, int emergency_shield, int phased, int deflector)
1979 {
1980 if (Conn[ind].version < 0x4300) {
1981 /* cloaking bit was also true if phased and that was used
1982 * to determine how to draw the ship.
1983 */
1984 cloak = (cloak || phased);
1985 }
1986 return Packet_printf(&Conn[ind].w,
1987 "%c%hd%hd%hd" "%c" "%c",
1988 PKT_SHIP, x, y, id,
1989 dir,
1990 (shield != 0)
1991 | ((cloak != 0) << 1)
1992 | ((emergency_shield != 0) << 2)
1993 | ((phased != 0) << 3) /* clients older than 3.8.0 will ignore this */
1994 | ((deflector != 0) << 4) /* clients older than 3.8.0 will ignore this */
1995 );
1996 }
1997
Send_refuel(int ind,int x0,int y0,int x1,int y1)1998 int Send_refuel(int ind, int x0, int y0, int x1, int y1)
1999 {
2000 return Packet_printf(&Conn[ind].w,
2001 "%c%hd%hd%hd%hd",
2002 PKT_REFUEL, x0, y0, x1, y1);
2003 }
2004
Send_connector(int ind,int x0,int y0,int x1,int y1,int tractor)2005 int Send_connector(int ind, int x0, int y0, int x1, int y1, int tractor)
2006 {
2007 connection_t *connp = &Conn[ind];
2008
2009 return Packet_printf(&connp->w,
2010 "%c%hd%hd%hd%hd%c",
2011 PKT_CONNECTOR, x0, y0, x1, y1, tractor);
2012 }
2013
Send_laser(int ind,int color,int x,int y,int len,int dir)2014 int Send_laser(int ind, int color, int x, int y, int len, int dir)
2015 {
2016 connection_t *connp = &Conn[ind];
2017
2018 return Packet_printf(&connp->w, "%c%c%hd%hd%hd%c", PKT_LASER,
2019 color, x, y, len, dir);
2020 }
2021
Send_radar(int ind,int x,int y,int size)2022 int Send_radar(int ind, int x, int y, int size)
2023 {
2024 connection_t *connp = &Conn[ind];
2025
2026 /* Only since 4.2.1 can clients correctly handle teammates in green. */
2027 /* Except the original patch from kth.se was 4.1.0 "experimental 1" */
2028 if (connp->version < 0x4210 && connp->version != 0x4101) {
2029 size &= ~0x80;
2030 }
2031 return Packet_printf(&connp->w, "%c%hd%hd%c", PKT_RADAR, x, y, size);
2032 }
2033
Send_fastradar(int ind,unsigned char * buf,int n)2034 int Send_fastradar(int ind, unsigned char *buf, int n)
2035 {
2036 int avail;
2037 sockbuf_t *w = &Conn[ind].w;
2038
2039 if ((n & 0xFF) != n) {
2040 errno = 0;
2041 error("Bad number of fastradar %d", n);
2042 return 0;
2043 }
2044 avail = w->size - w->len - SOCKBUF_WRITE_SPARE - 3;
2045 if (n * 3 >= avail) {
2046 if (avail > 3) {
2047 n = (avail - 2) / 3;
2048 } else {
2049 return 0;
2050 }
2051 }
2052 w->buf[w->len++] = PKT_FASTRADAR;
2053 w->buf[w->len++] = (unsigned char)(n & 0xFF);
2054 memcpy(&w->buf[w->len], buf, n * 3);
2055 w->len += n * 3;
2056
2057 return (2 + (n * 3));
2058 }
2059
Send_damaged(int ind,int damaged)2060 int Send_damaged(int ind, int damaged)
2061 {
2062 return Packet_printf(&Conn[ind].w, "%c%c", PKT_DAMAGED, damaged);
2063 }
2064
Send_audio(int ind,int type,int vol)2065 int Send_audio(int ind, int type, int vol)
2066 {
2067 connection_t *connp = &Conn[ind];
2068
2069 if (connp->w.size - connp->w.len <= 32) {
2070 return 0;
2071 }
2072 return Packet_printf(&connp->w, "%c%c%c", PKT_AUDIO, type, vol);
2073 }
2074
Send_time_left(int ind,long sec)2075 int Send_time_left(int ind, long sec)
2076 {
2077 connection_t *connp = &Conn[ind];
2078
2079 return Packet_printf(&connp->w, "%c%ld", PKT_TIME_LEFT, sec);
2080 }
2081
Send_eyes(int ind,int id)2082 int Send_eyes(int ind, int id)
2083 {
2084 connection_t *connp = &Conn[ind];
2085
2086 return Packet_printf(&connp->w, "%c%hd", PKT_EYES, id);
2087 }
2088
Send_message(int ind,const char * msg)2089 int Send_message(int ind, const char *msg)
2090 {
2091 connection_t *connp = &Conn[ind];
2092
2093 if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
2094 errno = 0;
2095 error("Connection not ready for message (%d,%d)",
2096 connp->state, connp->id);
2097 return 0;
2098 }
2099 return Packet_printf(&connp->c, "%c%S", PKT_MESSAGE, msg);
2100 }
2101
Send_loseitem(int lose_item_index,int ind)2102 int Send_loseitem(int lose_item_index, int ind)
2103 {
2104 if (Conn[ind].version < 0x3400) { /* this should never hit since */
2105 /* only a 3.4+ client would send */
2106 /* the loseitem key */
2107 return 1;
2108 }
2109 return Packet_printf(&Conn[ind].w, "%c%c", PKT_LOSEITEM, lose_item_index);
2110 }
2111
Send_start_of_frame(int ind)2112 int Send_start_of_frame(int ind)
2113 {
2114 connection_t *connp = &Conn[ind];
2115
2116 if (connp->state != CONN_PLAYING) {
2117 if (connp->state != CONN_READY) {
2118 errno = 0;
2119 error("Connection not ready for frame (%d,%d)",
2120 connp->state, connp->id);
2121 }
2122 return -1;
2123 }
2124 /*
2125 * We tell the client which frame number this is and
2126 * which keyboard update we have last received.
2127 */
2128 Sockbuf_clear(&connp->w);
2129 if (Packet_printf(&connp->w,
2130 "%c%ld%ld",
2131 PKT_START, frame_loops, connp->last_key_change) <= 0) {
2132 Destroy_connection(ind, "write error");
2133 return -1;
2134 }
2135
2136 /* Return ok */
2137 return 0;
2138 }
2139
Send_end_of_frame(int ind)2140 int Send_end_of_frame(int ind)
2141 {
2142 connection_t *connp = &Conn[ind];
2143 int n;
2144
2145 last_packet_of_frame = 1;
2146 n = Packet_printf(&connp->w, "%c%ld", PKT_END, frame_loops);
2147 last_packet_of_frame = 0;
2148 if (n == -1) {
2149 Destroy_connection(ind, "write error");
2150 return -1;
2151 }
2152 if (n == 0) {
2153 /*
2154 * Frame update size exceeded buffer size.
2155 * Drop this packet.
2156 */
2157 Sockbuf_clear(&connp->w);
2158 return 0;
2159 }
2160 while (connp->motd_offset >= 0
2161 && connp->c.len + connp->w.len < MAX_RELIABLE_DATA_PACKET_SIZE) {
2162 Send_motd(ind);
2163 }
2164 if (connp->c.len > 0 && connp->w.len < MAX_RELIABLE_DATA_PACKET_SIZE) {
2165 if (Send_reliable(ind) == -1) {
2166 return -1;
2167 }
2168 if (connp->w.len == 0) {
2169 return 1;
2170 }
2171 }
2172 if (Sockbuf_flush(&connp->w) == -1) {
2173 Destroy_connection(ind, "flush error");
2174 return -1;
2175 }
2176 Sockbuf_clear(&connp->w);
2177 return 0;
2178 }
2179
Receive_keyboard(int ind)2180 static int Receive_keyboard(int ind)
2181 {
2182 connection_t *connp = &Conn[ind];
2183 player *pl;
2184 long change;
2185 u_byte ch;
2186 int size = KEYBOARD_SIZE;
2187
2188 if (connp->version < 0x3800) {
2189 /* older servers have a keyboard_size of 8 bytes instead of 9. */
2190 size--;
2191 }
2192 if (connp->r.ptr - connp->r.buf + size + 1 + 4 > connp->r.len) {
2193 /*
2194 * Incomplete client packet.
2195 */
2196 return 0;
2197 }
2198 Packet_scanf(&connp->r, "%c%ld", &ch, &change);
2199 if (change <= connp->last_key_change) {
2200 /*
2201 * We already have this key.
2202 * Nothing to do.
2203 */
2204 connp->r.ptr += size;
2205 }
2206 else {
2207 connp->last_key_change = change;
2208 pl = Players[GetInd[connp->id]];
2209 memcpy(pl->last_keyv, connp->r.ptr, size);
2210 connp->r.ptr += size;
2211 Handle_keyboard(GetInd[connp->id]);
2212 }
2213 if (connp->num_keyboard_updates++ && (connp->state & CONN_PLAYING)) {
2214 Destroy_connection(ind, "no macros");
2215 return -1;
2216 }
2217
2218 return 1;
2219 }
2220
Receive_quit(int ind)2221 static int Receive_quit(int ind)
2222 {
2223 Destroy_connection(ind, "client quit");
2224
2225 return -1;
2226 }
2227
Receive_play(int ind)2228 static int Receive_play(int ind)
2229 {
2230 connection_t *connp = &Conn[ind];
2231 unsigned char ch;
2232 int n;
2233 char errmsg[MAX_CHARS];
2234
2235 if ((n = Packet_scanf(&connp->r, "%c", &ch)) != 1) {
2236 errno = 0;
2237 error("Cannot receive play packet");
2238 Destroy_connection(ind, "receive error");
2239 return -1;
2240 }
2241 if (ch != PKT_PLAY) {
2242 errno = 0;
2243 error("Packet is not of play type");
2244 Destroy_connection(ind, "not play");
2245 return -1;
2246 }
2247 if (connp->state != CONN_LOGIN) {
2248 if (connp->state != CONN_PLAYING) {
2249 if (connp->state == CONN_READY) {
2250 connp->r.ptr = connp->r.buf + connp->r.len;
2251 return 0;
2252 }
2253 errno = 0;
2254 error("Connection not in login state (%02x)", connp->state);
2255 Destroy_connection(ind, "not login");
2256 return -1;
2257 }
2258 if (Send_reliable(ind) == -1) {
2259 return -1;
2260 }
2261 return 0;
2262 }
2263 Sockbuf_clear(&connp->w);
2264 strlcpy(errmsg, "login failed", sizeof(errmsg));
2265 if (Handle_login(ind, errmsg, sizeof(errmsg)) == -1) {
2266 Destroy_connection(ind, errmsg);
2267 return -1;
2268 }
2269
2270 return 2;
2271 }
2272
Receive_power(int ind)2273 static int Receive_power(int ind)
2274 {
2275 connection_t *connp = &Conn[ind];
2276 player *pl;
2277 unsigned char ch;
2278 short tmp;
2279 int n;
2280 DFLOAT power;
2281 int autopilot;
2282
2283 if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &tmp)) <= 0) {
2284 if (n == -1) {
2285 Destroy_connection(ind, "read error");
2286 }
2287 return n;
2288 }
2289 power = (DFLOAT) tmp / 256.0F;
2290 pl = Players[GetInd[connp->id]];
2291 autopilot = BIT(pl->used, HAS_AUTOPILOT);
2292 /* old client are going to send autopilot-mangled data, ignore it */
2293 if (autopilot && pl->version < 0x4200)
2294 return 1;
2295
2296 switch (ch) {
2297 case PKT_POWER:
2298 if (autopilot)
2299 pl->auto_power_s = power;
2300 else
2301 pl->power = power;
2302 break;
2303 case PKT_POWER_S:
2304 pl->power_s = power;
2305 break;
2306 case PKT_TURNSPEED:
2307 if (autopilot)
2308 pl->auto_turnspeed_s = power;
2309 else
2310 pl->turnspeed = power;
2311 break;
2312 case PKT_TURNSPEED_S:
2313 pl->turnspeed_s = power;
2314 break;
2315 case PKT_TURNRESISTANCE:
2316 if (autopilot)
2317 pl->auto_turnresistance_s = power;
2318 else
2319 pl->turnresistance = power;
2320 break;
2321 case PKT_TURNRESISTANCE_S:
2322 pl->turnresistance_s = power;
2323 break;
2324 default:
2325 errno = 0;
2326 error("Not a power packet (%d,%02x)", ch, connp->state);
2327 Destroy_connection(ind, "not power");
2328 return -1;
2329 }
2330 return 1;
2331 }
2332
2333 /*
2334 * Send the reliable data.
2335 * If the client is in the receive-frame-updates state then
2336 * all reliable data is piggybacked at the end of the
2337 * frame update packets. (Except maybe for the MOTD data, which
2338 * could be transmitted in its own packets since MOTDs can be big.)
2339 * Otherwise if the client is not actively playing yet then
2340 * the reliable data is sent in its own packets since there
2341 * is no other data to combine it with.
2342 *
2343 * This thing still is not finished, but it works better than in 3.0.0 I hope.
2344 */
Send_reliable(int ind)2345 int Send_reliable(int ind)
2346 {
2347 connection_t *connp = &Conn[ind];
2348 char *read_buf;
2349 int i,
2350 n,
2351 len,
2352 todo,
2353 max_todo;
2354 long rel_off;
2355 const int max_packet_size = MAX_RELIABLE_DATA_PACKET_SIZE,
2356 min_send_size = 1; /* was 4 in 3.0.7, 1 in 3.1.0 */
2357
2358 if (connp->c.len <= 0
2359 || connp->last_send_loops == main_loops) {
2360 connp->last_send_loops = main_loops;
2361 return 0;
2362 }
2363 read_buf = connp->c.buf;
2364 max_todo = connp->c.len;
2365 rel_off = connp->reliable_offset;
2366 if (connp->w.len > 0) {
2367 /* We are piggybacking on a frame update. */
2368 if (connp->w.len >= max_packet_size - min_send_size) {
2369 /* Frame already too big */
2370 return 0;
2371 }
2372 if (max_todo > max_packet_size - connp->w.len) {
2373 /* Do not exceed minimum fragment size. */
2374 max_todo = max_packet_size - connp->w.len;
2375 }
2376 }
2377 if (connp->retransmit_at_loop > main_loops) {
2378 /*
2379 * It is no time to retransmit yet.
2380 */
2381 if (max_todo <= connp->reliable_unsent - connp->reliable_offset
2382 + min_send_size
2383 || connp->w.len == 0) {
2384 /*
2385 * And we cannot send anything new either
2386 * and we do not want to introduce a new packet.
2387 */
2388 return 0;
2389 }
2390 }
2391 else if (connp->retransmit_at_loop != 0) {
2392 /*
2393 * Timeout.
2394 * Either our packet or the acknowledgement got lost,
2395 * so retransmit.
2396 */
2397 connp->acks >>= 1;
2398 }
2399
2400 todo = max_todo;
2401 for (i = 0; i <= connp->acks && todo > 0; i++) {
2402 len = (todo > max_packet_size) ? max_packet_size : todo;
2403 if (Packet_printf(&connp->w, "%c%hd%ld%ld", PKT_RELIABLE,
2404 len, rel_off, main_loops) <= 0
2405 || Sockbuf_write(&connp->w, read_buf, len) != len) {
2406 error("Cannot write reliable data");
2407 Destroy_connection(ind, "write error");
2408 return -1;
2409 }
2410 if ((n = Sockbuf_flush(&connp->w)) < len) {
2411 if (n == 0
2412 && (errno == EWOULDBLOCK
2413 || errno == EAGAIN)) {
2414 connp->acks = 0;
2415 break;
2416 } else {
2417 error("Cannot flush reliable data (%d)", n);
2418 Destroy_connection(ind, "flush error");
2419 return -1;
2420 }
2421 }
2422 todo -= len;
2423 rel_off += len;
2424 read_buf += len;
2425 }
2426
2427 /*
2428 * Drop rest of outgoing data packet if something remains at all.
2429 */
2430 Sockbuf_clear(&connp->w);
2431
2432 connp->last_send_loops = main_loops;
2433
2434 if (max_todo - todo <= 0) {
2435 /*
2436 * We have not transmitted anything at all.
2437 */
2438 return 0;
2439 }
2440
2441 /*
2442 * Retransmission timer with exponential backoff.
2443 */
2444 if (connp->rtt_retransmit > MAX_RETRANSMIT) {
2445 connp->rtt_retransmit = MAX_RETRANSMIT;
2446 }
2447 if (connp->retransmit_at_loop <= main_loops) {
2448 connp->retransmit_at_loop = main_loops + connp->rtt_retransmit;
2449 connp->rtt_retransmit <<= 1;
2450 connp->rtt_timeouts++;
2451 } else {
2452 connp->retransmit_at_loop = main_loops + connp->rtt_retransmit;
2453 }
2454
2455 if (rel_off > connp->reliable_unsent) {
2456 connp->reliable_unsent = rel_off;
2457 }
2458
2459 return (max_todo - todo);
2460 }
2461
Receive_ack(int ind)2462 static int Receive_ack(int ind)
2463 {
2464 connection_t *connp = &Conn[ind];
2465 int n;
2466 unsigned char ch;
2467 long rel,
2468 rtt, /* RoundTrip Time */
2469 diff,
2470 delta,
2471 rel_loops;
2472
2473 if ((n = Packet_scanf(&connp->r, "%c%ld%ld",
2474 &ch, &rel, &rel_loops)) <= 0) {
2475 errno = 0;
2476 error("Cannot read ack packet (%d)", n);
2477 Destroy_connection(ind, "read error");
2478 return -1;
2479 }
2480 if (ch != PKT_ACK) {
2481 errno = 0;
2482 error("Not an ack packet (%d)", ch);
2483 Destroy_connection(ind, "not ack");
2484 return -1;
2485 }
2486 rtt = main_loops - rel_loops;
2487 if (rtt > 0 && rtt <= MAX_RTT) {
2488 /*
2489 * These roundtrip estimation calculations are derived from Comer's
2490 * books "Internetworking with TCP/IP" parts I & II.
2491 */
2492 if (connp->rtt_smoothed == 0) {
2493 /*
2494 * Initialize the rtt estimator by this first measurement.
2495 * The estimator is scaled by 3 bits.
2496 */
2497 connp->rtt_smoothed = rtt << 3;
2498 }
2499 /*
2500 * Scale the estimator back by 3 bits before calculating the error.
2501 */
2502 delta = rtt - (connp->rtt_smoothed >> 3);
2503 /*
2504 * Add one eigth of the error to the estimator.
2505 */
2506 connp->rtt_smoothed += delta;
2507 /*
2508 * Now we need the absolute value of the error.
2509 */
2510 if (delta < 0) {
2511 delta = -delta;
2512 }
2513 /*
2514 * The rtt deviation is scaled by 2 bits.
2515 * Now we add one fourth of the difference between the
2516 * error and the previous deviation to the deviation.
2517 */
2518 connp->rtt_dev += delta - (connp->rtt_dev >> 2);
2519 /*
2520 * The calculation of the retransmission timeout is what this is
2521 * all about. We take the smoothed rtt plus twice the deviation
2522 * as the next retransmission timeout to use. Because of the
2523 * scaling used we get the following statement:
2524 */
2525 connp->rtt_retransmit = ((connp->rtt_smoothed >> 2)
2526 + connp->rtt_dev) >> 1;
2527 /*
2528 * Now keep it within reasonable bounds.
2529 */
2530 if (connp->rtt_retransmit < MIN_RETRANSMIT) {
2531 connp->rtt_retransmit = MIN_RETRANSMIT;
2532 }
2533 }
2534 diff = rel - connp->reliable_offset;
2535 if (diff > connp->c.len) {
2536 /* Impossible to ack data that has not been send */
2537 errno = 0;
2538 error("Bad ack (diff=%ld,cru=%ld,c=%ld,len=%d)",
2539 diff, rel, connp->reliable_offset, connp->c.len);
2540 Destroy_connection(ind, "bad ack");
2541 return -1;
2542 }
2543 else if (diff <= 0) {
2544 /* Late or duplicate ack of old data. Discard. */
2545 return 1;
2546 }
2547 Sockbuf_advance(&connp->c, (int) diff);
2548 connp->reliable_offset += diff;
2549 if ((n = ((diff + 512 - 1) / 512)) > connp->acks) {
2550 connp->acks = n;
2551 }
2552 else {
2553 connp->acks++;
2554 }
2555 if (connp->reliable_offset >= connp->reliable_unsent) {
2556 /*
2557 * All reliable data has been sent and acked.
2558 */
2559 connp->retransmit_at_loop = 0;
2560 if (connp->state == CONN_DRAIN) {
2561 Conn_set_state(connp, connp->drain_state, connp->drain_state);
2562 }
2563 }
2564 if (connp->state == CONN_READY
2565 && (connp->c.len <= 0
2566 || (connp->c.buf[0] != PKT_REPLY
2567 && connp->c.buf[0] != PKT_PLAY
2568 && connp->c.buf[0] != PKT_SUCCESS
2569 && connp->c.buf[0] != PKT_FAILURE))) {
2570 Conn_set_state(connp, connp->drain_state, connp->drain_state);
2571 }
2572 connp->rtt_timeouts = 0;
2573
2574 return 1;
2575 }
2576
Receive_discard(int ind)2577 static int Receive_discard(int ind)
2578 {
2579 connection_t *connp = &Conn[ind];
2580
2581 errno = 0;
2582 error("Discarding packet %d while in state %02x",
2583 connp->r.ptr[0], connp->state);
2584 connp->r.ptr = connp->r.buf + connp->r.len;
2585
2586 return 0;
2587 }
2588
Receive_undefined(int ind)2589 static int Receive_undefined(int ind)
2590 {
2591 connection_t *connp = &Conn[ind];
2592
2593 errno = 0;
2594 error("Unknown packet type (%d,%02x)", connp->r.ptr[0], connp->state);
2595 Destroy_connection(ind, "undefined packet");
2596 return -1;
2597 }
2598
Receive_ack_cannon(int ind)2599 static int Receive_ack_cannon(int ind)
2600 {
2601 connection_t *connp = &Conn[ind];
2602 long loops_ack;
2603 unsigned char ch;
2604 int n;
2605 unsigned short num;
2606
2607 if ((n = Packet_scanf(&connp->r, "%c%ld%hu",
2608 &ch, &loops_ack, &num)) <= 0) {
2609 if (n == -1) {
2610 Destroy_connection(ind, "read error");
2611 }
2612 return n;
2613 }
2614 if (num >= World.NumCannons) {
2615 Destroy_connection(ind, "bad cannon ack");
2616 return -1;
2617 }
2618 if (loops_ack > World.cannon[num].last_change) {
2619 SET_BIT(World.cannon[num].conn_mask, 1 << ind);
2620 }
2621 return 1;
2622 }
2623
Receive_ack_fuel(int ind)2624 static int Receive_ack_fuel(int ind)
2625 {
2626 connection_t *connp = &Conn[ind];
2627 long loops_ack;
2628 unsigned char ch;
2629 int n;
2630 unsigned short num;
2631
2632 if ((n = Packet_scanf(&connp->r, "%c%ld%hu",
2633 &ch, &loops_ack, &num)) <= 0) {
2634 if (n == -1) {
2635 Destroy_connection(ind, "read error");
2636 }
2637 return n;
2638 }
2639 if (num >= World.NumFuels) {
2640 Destroy_connection(ind, "bad fuel ack");
2641 return -1;
2642 }
2643 if (loops_ack > World.fuel[num].last_change) {
2644 SET_BIT(World.fuel[num].conn_mask, 1 << ind);
2645 }
2646 return 1;
2647 }
2648
Receive_ack_target(int ind)2649 static int Receive_ack_target(int ind)
2650 {
2651 connection_t *connp = &Conn[ind];
2652 long loops_ack;
2653 unsigned char ch;
2654 int n;
2655 unsigned short num;
2656
2657 if ((n = Packet_scanf(&connp->r, "%c%ld%hu",
2658 &ch, &loops_ack, &num)) <= 0) {
2659 if (n == -1) {
2660 Destroy_connection(ind, "read error");
2661 }
2662 return n;
2663 }
2664 if (num >= World.NumTargets) {
2665 Destroy_connection(ind, "bad target ack");
2666 return -1;
2667 }
2668 /*
2669 * Because the "loops" value as received by the client as part
2670 * of a frame update is 1 higher than the actual change to the
2671 * target in collision.c a valid map object change
2672 * acknowledgement must be at least 1 higher.
2673 * That's why we should use the '>' symbol to compare
2674 * and not the '>=' symbol.
2675 * The same applies to cannon and fuelstation updates.
2676 * This fix was discovered for 3.2.7, previously some
2677 * destroyed targets could have been displayed with
2678 * a diagonal cross through them.
2679 */
2680 if (loops_ack > World.targets[num].last_change) {
2681 SET_BIT(World.targets[num].conn_mask, 1 << ind);
2682 CLR_BIT(World.targets[num].update_mask, 1 << ind);
2683 }
2684 return 1;
2685 }
2686
2687 /*
2688 * If a message contains a colon then everything before that colon is
2689 * either a unique player name prefix, or a team number with players.
2690 * If the string does not match one team or one player the message is not sent.
2691 * If no colon, the message is general.
2692 */
Handle_talk(int ind,char * str)2693 static void Handle_talk(int ind, char *str)
2694 {
2695 connection_t *connp = &Conn[ind];
2696 player *pl = Players[GetInd[connp->id]];
2697 int i, sent, team;
2698 unsigned int len;
2699 char *cp,
2700 msg[MSG_LEN * 2];
2701
2702 if ((cp = strchr (str, ':')) == NULL
2703 || cp == str
2704 || strchr("-_~)(/\\}{[]", cp[1]) /* smileys are smileys */
2705 ) {
2706 sprintf(msg, "%s [%s]", str, pl->name);
2707 Set_message(msg);
2708 return;
2709 }
2710 *cp++ = '\0';
2711 len = strlen (str);
2712 sprintf(msg, "%s [%s]", cp, pl->name);
2713
2714 if (strspn(str, "0123456789") == len) { /* Team message */
2715 team = atoi (str);
2716 sprintf(msg + strlen(msg), ":[%d]", team);
2717 for (sent = i = 0; i < NumPlayers; i++) {
2718 if (Players[i]->team != TEAM_NOT_SET && Players[i]->team == team) {
2719 sent++;
2720 Set_player_message (Players[i], msg);
2721 }
2722 }
2723 if (sent) {
2724 if (pl->team != team)
2725 Set_player_message (pl, msg);
2726 } else {
2727 sprintf(msg, "Message not sent, nobody in team %d!",
2728 team);
2729 Set_player_message(pl, msg);
2730 }
2731 }
2732 else if (strcasecmp(str, "god") == 0) {
2733 Server_log_admin_message(GetInd[connp->id], cp);
2734 }
2735 else { /* Player message */
2736 sent = -1;
2737 /* first look for an exact match on player nickname. */
2738 for (i = 0; i < NumPlayers; i++) {
2739 if (strcasecmp(Players[i]->name, str) == 0) {
2740 sent = i;
2741 break;
2742 }
2743 }
2744 if (sent == -1) {
2745 /* now look for a partial match on both nick and realname. */
2746 for (sent = -1, i = 0; i < NumPlayers; i++) {
2747 if (strncasecmp(Players[i]->name, str, len) == 0
2748 || strncasecmp(Players[i]->realname, str, len) == 0)
2749 sent = (sent == -1) ? i : -2;
2750 }
2751 }
2752 switch (sent) {
2753 case -2:
2754 sprintf(msg, "Message not sent, %s matches more than one player!",
2755 str);
2756 Set_player_message(pl, msg);
2757 break;
2758 case -1:
2759 sprintf(msg, "Message not sent, %s does not match any player!",
2760 str);
2761 Set_player_message(pl, msg);
2762 break;
2763 default:
2764 if (Players[sent] != pl) {
2765 sprintf(msg + strlen(msg), ":[%s]", Players[sent]->name);
2766 Set_player_message(Players[sent], msg);
2767 Set_player_message(pl, msg);
2768 }
2769 break;
2770 }
2771 }
2772 }
2773
Receive_talk(int ind)2774 static int Receive_talk(int ind)
2775 {
2776 connection_t *connp = &Conn[ind];
2777 unsigned char ch;
2778 int n;
2779 long seq;
2780 char str[MAX_CHARS];
2781
2782 if ((n = Packet_scanf(&connp->r, "%c%ld%s", &ch, &seq, str)) <= 0) {
2783 if (n == -1) {
2784 Destroy_connection(ind, "read error");
2785 }
2786 return n;
2787 }
2788 if (seq > connp->talk_sequence_num) {
2789 if ((n = Packet_printf(&connp->c, "%c%ld", PKT_TALK_ACK, seq)) <= 0) {
2790 if (n == -1) {
2791 Destroy_connection(ind, "write error");
2792 }
2793 return n;
2794 }
2795 connp->talk_sequence_num = seq;
2796 if (*str == '/') {
2797 Handle_player_command(Players[GetInd[connp->id]], str + 1);
2798 }
2799 else {
2800 Handle_talk(ind, str);
2801 }
2802 }
2803 return 1;
2804 }
2805
Receive_display(int ind)2806 static int Receive_display(int ind)
2807 {
2808 connection_t *connp = &Conn[ind];
2809 unsigned char ch, debris_colors, spark_rand;
2810 short width, height;
2811 int n;
2812
2813 if ((n = Packet_scanf(&connp->r, "%c%hd%hd%c%c", &ch, &width, &height,
2814 &debris_colors, &spark_rand)) <= 0) {
2815 if (n == -1) {
2816 Destroy_connection(ind, "read error");
2817 }
2818 return n;
2819 }
2820 LIMIT(width, MIN_VIEW_SIZE, MAX_VIEW_SIZE);
2821 LIMIT(height, MIN_VIEW_SIZE, MAX_VIEW_SIZE);
2822 connp->view_width = width;
2823 connp->view_height = height;
2824 connp->debris_colors = debris_colors;
2825 connp->spark_rand = spark_rand;
2826 return 1;
2827 }
2828
str2num(char ** strp,int min,int max)2829 static int str2num (char **strp, int min, int max)
2830 {
2831 char *str = *strp;
2832 int num = 0;
2833
2834 while (isdigit(*str)) {
2835 num *= 10;
2836 num += *str++ - '0';
2837 }
2838 *strp = str;
2839 if (num < min || num > max)
2840 return min;
2841 return num;
2842 }
2843
Receive_modifier_bank(int ind)2844 static int Receive_modifier_bank(int ind)
2845 {
2846 connection_t *connp = &Conn[ind];
2847 player *pl;
2848 unsigned char bank;
2849 char str[MAX_CHARS];
2850 unsigned char ch;
2851 char *cp;
2852 modifiers mods;
2853 int n;
2854
2855 if ((n = Packet_scanf(&connp->r, "%c%c%s", &ch, &bank, str)) <= 0) {
2856 if (n == -1) {
2857 Destroy_connection(ind, "read modbank");
2858 }
2859 return n;
2860 }
2861 pl = Players[GetInd[connp->id]];
2862 if (bank < NUM_MODBANKS) {
2863 CLEAR_MODS(mods);
2864 if (BIT(World.rules->mode, ALLOW_MODIFIERS)) {
2865 for (cp = str; *cp; cp++) {
2866 switch (*cp) {
2867 case 'F': case 'f':
2868 if (!BIT(World.rules->mode, ALLOW_NUKES))
2869 break;
2870 if (*(cp+1) == 'N' || *(cp+1) == 'n')
2871 SET_BIT(mods.nuclear, FULLNUCLEAR);
2872 break;
2873 case 'N': case 'n':
2874 if (!BIT(World.rules->mode, ALLOW_NUKES))
2875 break;
2876 SET_BIT(mods.nuclear, NUCLEAR);
2877 break;
2878 case 'C': case 'c':
2879 if (!BIT(World.rules->mode, ALLOW_CLUSTERS))
2880 break;
2881 SET_BIT(mods.warhead, CLUSTER);
2882 break;
2883 case 'I': case 'i':
2884 SET_BIT(mods.warhead, IMPLOSION);
2885 break;
2886 case 'V': case 'v':
2887 cp++; mods.velocity = str2num (&cp, 0, MODS_VELOCITY_MAX);
2888 cp--;
2889 break;
2890 case 'X': case 'x':
2891 cp++; mods.mini = str2num (&cp, 1, MODS_MINI_MAX+1) - 1;
2892 cp--;
2893 break;
2894 case 'Z': case 'z':
2895 cp++; mods.spread = str2num (&cp, 0, MODS_SPREAD_MAX);
2896 cp--;
2897 break;
2898 case 'B': case 'b':
2899 cp++; mods.power = str2num (&cp, 0, MODS_POWER_MAX);
2900 cp--;
2901 break;
2902 case 'L': case 'l':
2903 cp++;
2904 if (!BIT(World.rules->mode, ALLOW_LASER_MODIFIERS))
2905 break;
2906 if (*cp == 'S' || *cp == 's')
2907 SET_BIT(mods.laser, STUN);
2908 if (*cp == 'B' || *cp == 'b')
2909 SET_BIT(mods.laser, BLIND);
2910 break;
2911 }
2912 }
2913 }
2914 pl->modbank[bank] = mods;
2915 }
2916 return 1;
2917 }
2918
Get_display_parameters(int ind,int * width,int * height,int * debris_colors,int * spark_rand)2919 void Get_display_parameters(int ind, int *width, int *height,
2920 int *debris_colors, int *spark_rand)
2921 {
2922 connection_t *connp = &Conn[ind];
2923
2924 *width = connp->view_width;
2925 *height = connp->view_height;
2926 *debris_colors = connp->debris_colors;
2927 *spark_rand = connp->spark_rand;
2928 }
2929
Get_player_id(int ind)2930 int Get_player_id(int ind)
2931 {
2932 connection_t *connp = &Conn[ind];
2933
2934 return connp->id;
2935 }
2936
Get_conn_version(int ind)2937 int Get_conn_version(int ind)
2938 {
2939 connection_t *connp = &Conn[ind];
2940
2941 return connp->version;
2942 }
2943
Get_player_addr(int ind)2944 const char *Get_player_addr(int ind)
2945 {
2946 connection_t *connp = &Conn[ind];
2947
2948 return connp->addr;
2949 }
2950
Get_player_dpy(int ind)2951 const char *Get_player_dpy(int ind)
2952 {
2953 connection_t *connp = &Conn[ind];
2954
2955 return connp->dpy;
2956 }
2957
Receive_shape(int ind)2958 static int Receive_shape(int ind)
2959 {
2960 connection_t *connp = &Conn[ind];
2961 int n;
2962 char ch;
2963 char str[2*MSG_LEN];
2964
2965 if ((n = Packet_scanf(&connp->r, "%c%S", &ch, str)) <= 0) {
2966 if (n == -1) {
2967 Destroy_connection(ind, "read shape");
2968 }
2969 return n;
2970 }
2971 if (connp->version > 0x3200) {
2972 if ((n = Packet_scanf(&connp->r, "%S", &str[strlen(str)])) <= 0) {
2973 if (n == -1) {
2974 Destroy_connection(ind, "read shape ext");
2975 }
2976 return n;
2977 }
2978 }
2979 if (connp->state == CONN_LOGIN && connp->ship == NULL) {
2980 connp->ship = Parse_shape_str(str);
2981 }
2982 return 1;
2983 }
2984
Receive_motd(int ind)2985 static int Receive_motd(int ind)
2986 {
2987 connection_t *connp = &Conn[ind];
2988 unsigned char ch;
2989 long offset;
2990 int n;
2991 long bytes;
2992
2993 if ((n = Packet_scanf(&connp->r,
2994 "%c%ld%ld",
2995 &ch, &offset, &bytes)) <= 0) {
2996 if (n == -1) {
2997 Destroy_connection(ind, "read error");
2998 }
2999 return n;
3000 }
3001 connp->motd_offset = offset;
3002 connp->motd_stop = offset + bytes;
3003
3004 return 1;
3005 }
3006
3007 /*
3008 * Return part of the MOTD into buf starting from offset
3009 * and continueing at most for maxlen bytes.
3010 * Return the total MOTD size in size_ptr.
3011 * The return value is the actual amount of MOTD bytes copied
3012 * or -1 on error. A value of 0 means EndOfMOTD.
3013 *
3014 * The MOTD is completely read into a dynamic buffer.
3015 * If this MOTD buffer hasn't been accessed for a while
3016 * then on the next access the MOTD file is checked for changes.
3017 */
3018 #ifdef _WINDOWS
3019 #define close(__a) _close(__a)
3020 #endif
Get_motd(char * buf,int offset,int maxlen,int * size_ptr)3021 int Get_motd(char *buf, int offset, int maxlen, int *size_ptr)
3022 {
3023 static int motd_size;
3024 static char *motd_buf;
3025 static long motd_loops;
3026 static time_t motd_mtime;
3027
3028 if (size_ptr) {
3029 *size_ptr = 0;
3030 }
3031 if (offset < 0 || maxlen < 0) {
3032 return -1;
3033 }
3034
3035 if (!motd_loops
3036 || (motd_loops + MAX_MOTD_LOOPS < main_loops
3037 && offset == 0)) {
3038
3039 int fd, size;
3040 struct stat st;
3041
3042 motd_loops = main_loops;
3043
3044 if ((fd = open(motdFileName, O_RDONLY)) == -1) {
3045 motd_size = 0;
3046 return -1;
3047 }
3048 if (fstat(fd, &st) == -1 || st.st_size == 0) {
3049 motd_size = 0;
3050 close(fd);
3051 return -1;
3052 }
3053 size = st.st_size;
3054 if (size > MAX_MOTD_SIZE) {
3055 size = MAX_MOTD_SIZE;
3056 }
3057 if (size != motd_size) {
3058 motd_mtime = 0;
3059 motd_size = size;
3060 if (motd_size == 0) {
3061 close(fd);
3062 return 0;
3063 }
3064 if (motd_buf) {
3065 free(motd_buf);
3066 }
3067 if ((motd_buf = (char *) malloc(size)) == NULL) {
3068 close(fd);
3069 return -1;
3070 }
3071 }
3072 if (motd_mtime != st.st_mtime) {
3073 motd_mtime = st.st_mtime;
3074 if ((size = read(fd, motd_buf, motd_size)) <= 0) {
3075 free(motd_buf);
3076 motd_buf = 0;
3077 close(fd);
3078 motd_size = 0;
3079 return -1;
3080 }
3081 motd_size = size;
3082 }
3083 close(fd);
3084 }
3085
3086 motd_loops = main_loops;
3087
3088 if (size_ptr) {
3089 *size_ptr = motd_size;
3090 }
3091 if (offset + maxlen > motd_size) {
3092 maxlen = motd_size - offset;
3093 }
3094 if (maxlen <= 0) {
3095 return 0;
3096 }
3097 memcpy(buf, motd_buf + offset, maxlen);
3098 return maxlen;
3099 }
3100
3101 /*
3102 * Send the server MOTD to the client.
3103 * The last time we send a motd packet it should
3104 * have datalength zero to mean EOMOTD.
3105 */
Send_motd(int ind)3106 static int Send_motd(int ind)
3107 {
3108 connection_t *connp = &Conn[ind];
3109 int len;
3110 int off = connp->motd_offset,
3111 size = 0;
3112 char buf[MAX_MOTD_CHUNK];
3113
3114 len = MIN(MAX_MOTD_CHUNK, MAX_RELIABLE_DATA_PACKET_SIZE - connp->c.len - 10);
3115 if (len >= 10) {
3116 len = Get_motd(buf, off, len, &size);
3117 if (len <= 0) {
3118 len = 0;
3119 connp->motd_offset = -1;
3120 }
3121 if (Packet_printf(&connp->c,
3122 "%c%ld%hd%ld",
3123 PKT_MOTD, off, len, size) <= 0) {
3124 Destroy_connection(ind, "motd header");
3125 return -1;
3126 }
3127 if (len > 0) {
3128 connp->motd_offset += len;
3129 if (Sockbuf_write(&connp->c, buf, len) != len) {
3130 Destroy_connection(ind, "motd data");
3131 return -1;
3132 }
3133 }
3134 }
3135
3136 /* Return ok */
3137 return 1;
3138 }
3139
Receive_pointer_move(int ind)3140 static int Receive_pointer_move(int ind)
3141 {
3142 connection_t *connp = &Conn[ind];
3143 player *pl;
3144 unsigned char ch;
3145 short movement;
3146 int n;
3147 DFLOAT turnspeed, turndir;
3148
3149 if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &movement)) <= 0) {
3150 if (n == -1) {
3151 Destroy_connection(ind, "read error");
3152 }
3153 return n;
3154 }
3155 pl = Players[GetInd[connp->id]];
3156 if (BIT(pl->status, HOVERPAUSE))
3157 return 1;
3158
3159 if (BIT(pl->used, HAS_AUTOPILOT))
3160 Autopilot(GetInd[connp->id], 0);
3161 turnspeed = movement * pl->turnspeed / MAX_PLAYER_TURNSPEED;
3162 if (turnspeed < 0) {
3163 turndir = -1.0;
3164 turnspeed = -turnspeed;
3165 }
3166 else {
3167 turndir = 1.0;
3168 }
3169 if (pl->turnresistance)
3170 LIMIT(turnspeed, MIN_PLAYER_TURNSPEED, MAX_PLAYER_TURNSPEED);
3171 /* Minimum amount of turning if you want to turn at all?
3172 And the only effect of that maximum is making
3173 finding the correct settings harder for new mouse players,
3174 because the limit is checked BEFORE multiplying by turnres!
3175 Kept here to avoid changing the feeling for old players who
3176 are already used to this odd behavior. New players should set
3177 turnresistance to 0.
3178 */
3179 else
3180 LIMIT(turnspeed, 0, 5*RES);
3181
3182 pl->turnvel -= turndir * turnspeed;
3183
3184 return 1;
3185 }
3186
Receive_fps_request(int ind)3187 static int Receive_fps_request(int ind)
3188 {
3189 connection_t *connp = &Conn[ind];
3190 player *pl;
3191 int n;
3192 unsigned char ch;
3193 unsigned char fps;
3194
3195 if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &fps)) <= 0) {
3196 if (n == -1) {
3197 Destroy_connection(ind, "read error");
3198 }
3199 return n;
3200 }
3201 if (connp->id != NO_ID) {
3202 pl = Players[GetInd[connp->id]];
3203 pl->player_fps = fps;
3204 if (fps > FPS) pl->player_fps = FPS;
3205 if (fps < (FPS / 2)) pl->player_fps = (FPS+1) / 2;
3206 if (fps == 0) pl->player_fps = FPS;
3207 if ((fps == 20) && ignore20MaxFPS) pl->player_fps = FPS;
3208 n = FPS - pl->player_fps;
3209 if (n <= 0) {
3210 pl->player_count = 0;
3211 } else {
3212 pl->player_count = FPS / n;
3213 }
3214 }
3215
3216 return 1;
3217 }
3218
Receive_audio_request(int ind)3219 static int Receive_audio_request(int ind)
3220 {
3221 connection_t *connp = &Conn[ind];
3222 player *pl;
3223 int n;
3224 unsigned char ch;
3225 unsigned char onoff;
3226
3227 if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &onoff)) <= 0) {
3228 if (n == -1) {
3229 Destroy_connection(ind, "read error");
3230 }
3231 return n;
3232 }
3233 if (connp->id != NO_ID) {
3234 pl = Players[GetInd[connp->id]];
3235 sound_player_onoff(pl, onoff);
3236 }
3237
3238 return 1;
3239 }
3240
Check_max_clients_per_IP(char * host_addr)3241 int Check_max_clients_per_IP(char *host_addr)
3242 {
3243 int i, clients_per_ip = 0;
3244 connection_t *connp;
3245
3246 if (maxClientsPerIP <= 0)
3247 return 0;
3248
3249 for (i = 0; i < max_connections; i++) {
3250 connp = &Conn[i];
3251 if (connp->state != CONN_FREE && !strcasecmp(connp->addr, host_addr))
3252 clients_per_ip++;
3253 }
3254
3255 if (clients_per_ip >= maxClientsPerIP)
3256 return 1;
3257
3258 return 0;
3259 }
3260
3261