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