Freeciv-3.1
Loading...
Searching...
No Matches
sernet.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include "fc_prehdrs.h"
19
20#include <errno.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <time.h>
25
26#ifdef FREECIV_HAVE_SYS_TYPES_H
27#include <sys/types.h>
28#endif
29#ifdef HAVE_SYS_SOCKET_H
30#include <sys/socket.h>
31#endif
32#ifdef HAVE_NETINET_IN_H
33#include <netinet/in.h>
34#endif
35#ifdef HAVE_ARPA_INET_H
36#include <arpa/inet.h>
37#endif
38#ifdef HAVE_NETDB_H
39#include <netdb.h>
40#endif
41#ifdef HAVE_PWD_H
42#include <pwd.h>
43#endif
44#ifdef FREECIV_HAVE_LIBREADLINE
45#include <readline/history.h>
46#include <readline/readline.h>
47#endif
48#ifdef HAVE_SYS_SELECT_H
49#include <sys/select.h>
50#endif
51#ifdef HAVE_SYS_TIME_H
52#include <sys/time.h>
53#endif
54#ifdef HAVE_SYS_UIO_H
55#include <sys/uio.h>
56#endif
57#ifdef HAVE_UNISTD_H
58#include <unistd.h>
59#endif
60
61/* utility */
62#include "capability.h"
63#include "fciconv.h"
64#include "fcintl.h"
65#include "log.h"
66#include "mem.h"
67#include "netintf.h"
68#include "shared.h"
69#include "support.h"
70#include "timing.h"
71
72/* common */
73#include "dataio.h"
74#include "events.h"
75#include "game.h"
76#include "packets.h"
77
78/* server/scripting */
79#include "script_server.h"
80
81/* server */
82#include "aiiface.h"
83#include "auth.h"
84#include "connecthand.h"
85#include "console.h"
86#include "meta.h"
87#include "plrhand.h"
88#include "srv_main.h"
89#include "stdinhand.h"
90#include "voting.h"
91
92#include "sernet.h"
93
95
96#ifdef GENERATING_MAC /* mac network globals */
97TEndpointInfo serv_info;
98EndpointRef serv_ep;
99#else
100static int *listen_socks;
101static int listen_count;
102static int socklan;
103#endif
104
105#if defined(__VMS)
106# if defined(_VAX_)
107# define lib$stop LIB$STOP
108# define sys$qiow SYS$QIOW
109# define sys$assign SYS$ASSIGN
110# endif
111# include <descrip.h>
112# include <iodef.h>
113# include <stsdef.h>
114# include <starlet.h>
115# include <lib$routines.h>
116# include <efndef.h>
117 static unsigned long int tt_chan;
118 static char input_char = 0;
119 static char got_input = 0;
120 void user_interrupt_callback();
121#endif
122
123#define PROCESSING_TIME_STATISTICS 0
124
125static int server_accept_connection(int sockfd);
126static void start_processing_request(struct connection *pconn,
127 int request_id);
128static void finish_processing_request(struct connection *pconn);
129static void connection_ping(struct connection *pconn);
130static void send_ping_times_to_all(void);
131
132static void get_lanserver_announcement(void);
133static void send_lanserver_response(void);
134
135static bool no_input = FALSE;
136
137/* Avoid compiler warning about defined, but unused function
138 * by defining it only when needed */
139#if defined(FREECIV_HAVE_LIBREADLINE) || \
140 (!defined(FREECIV_SOCKET_ZERO_NOT_STDIN) && !defined(FREECIV_HAVE_LIBREADLINE))
141/*************************************************************************/
144static void handle_stdin_close(void)
145{
146 /* Note this function may be called even if FREECIV_SOCKET_ZERO_NOT_STDIN, so
147 * the preprocessor check has to come inside the function body. But
148 * perhaps we want to do this even when FREECIV_SOCKET_ZERO_NOT_STDIN? */
149#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
150 log_normal(_("Server cannot read standard input. Ignoring input."));
151 no_input = TRUE;
152#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
153}
154
155#endif /* FREECIV_HAVE_LIBREADLINE || (!FREECIV_SOCKET_ZERO_NOT_STDIN && !FREECIV_HAVE_LIBREADLINE) */
156
157static char *current_internal = NULL;
158
159#ifdef FREECIV_HAVE_LIBREADLINE
160/****************************************************************************/
161
162#define HISTORY_FILENAME "freeciv-server_history"
163#define HISTORY_LENGTH 100
164
165static char *history_file = NULL;
166static bool readline_handled_input = FALSE;
167static bool readline_initialized = FALSE;
168
169/*************************************************************************/
172static void handle_readline_input_callback(char *line)
173{
174 if (no_input) {
175 return;
176 }
177
178 if (line == NULL) {
179 handle_stdin_close(); /* maybe print an 'are you sure?' message? */
180 return;
181 }
182
183 if (line[0] != '\0') {
184 add_history(line);
185 }
186
187 con_prompt_enter(); /* just got an 'Enter' hit */
189 free(line); /* This is already freed if we exit() with /quit command */
191 current_internal = NULL;
192
193 readline_handled_input = TRUE;
194}
195#endif /* FREECIV_HAVE_LIBREADLINE */
196
197/*************************************************************************/
210{
211#ifdef FREECIV_HAVE_LIBREADLINE
212 if (readline_initialized) {
213 rl_callback_handler_remove();
214 readline_initialized = FALSE;
215 }
216#endif /* FREECIV_HAVE_LIBREADLINE */
217
218 if (current_internal != NULL) {
219 free(current_internal);
220 current_internal = NULL;
221 }
222}
223
224/*************************************************************************/
228static void close_connection(struct connection *pconn)
229{
230 if (!pconn) {
231 return;
232 }
233
234 if (pconn->server.ping_timers != NULL) {
235 timer_list_destroy(pconn->server.ping_timers);
236 pconn->server.ping_timers = NULL;
237 }
238
239 conn_pattern_list_destroy(pconn->server.ignore_list);
240 pconn->server.ignore_list = NULL;
241
242 /* safe to do these even if not in lists: */
243 conn_list_remove(game.glob_observers, pconn);
244 conn_list_remove(game.all_connections, pconn);
245 conn_list_remove(game.est_connections, pconn);
246
247 pconn->playing = NULL;
248 pconn->client_gui = GUI_STUB;
249 pconn->access_level = ALLOW_NONE;
251
253}
254
255/*************************************************************************/
260{
261 int i;
262
264
265 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
266 if (connections[i].used) {
268 }
269 conn_list_destroy(connections[i].self);
270 }
271
272 /* Remove the game connection lists and make sure they are empty. */
273 conn_list_destroy(game.glob_observers);
274 conn_list_destroy(game.all_connections);
275 conn_list_destroy(game.est_connections);
276
277 for (i = 0; i < listen_count; i++) {
279 }
281
284 }
285
286#ifdef FREECIV_HAVE_LIBREADLINE
287 if (history_file) {
288 write_history(history_file);
289 history_truncate_file(history_file, HISTORY_LENGTH);
290 free(history_file);
291 history_file = NULL;
292 clear_history();
293 }
294#endif /* FREECIV_HAVE_LIBREADLINE */
295
298
301}
302
303/*************************************************************************/
308{
309 struct connection *closing[MAX_NUM_CONNECTIONS];
310 struct connection *pconn;
311 int i, num;
312
313 do {
314 num = 0;
315
316 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
317 pconn = connections + i;
318 if (pconn->used && pconn->server.is_closing) {
319 closing[num++] = pconn;
320 /* Remove closing connections from the lists (hard detach)
321 * to avoid sending to closing connections. */
322 conn_list_remove(game.glob_observers, pconn);
323 conn_list_remove(game.est_connections, pconn);
324 conn_list_remove(game.all_connections, pconn);
325 if (NULL != conn_get_player(pconn)) {
326 conn_list_remove(conn_get_player(pconn)->connections, pconn);
327 }
328 }
329 }
330
331 for (i = 0; i < num; i++) {
332 /* Now really close them. */
333 pconn = closing[i];
335 close_connection(pconn);
336 }
337 } while (0 < num); /* May some errors occurred, let's check. */
338}
339
340/*************************************************************************/
344static void server_conn_close_callback(struct connection *pconn)
345{
346 /* Do as little as possible here to avoid recursive evil. */
347 pconn->server.is_closing = TRUE;
348}
349
350/*************************************************************************/
354static void cut_lagging_connection(struct connection *pconn)
355{
356 if (!pconn->server.is_closing
357 && game.server.tcptimeout != 0
358 && pconn->last_write
359 && conn_list_size(game.all_connections) > 1
360 && pconn->access_level != ALLOW_HACK
362 /* Cut the connections to players who lag too much. This
363 * usually happens because client animation slows the client
364 * too much and it can't keep up with the server. We don't
365 * cut HACK connections, or cut in single-player games, since
366 * it wouldn't help the game progress. For other connections
367 * the best thing to do when they lag too much is to be
368 * disconnected and reconnect. */
369 log_verbose("connection (%s) cut due to lagging player",
370 conn_description(pconn));
371 connection_close_server(pconn, _("lagging connection"));
372 }
373}
374
375/*************************************************************************/
380{
381 int i;
382 int max_desc;
383 fd_set writefs, exceptfs;
384 fc_timeval tv;
385 time_t start;
386
387 (void) time(&start);
388
389 for (;;) {
390 /* Can't assign to tv.tv_sec directly on systems where it's unsigned */
391 signed signsecs = (game.server.netwait - (time(NULL) - start));
392
393 if (signsecs < 0) {
394 return;
395 }
396
397 tv.tv_usec = 0;
398 tv.tv_sec = signsecs;
399
400 FC_FD_ZERO(&writefs);
401 FC_FD_ZERO(&exceptfs);
402 max_desc = -1;
403
404 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
405 struct connection *pconn = &connections[i];
406
407 if (pconn->used
408 && !pconn->server.is_closing
409 && 0 < pconn->send_buffer->ndata) {
410 FD_SET(pconn->sock, &writefs);
411 FD_SET(pconn->sock, &exceptfs);
412 max_desc = MAX(pconn->sock, max_desc);
413 }
414 }
415
416 if (max_desc == -1) {
417 return;
418 }
419
420 if (fc_select(max_desc + 1, NULL, &writefs, &exceptfs, &tv) <= 0) {
421 return;
422 }
423
424 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) { /* check for freaky players */
425 struct connection *pconn = &connections[i];
426
427 if (pconn->used && !pconn->server.is_closing) {
428 if (FD_ISSET(pconn->sock, &exceptfs)) {
429 log_verbose("connection (%s) cut due to exception data",
430 conn_description(pconn));
431 connection_close_server(pconn, _("network exception"));
432 } else {
433 if (pconn->send_buffer && pconn->send_buffer->ndata > 0) {
434 if (FD_ISSET(pconn->sock, &writefs)) {
436 } else {
438 }
439 }
440 }
441 }
442 }
443 }
444}
445
447 void *data;
449};
450
451/*************************************************************************/
454static bool get_packet(struct connection *pconn,
455 struct packet_to_handle *ppacket)
456{
457 ppacket->data = get_packet_from_connection(pconn, &ppacket->type);
458
459 return NULL != ppacket->data;
460}
461
462/*************************************************************************/
467static void incoming_client_packets(struct connection *pconn)
468{
469 struct packet_to_handle packet;
470#if PROCESSING_TIME_STATISTICS
471 struct timer *request_time = NULL;
472#endif
473
474 while (get_packet(pconn, &packet)) {
475 bool command_ok;
476
477#if PROCESSING_TIME_STATISTICS
478 int request_id;
479
480 request_time = timer_renew(request_time, TIMER_USER, TIMER_ACTIVE);
481 timer_start(request_time);
482#endif /* PROCESSING_TIME_STATISTICS */
483
486
487#if PROCESSING_TIME_STATISTICS
488 request_id = pconn->server.last_request_id_seen;
489#endif /* PROCESSING_TIME_STATISTICS */
490
493
494 command_ok = server_packet_input(pconn, packet.data, packet.type);
495 free(packet.data);
496
499
500#if PROCESSING_TIME_STATISTICS
501 log_verbose("processed request %d in %gms", request_id,
502 timer_read_seconds(request_time) * 1000.0);
503#endif /* PROCESSING_TIME_STATISTICS */
504
505 if (!command_ok) {
506 connection_close_server(pconn, _("rejected"));
507 }
508 }
509
510#if PROCESSING_TIME_STATISTICS
511 timer_destroy(request_time);
512#endif /* PROCESSING_TIME_STATISTICS */
513}
514
515/*************************************************************************/
525{
526 int i, s;
527 int max_desc;
528 bool excepting;
529 fd_set readfs, writefs, exceptfs;
530 fc_timeval tv;
531#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
532 char *bufptr;
533#endif
534
536
537#ifdef FREECIV_HAVE_LIBREADLINE
538 {
539 if (!no_input && !readline_initialized) {
540 char *storage_dir = freeciv_storage_dir();
541
542 if (storage_dir != NULL) {
543 int fcdl = strlen(storage_dir) + 1;
544 char *fc_dir = fc_malloc(fcdl);
545
546 if (fc_dir != NULL) {
547 fc_snprintf(fc_dir, fcdl, "%s", storage_dir);
548
549 if (make_dir(fc_dir)) {
550 history_file
551 = fc_malloc(strlen(fc_dir) + 1 + strlen(HISTORY_FILENAME) + 1);
552 if (history_file) {
553 strcpy(history_file, fc_dir);
554 strcat(history_file, "/");
555 strcat(history_file, HISTORY_FILENAME);
556 using_history();
557 read_history(history_file);
558 }
559 }
560 FC_FREE(fc_dir);
561 }
562 }
563
564 rl_initialize();
565 rl_callback_handler_install((char *) "> ",
566 handle_readline_input_callback);
567 rl_attempted_completion_function = freeciv_completion;
568
569 readline_initialized = TRUE;
570 atexit(readline_atexit);
571 }
572 }
573#endif /* FREECIV_HAVE_LIBREADLINE */
574
575 while (TRUE) {
576 int selret;
577
578 con_prompt_on(); /* accepting new input */
579
580 if (force_end_of_sniff) {
584 }
585
587
588 /* end server if no players for 'srvarg.quitidle' seconds,
589 * but only if at least one player has previously connected. */
590 if (srvarg.quitidle != 0) {
591 static time_t last_noplayers;
592 static bool conns;
593
594 if (conn_list_size(game.est_connections) > 0) {
595 conns = TRUE;
596 }
597 if (conns && conn_list_size(game.est_connections) == 0) {
598 if (last_noplayers != 0) {
599 if (time(NULL) > last_noplayers + srvarg.quitidle) {
600 save_game_auto("Lost all connections", AS_QUITIDLE);
601
602 if (srvarg.exit_on_end) {
603 log_normal(_("Shutting down for lack of players."));
604 set_meta_message_string("shutting down for lack of players");
605 } else {
606 log_normal(_("Restarting for lack of players."));
607 set_meta_message_string("restarting for lack of players");
608 }
610
611 set_server_state(S_S_OVER);
613
614 if (srvarg.exit_on_end) {
615 /* No need for anything more; just quit. */
616 server_quit();
617 }
618
619 /* Do not restart before someone has connected and left again */
620 conns = FALSE;
621 }
622 } else {
623 last_noplayers = time(NULL);
624
625 if (srvarg.exit_on_end) {
626 log_normal(_("Shutting down in %d seconds for lack of players."),
628
629 set_meta_message_string(N_("shutting down soon for lack of players"));
630 } else {
631 log_normal(_("Restarting in %d seconds for lack of players."),
633
634 set_meta_message_string(N_("restarting soon for lack of players"));
635 }
637 }
638 } else {
639 last_noplayers = 0;
640 }
641 }
642
643 /* Pinging around for statistics */
644 if (time(NULL) > (game.server.last_ping + game.server.pingtime)) {
645 /* send data about the previous run */
647
649 if ((!pconn->server.is_closing
650 && 0 < timer_list_size(pconn->server.ping_timers)
651 && timer_read_seconds(timer_list_front
652 (pconn->server.ping_timers))
654 || pconn->ping_time > game.server.pingtimeout) {
655 /* cut mute players, except for hack-level ones */
656 if (pconn->access_level == ALLOW_HACK) {
657 log_verbose("connection (%s) [hack-level] ping timeout ignored",
658 conn_description(pconn));
659 } else {
660 log_verbose("connection (%s) cut due to ping timeout",
661 conn_description(pconn));
662 connection_close_server(pconn, _("ping timeout"));
663 }
664 } else if (pconn->established) {
665 /* We don't send ping to connection not established, because
666 * we wouldn't be able to handle asynchronous ping/pong with
667 * different packet header size. */
668 connection_ping(pconn);
669 }
671 game.server.last_ping = time(NULL);
672 }
673
674 /* if we've waited long enough after a failure, respond to the client */
677 && !pconn->server.is_closing
678 && pconn->server.status != AS_ESTABLISHED) {
679 auth_process_status(pconn);
680 }
682
683 /* Don't wait if timeout == -1 (i.e. on auto games) */
684 if (S_S_RUNNING == server_state() && game.info.timeout == -1) {
689 }
690
691 tv.tv_sec = 1;
692 tv.tv_usec = 0;
693
694 FC_FD_ZERO(&readfs);
695 FC_FD_ZERO(&writefs);
696 FC_FD_ZERO(&exceptfs);
697
698 if (!no_input) {
699#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
700 fc_init_console();
701#else /* FREECIV_SOCKET_ZERO_NOT_STDIN */
702# if !defined(__VMS)
703 FD_SET(0, &readfs);
704# endif /* VMS */
705#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
706 }
707
708 max_desc = 0;
709 for (i = 0; i < listen_count; i++) {
710 FD_SET(listen_socks[i], &readfs);
711 FD_SET(listen_socks[i], &exceptfs);
712 max_desc = MAX(max_desc, listen_socks[i]);
713 }
714
715 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
716 struct connection *pconn = connections + i;
717
718 if (pconn->used && !pconn->server.is_closing) {
719 FD_SET(pconn->sock, &readfs);
720 if (0 < pconn->send_buffer->ndata) {
721 FD_SET(pconn->sock, &writefs);
722 }
723 FD_SET(pconn->sock, &exceptfs);
724 max_desc = MAX(pconn->sock, max_desc);
725 }
726 }
727 con_prompt_off(); /* output doesn't generate a new prompt */
728
729 selret = fc_select(max_desc + 1, &readfs, &writefs, &exceptfs, &tv);
730 if (selret == 0) {
731 /* timeout */
735 if (current_turn_timeout() > 0
736 && S_S_RUNNING == server_state()
743 }
744 if ((game.server.autosaves & (1 << AS_TIMER))
745 && S_S_RUNNING == server_state()
747 >= game.server.save_frequency * 60)) {
748 save_game_auto("Timer", AS_TIMER);
752 }
753
754 if (!no_input) {
755#if defined(__VMS)
756 {
757 struct {
758 short numchars;
759 char firstchar;
760 char reserved;
761 int reserved2;
762 } ttchar;
763 unsigned long status;
764
765 status = sys$qiow(EFN$C_ENF, tt_chan,
766 IO$_SENSEMODE | IO$M_TYPEAHDCNT, 0, 0, 0,
767 &ttchar, sizeof(ttchar), 0, 0, 0, 0);
768 if (!$VMS_STATUS_SUCCESS(status)) {
769 lib$stop(status);
770 }
771 if (ttchar.numchars) {
772 FD_SET(0, &readfs);
773 } else {
774 continue;
775 }
776 }
777#else /* !__VMS */
778#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
780 continue;
781#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
782#endif /* !__VMS */
783 }
784 } else if (selret < 0) {
785 log_error("fc_select() failed: %s", fc_strerror(fc_get_errno()));
786 }
787
788 excepting = FALSE;
789 for (i = 0; i < listen_count; i++) {
790 if (FD_ISSET(listen_socks[i], &exceptfs)) {
791 excepting = TRUE;
792 break;
793 }
794 }
795 if (excepting) { /* handle Ctrl-Z suspend/resume */
796 continue;
797 }
798 for (i = 0; i < listen_count; i++) {
799 s = listen_socks[i];
800 if (FD_ISSET(s, &readfs)) { /* new players connects */
801 log_verbose("got new connection");
802 if (-1 == server_accept_connection(s)) {
803 /* There will be a log_error() message from
804 * server_accept_connection() if something
805 * goes wrong, so no need to make another
806 * error-level message here. */
807 log_verbose("failed accepting connection");
808 }
809 }
810 }
811 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
812 /* check for freaky players */
813 struct connection *pconn = &connections[i];
814
815 if (pconn->used
816 && !pconn->server.is_closing
817 && FD_ISSET(pconn->sock, &exceptfs)) {
818 log_verbose("connection (%s) cut due to exception data",
819 conn_description(pconn));
820 connection_close_server(pconn, _("network exception"));
821 }
822 }
823#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
824 if (!no_input && (bufptr = fc_read_console())) {
826
827 con_prompt_enter(); /* Will need a new prompt, regardless */
829 current_internal = NULL;
830 }
831#else /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
832 if (!no_input && FD_ISSET(0, &readfs)) { /* input from server operator */
833#ifdef FREECIV_HAVE_LIBREADLINE
834 rl_callback_read_char();
835 if (readline_handled_input) {
836 readline_handled_input = FALSE;
838 }
839 continue;
840#else /* !FREECIV_HAVE_LIBREADLINE */
841 ssize_t didget;
842 char *buffer;
843
844#ifdef HAVE_GETLINE
845 size_t len = 0;
846
847 buffer = NULL; /* Must be NULL when calling getline() */
848 didget = getline(&buffer, &len, stdin);
849 if (didget >= 1) {
850 buffer[--didget] = '\0'; /* Overwrite newline character */
851 log_debug("Got line: \"%s\" (" SIZE_T_PRINTF ", " SIZE_T_PRINTF ")", buffer,
852 didget, len);
853 }
854#else /* HAVE_GETLINE */
855 buffer = malloc(BUF_SIZE + 1);
856
857 didget = read(0, buffer, BUF_SIZE);
858 if (didget > 0) {
859 buffer[didget] = '\0';
860 } else {
861 didget = -1; /* Error or end-of-file: closing stdin... */
862 }
863#endif /* HAVE_GETLINE */
864 if (didget < 0) {
866 }
867
868 con_prompt_enter(); /* Will need a new prompt, regardless */
869
870 if (didget >= 0) {
873 current_internal = NULL;
874 }
875 free(buffer);
876#endif /* !FREECIV_HAVE_LIBREADLINE */
877 } else
878#endif /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
879
880 { /* Input from a player */
881 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
882 struct connection *pconn = connections + i;
883 int nb;
884
885 if (!pconn->used
886 || pconn->server.is_closing
887 || !FD_ISSET(pconn->sock, &readfs)) {
888 continue;
889 }
890
891 nb = read_socket_data(pconn->sock, pconn->buffer);
892 if (0 <= nb) {
893 /* We read packets; now handle them. */
895 } else if (-2 == nb) {
896 connection_close_server(pconn, _("client disconnected"));
897 } else {
898 /* Read failure; the connection is closed. */
899 connection_close_server(pconn, _("read error"));
900 }
901 }
902
903 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
904 struct connection *pconn = &connections[i];
905
906 if (pconn->used
907 && !pconn->server.is_closing
908 && pconn->send_buffer
909 && pconn->send_buffer->ndata > 0) {
910 if (FD_ISSET(pconn->sock, &writefs)) {
912 } else {
914 }
915 }
916 }
918 break;
919 }
920 }
922
925
926 if (current_turn_timeout() > 0
927 && S_S_RUNNING == server_state()
933 }
934 if ((game.server.autosaves & (1 << AS_TIMER))
935 && S_S_RUNNING == server_state()
937 >= game.server.save_frequency * 60)) {
938 save_game_auto("Timer", AS_TIMER);
942 }
943
944 return S_E_OTHERWISE;
945}
946
947/*************************************************************************/
955static const char *makeup_connection_name(int *id)
956{
957 static unsigned short i = 0;
958 static char name[MAX_LEN_NAME];
959
960 for (;;) {
961 if (i == (unsigned short) - 1) {
962 /* don't use 0 */
963 i++;
964 }
965 fc_snprintf(name, sizeof(name), "c%u", (unsigned int)++i);
966 if (NULL == player_by_name(name)
967 && NULL == player_by_user(name)
968 && NULL == conn_by_number(i)
969 && NULL == conn_by_user(name)) {
970 *id = i;
971 return name;
972 }
973 }
974}
975
976/*************************************************************************/
982static int server_accept_connection(int sockfd)
983{
984 /* This used to have size_t for some platforms. If this is necessary
985 * it should be done with a configure check not a platform check. */
986 socklen_t fromlen;
987
988 int new_sock;
989 union fc_sockaddr fromend;
990 bool nameinfo = FALSE;
991#ifdef FREECIV_IPV6_SUPPORT
992 char host[NI_MAXHOST], service[NI_MAXSERV];
993 char dst[INET6_ADDRSTRLEN];
994#else /* IPv6 support */
995 struct hostent *from;
996 const char *host = NULL;
997 const char *dst;
998#endif /* IPv6 support */
999
1000 fromlen = sizeof(fromend);
1001
1002 if ((new_sock = accept(sockfd, &fromend.saddr, &fromlen)) == -1) {
1003 log_error("accept failed: %s", fc_strerror(fc_get_errno()));
1004 return -1;
1005 }
1006
1007#ifdef FREECIV_IPV6_SUPPORT
1008 if (fromend.saddr.sa_family == AF_INET6) {
1009 inet_ntop(AF_INET6, &fromend.saddr_in6.sin6_addr,
1010 dst, sizeof(dst));
1011 } else if (fromend.saddr.sa_family == AF_INET) {
1012 inet_ntop(AF_INET, &fromend.saddr_in4.sin_addr, dst, sizeof(dst));
1013 } else {
1015
1016 log_error("Unsupported address family in server_accept_connection()");
1017
1018 return -1;
1019 }
1020#else /* IPv6 support */
1021 dst = inet_ntoa(fromend.saddr_in4.sin_addr);
1022#endif /* IPv6 support */
1023
1025 int count = 0;
1026
1028 if (0 != strcmp(dst, pconn->server.ipaddr)) {
1029 continue;
1030 }
1031 if (++count >= game.server.maxconnectionsperhost) {
1032 log_verbose("Rejecting new connection from %s: maximum number of "
1033 "connections for this address exceeded (%d).",
1035
1036 /* Disconnect the accepted socket. */
1037 fc_closesocket(new_sock);
1038
1039 return -1;
1040 }
1042 }
1043
1044#ifdef FREECIV_IPV6_SUPPORT
1045 nameinfo = (0 == getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
1046 service, NI_MAXSERV, NI_NUMERICSERV)
1047 && '\0' != host[0]);
1048#else /* IPv6 support */
1049 from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
1050 sizeof(fromend.saddr_in4.sin_addr), AF_INET);
1051 if (NULL != from && '\0' != from->h_name[0]) {
1052 host = from->h_name;
1053 nameinfo = TRUE;
1054 }
1055#endif /* IPv6 support */
1056
1057 return server_make_connection(new_sock,
1058 (nameinfo ? host : dst), dst);
1059}
1060
1061/*************************************************************************/
1067int server_make_connection(int new_sock, const char *client_addr,
1068 const char *client_ip)
1069{
1070 struct timer *timer;
1071 int i;
1072
1073 fc_nonblock(new_sock);
1074
1075 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
1076 struct connection *pconn = &connections[i];
1077
1078 if (!pconn->used) {
1080 pconn->sock = new_sock;
1081 pconn->observer = FALSE;
1082 pconn->playing = NULL;
1083 pconn->capability[0] = '\0';
1085 pconn->notify_of_writable_data = NULL;
1087 pconn->server.last_request_id_seen = 0;
1088 pconn->server.auth_tries = 0;
1089 pconn->server.auth_settime = 0;
1091 pconn->server.ping_timers = timer_list_new_full(timer_destroy);
1093 pconn->server.ignore_list =
1094 conn_pattern_list_new_full(conn_pattern_destroy);
1095 pconn->server.is_closing = FALSE;
1096 pconn->ping_time = -1.0;
1097 pconn->incoming_packet_notify = NULL;
1098 pconn->outgoing_packet_notify = NULL;
1099
1100 sz_strlcpy(pconn->username, makeup_connection_name(&pconn->id));
1101 sz_strlcpy(pconn->addr, client_addr);
1102 sz_strlcpy(pconn->server.ipaddr, client_ip);
1103
1104 conn_list_append(game.all_connections, pconn);
1105
1106 log_verbose("connection (%s) from %s (%s)",
1107 pconn->username, pconn->addr, pconn->server.ipaddr);
1108 /* Give a ping timeout to send the PACKET_SERVER_JOIN_REQ, or close
1109 * the mute connection. This timer will be canceled into
1110 * connecthand.c:handle_login_request(). */
1113 timer_list_append(pconn->server.ping_timers, timer);
1114 return 0;
1115 }
1116 }
1117
1118 log_error("maximum number of connections reached");
1119 fc_closesocket(new_sock);
1120 return -1;
1121}
1122
1123/*************************************************************************/
1128{
1129 /* setup socket address */
1130 union fc_sockaddr addr;
1131#ifdef HAVE_IP_MREQN
1132 struct ip_mreqn mreq4;
1133#else
1134 struct ip_mreq mreq4;
1135#endif
1136 const char *cause, *group;
1137 int j, on, s;
1138 int lan_family;
1139 struct fc_sockaddr_list *list;
1140 int name_count;
1141 fc_errno eno = 0;
1142 union fc_sockaddr *problematic = NULL;
1143
1144#ifdef FREECIV_IPV6_SUPPORT
1145 struct ipv6_mreq mreq6;
1146#endif
1147
1148 log_verbose("Server attempting to listen on %s:%d",
1149 srvarg.bind_addr ? srvarg.bind_addr : "(any)",
1150 srvarg.port);
1151
1152 /* Any supported family will do */
1154
1155 name_count = fc_sockaddr_list_size(list);
1156
1157 /* Lookup addresses to bind. */
1158 if (name_count <= 0) {
1159 log_fatal(_("Server: bad address: <%s:%d>."),
1160 srvarg.bind_addr ? srvarg.bind_addr : "(none)", srvarg.port);
1161 exit(EXIT_FAILURE);
1162 }
1163
1164 cause = "internal"; /* If cause is not overwritten but gets printed... */
1165 on = 1;
1166
1167 /* Loop to create sockets, bind, listen. */
1169 listen_count = 0;
1170
1172 /* Create socket for client connections. */
1173 s = socket(paddr->saddr.sa_family, SOCK_STREAM, 0);
1174 if (s == -1) {
1175 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1176 * Kernel might have disabled AF_INET6. */
1177 eno = fc_get_errno();
1178 cause = "socket";
1179 problematic = paddr;
1180 continue;
1181 }
1182
1183#ifndef FREECIV_HAVE_WINSOCK
1184 /* SO_REUSEADDR considered harmful on Win, necessary otherwise */
1185 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1186 (char *)&on, sizeof(on)) == -1) {
1187 log_error("setsockopt SO_REUSEADDR failed: %s",
1189 sockaddr_debug(paddr, LOG_NORMAL);
1190 }
1191#endif /* FREECIV_HAVE_WINSOCK */
1192
1193 /* AF_INET6 sockets should use IPv6 only,
1194 * without stealing IPv4 from AF_INET sockets. */
1195#ifdef FREECIV_IPV6_SUPPORT
1196 if (paddr->saddr.sa_family == AF_INET6) {
1197#ifdef IPV6_V6ONLY
1198 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
1199 (char *)&on, sizeof(on)) == -1) {
1200 log_error("setsockopt IPV6_V6ONLY failed: %s",
1202 sockaddr_debug(paddr, LOG_DEBUG);
1203 }
1204#endif /* IPV6_V6ONLY */
1205 }
1206#endif /* IPv6 support */
1207
1208 if (bind(s, &paddr->saddr, sockaddr_size(paddr)) == -1) {
1209 eno = fc_get_errno();
1210 cause = "bind";
1211 problematic = paddr;
1212
1213 if (eno == EADDRNOTAVAIL) {
1214 /* Close only this socket. This address is not available.
1215 * This can happen with the IPv6 wildcard address if this
1216 * machine has no IPv6 interfaces. */
1217 /* If you change this logic, be sure to make clientside checking
1218 * of acceptable port to match. */
1219 fc_closesocket(s);
1220 continue;
1221 } else {
1222 /* Close all sockets. Another program might have bound to
1223 * one of our addresses, and might hijack some of our
1224 * connections. */
1225 fc_closesocket(s);
1226 for (j = 0; j < listen_count; j++) {
1228 }
1229 listen_count = 0;
1230 break;
1231 }
1232 }
1233
1234 if (listen(s, MAX_NUM_CONNECTIONS) == -1) {
1235 eno = fc_get_errno();
1236 cause = "listen";
1237 problematic = paddr;
1238 fc_closesocket(s);
1239 continue;
1240 }
1241
1244
1245 if (listen_count == 0) {
1246 log_fatal("%s failure: %s (%d failed)", cause, fc_strerror(eno), name_count);
1247 if (problematic != NULL) {
1248 sockaddr_debug(problematic, LOG_NORMAL);
1249 }
1251 /* Do not list already logged 'problematic' again */
1252 if (paddr != problematic) {
1253 sockaddr_debug(paddr, LOG_DEBUG);
1254 }
1256 exit(EXIT_FAILURE);
1257 }
1258
1259 fc_sockaddr_list_destroy(list);
1260
1262
1263 if (srvarg.announce == ANNOUNCE_NONE) {
1264 return 0;
1265 }
1266
1267#ifdef FREECIV_IPV6_SUPPORT
1268 if (srvarg.announce == ANNOUNCE_IPV6) {
1269 lan_family = AF_INET6;
1270 } else
1271#endif /* IPV6 support */
1272 {
1273 lan_family = AF_INET;
1274 }
1275
1276 /* Create socket for server LAN announcements */
1277 if ((socklan = socket(lan_family, SOCK_DGRAM, 0)) < 0) {
1278 log_error("Announcement socket failed: %s", fc_strerror(fc_get_errno()));
1279 return 0; /* FIXME: Should this cause hard error as exit(EXIT_FAILURE).
1280 * It's failure to do as commandline parameters requested after all */
1281 }
1282
1283 if (setsockopt(socklan, SOL_SOCKET, SO_REUSEADDR,
1284 (char *)&on, sizeof(on)) == -1) {
1285 log_error("SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1286 }
1287
1289
1291
1292 memset(&addr, 0, sizeof(addr));
1293
1294 addr.saddr.sa_family = lan_family;
1295
1296#ifdef FREECIV_IPV6_SUPPORT
1297 if (addr.saddr.sa_family == AF_INET6) {
1298 addr.saddr_in6.sin6_family = AF_INET6;
1299 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT);
1300 addr.saddr_in6.sin6_addr = in6addr_any;
1301 } else
1302#endif /* IPv6 support */
1303 if (addr.saddr.sa_family == AF_INET) {
1304 addr.saddr_in4.sin_family = AF_INET;
1305 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT);
1306 addr.saddr_in4.sin_addr.s_addr = htonl(INADDR_ANY);
1307 } else {
1309
1310 log_error("Unsupported address family in server_open_socket()");
1311 }
1312
1313 if (bind(socklan, &addr.saddr, sockaddr_size(&addr)) < 0) {
1314 log_error("Announcement socket binding failed: %s", fc_strerror(fc_get_errno()));
1315 }
1316
1317#ifdef FREECIV_IPV6_SUPPORT
1318 if (addr.saddr.sa_family == AF_INET6) {
1319 inet_pton(AF_INET6, group, &mreq6.ipv6mr_multiaddr.s6_addr);
1320 mreq6.ipv6mr_interface = 0; /* TODO: Interface selection */
1321 if (setsockopt(socklan, IPPROTO_IPV6, FC_IPV6_ADD_MEMBERSHIP,
1322 (const char*)&mreq6, sizeof(mreq6)) < 0) {
1323 log_error("FC_IPV6_ADD_MEMBERSHIP (%s) failed: %s",
1324 group, fc_strerror(fc_get_errno()));
1325 }
1326 } else
1327#endif /* IPV6 Support */
1328 if (addr.saddr.sa_family == AF_INET) {
1329 fc_inet_aton(group, &mreq4.imr_multiaddr, FALSE);
1330#ifdef HAVE_IP_MREQN
1331 mreq4.imr_address.s_addr = htonl(INADDR_ANY);
1332 mreq4.imr_ifindex = 0;
1333#else
1334 mreq4.imr_interface.s_addr = htonl(INADDR_ANY);
1335#endif
1336
1337 if (setsockopt(socklan, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1338 (const char*)&mreq4, sizeof(mreq4)) < 0) {
1339 log_error("IP_ADD_MEMBERSHIP (%s) failed: %s",
1340 group, fc_strerror(fc_get_errno()));
1341 }
1342 } else {
1344
1345 log_error("Unsupported address family for broadcasting.");
1346 }
1347
1348 return 0;
1349}
1350
1351/*************************************************************************/
1356{
1357 int i;
1358
1359 game.all_connections = conn_list_new();
1360 game.est_connections = conn_list_new();
1361 game.glob_observers = conn_list_new();
1362
1363 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
1364 struct connection *pconn = &connections[i];
1365
1366 pconn->used = FALSE;
1367 pconn->self = conn_list_new();
1368 conn_list_prepend(pconn->self, pconn);
1369 }
1370#if defined(__VMS)
1371 {
1372 unsigned long status;
1373
1374 $DESCRIPTOR (tt_desc, "SYS$INPUT");
1375 status = sys$assign(&tt_desc, &tt_chan, 0, 0);
1376 if (!$VMS_STATUS_SUCCESS(status)) {
1377 lib$stop(status);
1378 }
1379 }
1380#endif /* VMS */
1381}
1382
1383/*************************************************************************/
1386static void start_processing_request(struct connection *pconn,
1387 int request_id)
1388{
1389 fc_assert_ret(request_id);
1391 log_debug("start processing packet %d from connection %d",
1392 request_id, pconn->id);
1395 pconn->server.currently_processed_request_id = request_id;
1396}
1397
1398/*************************************************************************/
1401static void finish_processing_request(struct connection *pconn)
1402{
1403 if (!pconn || !pconn->used) {
1404 return;
1405 }
1407 log_debug("finish processing packet %d from connection %d",
1411 conn_compression_thaw(pconn);
1412}
1413
1414/*************************************************************************/
1417static void connection_ping(struct connection *pconn)
1418{
1420
1421 log_debug("sending ping to %s (open=%d)", conn_description(pconn),
1422 timer_list_size(pconn->server.ping_timers));
1424 timer_list_append(pconn->server.ping_timers, timer);
1425 send_packet_conn_ping(pconn);
1426}
1427
1428/*************************************************************************/
1431void handle_conn_pong(struct connection *pconn)
1432{
1433 struct timer *timer;
1434
1435 if (timer_list_size(pconn->server.ping_timers) == 0) {
1436 log_error("got unexpected pong from %s", conn_description(pconn));
1437 return;
1438 }
1439
1440 timer = timer_list_front(pconn->server.ping_timers);
1442 timer_list_pop_front(pconn->server.ping_timers);
1443 log_debug("got pong from %s (open=%d); ping time = %fs",
1444 conn_description(pconn),
1445 timer_list_size(pconn->server.ping_timers), pconn->ping_time);
1446}
1447
1448/*************************************************************************/
1452{
1453 log_debug("Received heartbeat");
1454}
1455
1456/*************************************************************************/
1459static void send_ping_times_to_all(void)
1460{
1461 struct packet_conn_ping_info packet;
1462 int i;
1463
1464 i = 0;
1466 if (!pconn->used) {
1467 continue;
1468 }
1469 fc_assert(i < ARRAY_SIZE(packet.conn_id));
1470 packet.conn_id[i] = pconn->id;
1471 packet.ping_time[i] = pconn->ping_time;
1472 i++;
1474 packet.connections = i;
1475
1477}
1478
1479/*************************************************************************/
1484{
1485 fd_set readfs, exceptfs;
1486 fc_timeval tv;
1487 char msgbuf[128];
1488 struct data_in din;
1489 int type;
1490
1491 if (srvarg.announce == ANNOUNCE_NONE) {
1492 return;
1493 }
1494
1495 FD_ZERO(&readfs);
1496 FD_ZERO(&exceptfs);
1497 FD_SET(socklan, &exceptfs);
1498 FD_SET(socklan, &readfs);
1499
1500 tv.tv_sec = 0;
1501 tv.tv_usec = 0;
1502
1503 while (fc_select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) {
1504 if (errno != EINTR) {
1505 log_error("select failed: %s", fc_strerror(fc_get_errno()));
1506 return;
1507 }
1508 /* EINTR can happen sometimes, especially when compiling with -pg.
1509 * Generally we just want to run select again. */
1510 }
1511
1512 /* We would need a raw network connection for broadcast messages */
1513 if (FD_ISSET(socklan, &readfs)) {
1514 if (0 < recvfrom(socklan, msgbuf, sizeof(msgbuf), 0, NULL, NULL)) {
1515 dio_input_init(&din, msgbuf, 1);
1516 dio_get_uint8_raw(&din, &type);
1517 if (type == SERVER_LAN_VERSION) {
1518 log_debug("Received request for server LAN announcement.");
1520 } else {
1521 log_debug("Received invalid request for server LAN announcement.");
1522 }
1523 }
1524 }
1525}
1526
1527/*************************************************************************/
1531/* We would need a raw network connection for broadcast messages */
1533{
1534#ifndef FREECIV_HAVE_WINSOCK
1535 unsigned char buffer[MAX_LEN_PACKET];
1536#else /* FREECIV_HAVE_WINSOCK */
1537 char buffer[MAX_LEN_PACKET];
1538#endif /* FREECIV_HAVE_WINSOCK */
1539 char hostname[512];
1540 char port[256];
1541 char version[256];
1542 char players[256];
1543 int nhumans;
1544 char humans[256];
1545 char status[256];
1546 struct raw_data_out dout;
1547 union fc_sockaddr addr;
1548 int socksend, setting = 1;
1549 const char *group;
1550 size_t size;
1551#ifndef FREECIV_HAVE_WINSOCK
1552 unsigned char ttl;
1553#endif
1555
1556 /* Create a socket to broadcast to client. */
1557 if ((socksend = socket(addr_fam, SOCK_DGRAM, 0)) < 0) {
1558 log_error("Lan response socket failed: %s", fc_strerror(fc_get_errno()));
1559 return;
1560 }
1561
1562 /* Set the UDP Multicast group IP address of the packet. */
1564 memset(&addr, 0, sizeof(addr));
1565#ifdef FREECIV_IPV6_SUPPORT
1566 if (addr_fam == AF_INET6) {
1567 addr.saddr_in6.sin6_family = AF_INET6;
1568 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT + 1);
1569 inet_pton(addr_fam, group, &addr.saddr_in6.sin6_addr);
1570 } else
1571#endif /* FREECIV_IPV6_SUPPORT */
1572 {
1573 addr.saddr_in4.sin_family = AF_INET;
1574 addr.saddr_in4.sin_addr.s_addr = inet_addr(group);
1575 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT + 1);
1576 }
1577
1578 /* This setsockopt call fails on Windows 98, so we stick with the default
1579 * value of 1 on Windows, which should be fine in most cases */
1580#ifndef FREECIV_HAVE_WINSOCK
1581 {
1582 int proto;
1583
1584#ifdef FREECIV_IPV6_SUPPORT
1585 if (addr_fam == AF_INET6) {
1586 proto = IPPROTO_IPV6;
1587 } else
1588#endif /* FREECIV_IPV6_SUPPORT */
1589 {
1590 proto = IPPROTO_IP;
1591 }
1592
1593 /* Set the Time-to-Live field for the packet. */
1594 ttl = SERVER_LAN_TTL;
1595 if (setsockopt(socksend, proto, IP_MULTICAST_TTL,
1596 (const char*)&ttl, sizeof(ttl))) {
1597 log_error("setsockopt failed: %s", fc_strerror(fc_get_errno()));
1598 return;
1599 }
1600 }
1601#endif /* FREECIV_HAVE_WINSOCK */
1602
1603 if (setsockopt(socksend, SOL_SOCKET, SO_BROADCAST,
1604 (const char*)&setting, sizeof(setting))) {
1605 log_error("Lan response setsockopt failed: %s", fc_strerror(fc_get_errno()));
1606 return;
1607 }
1608
1609 /* Create a description of server state to send to clients. */
1610 if (srvarg.identity_name[0] != '\0') {
1611 sz_strlcpy(hostname, srvarg.identity_name);
1612 } else if (fc_gethostname(hostname, sizeof(hostname)) != 0) {
1613 sz_strlcpy(hostname, "none");
1614 }
1615
1616 fc_snprintf(version, sizeof(version), "%d.%d.%d%s",
1617 MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION, VERSION_LABEL);
1618
1619 switch (server_state()) {
1620 case S_S_INITIAL:
1621 /* TRANS: Game state for local server */
1622 fc_snprintf(status, sizeof(status), _("Pregame"));
1623 break;
1624 case S_S_RUNNING:
1625 /* TRANS: Game state for local server */
1626 fc_snprintf(status, sizeof(status), _("Running"));
1627 break;
1628 case S_S_OVER:
1629 /* TRANS: Game state for local server */
1630 fc_snprintf(status, sizeof(status), _("Game over"));
1631 break;
1632 }
1633
1634 fc_snprintf(players, sizeof(players), "%d",
1636
1637 nhumans = 0;
1638 players_iterate(pplayer) {
1639 if (pplayer->is_alive && is_human(pplayer)) {
1640 nhumans++;
1641 }
1643 fc_snprintf(humans, sizeof(humans), "%d", nhumans);
1644
1645 fc_snprintf(port, sizeof(port), "%d",
1646 srvarg.port);
1647
1648 dio_output_init(&dout, buffer, sizeof(buffer));
1650 dio_put_string_raw(&dout, hostname);
1651 dio_put_string_raw(&dout, port);
1652 dio_put_string_raw(&dout, version);
1653 dio_put_string_raw(&dout, status);
1654 dio_put_string_raw(&dout, players);
1655 dio_put_string_raw(&dout, humans);
1657 size = dio_output_used(&dout);
1658
1659 /* Sending packet to client with the information gathered above. */
1660 if (sendto(socksend, buffer, size, 0, &addr.saddr,
1661 sockaddr_size(&addr)) < 0) {
1662 log_error("landserver response sendto failed: %s",
1664 return;
1665 }
1666
1667 fc_closesocket(socksend);
1668}
void call_ai_refresh(void)
Definition aiiface.c:252
void auth_process_status(struct connection *pconn)
Definition auth.c:207
static struct ai_type * self
Definition classicai.c:46
static struct fc_sockaddr_list * list
Definition clinet.c:102
static int name_count
Definition clinet.c:103
void lost_connection_to_client(struct connection *pconn)
void connection_close_server(struct connection *pconn, const char *reason)
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:760
struct connection * conn_by_user(const char *user_name)
Definition connection.c:376
void connections_set_close_callback(conn_close_fn_t func)
Definition connection.c:80
void flush_connection_send_buffer_all(struct connection *pc)
Definition connection.c:229
int get_next_request_id(int old_request_id)
Definition connection.c:529
void connection_do_buffer(struct connection *pc)
Definition connection.c:323
void conn_pattern_destroy(struct conn_pattern *ppattern)
Definition connection.c:806
void connection_common_init(struct connection *pconn)
Definition connection.c:602
const char * conn_description(const struct connection *pconn)
Definition connection.c:473
void connection_common_close(struct connection *pconn)
Definition connection.c:627
void conn_compression_freeze(struct connection *pconn)
Definition connection.c:691
struct connection * conn_by_number(int id)
Definition connection.c:420
int read_socket_data(int sock, struct socket_packet_buffer *buffer)
Definition connection.c:129
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:335
@ AS_NOT_ESTABLISHED
Definition connection.h:98
@ AS_ESTABLISHED
Definition connection.h:102
bool conn_compression_thaw(struct connection *pconn)
Definition packets.c:194
#define MAX_LEN_PACKET
Definition connection.h:56
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
#define conn_list_iterate_end
Definition connection.h:115
void con_prompt_enter_clear(void)
Definition console.c:314
void con_prompt_init(void)
Definition console.c:272
void con_prompt_enter(void)
Definition console.c:303
void con_prompt_off(void)
Definition console.c:295
void con_prompt_on(void)
Definition console.c:286
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Definition dataio_raw.c:171
void dio_put_uint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:265
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:572
void dio_put_string_raw(struct raw_data_out *dout, const char *value)
Definition dataio_raw.c:499
size_t dio_output_used(struct raw_data_out *dout)
Definition dataio_raw.c:184
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Definition dataio_raw.c:202
#define MAX_NUM_CONNECTIONS
Definition fc_types.h:38
#define MAX_LEN_NAME
Definition fc_types.h:66
char * local_to_internal_string_malloc(const char *text)
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct civ_game game
Definition game.c:57
int current_turn_timeout(void)
Definition game.c:828
@ AS_QUITIDLE
Definition game.h:62
@ AS_TIMER
Definition game.h:64
GType type
Definition repodlgs.c:1312
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_fatal(message,...)
Definition log.h:100
#define log_debug(message,...)
Definition log.h:115
#define log_normal(message,...)
Definition log.h:107
@ LOG_DEBUG
Definition log.h:34
@ LOG_NORMAL
Definition log.h:32
#define log_error(message,...)
Definition log.h:103
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
void set_meta_message_string(const char *string)
Definition meta.c:179
void server_close_meta(void)
Definition meta.c:454
const char * get_meta_message_string(void)
Definition meta.c:114
bool send_server_info_to_metaserver(enum meta_flag flag)
Definition meta.c:490
@ META_GOODBYE
Definition meta.h:28
@ META_INFO
Definition meta.h:26
@ META_REFRESH
Definition meta.h:27
void fc_shutdown_network(void)
Definition netintf.c:217
@ ANNOUNCE_IPV6
Definition net_types.h:56
@ ANNOUNCE_NONE
Definition net_types.h:54
int addr_family_for_announce_type(enum announce_type announce)
Definition netintf.c:692
@ FC_ADDR_ANY
Definition net_types.h:64
bool fc_inet_aton(const char *cp, struct in_addr *inp, bool addr_none_ok)
Definition netintf.c:466
struct fc_sockaddr_list * net_lookup_service(const char *name, int port, enum fc_addr_family family)
Definition netintf.c:411
void fc_closesocket(int sock)
Definition netintf.c:186
void sockaddr_debug(union fc_sockaddr *addr, enum log_level lvl)
Definition netintf.c:269
int sockaddr_size(union fc_sockaddr *addr)
Definition netintf.c:305
void fc_nonblock(int sockfd)
Definition netintf.c:227
int fc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fc_timeval *timeout)
Definition netintf.c:125
struct timeval fc_timeval
Definition netintf.h:90
#define fc_sockaddr_list_iterate_end
Definition netintf.h:85
#define FC_FD_ZERO(p)
Definition netintf.h:57
int socklen_t
Definition netintf.h:67
#define fc_sockaddr_list_iterate(sockaddrlist, paddr)
Definition netintf.h:83
#define FC_IPV6_ADD_MEMBERSHIP
Definition netintf.h:63
void packets_deinit(void)
Definition packets.c:900
#define get_packet_from_connection(pc, ptype)
Definition packets.h:113
int send_packet_conn_ping(struct connection *pc)
int send_packet_processing_finished(struct connection *pc)
int send_packet_processing_started(struct connection *pc)
void lsend_packet_conn_ping_info(struct conn_list *dest, const struct packet_conn_ping_info *packet)
void lsend_packet_server_shutdown(struct conn_list *dest)
packet_type
int len
Definition packhand.c:125
struct player * player_by_name(const char *name)
Definition player.c:872
struct player * player_by_user(const char *name)
Definition player.c:931
#define players_iterate_end
Definition player.h:535
#define players_iterate(_pplayer)
Definition player.h:530
#define is_human(plr)
Definition player.h:233
int normal_player_count(void)
Definition plrhand.c:3034
void script_server_signal_emit(const char *signal_name,...)
static void cut_lagging_connection(struct connection *pconn)
Definition sernet.c:354
static void connection_ping(struct connection *pconn)
Definition sernet.c:1417
static void server_conn_close_callback(struct connection *pconn)
Definition sernet.c:344
static void send_lanserver_response(void)
Definition sernet.c:1532
static struct connection connections[MAX_NUM_CONNECTIONS]
Definition sernet.c:94
int server_open_socket(void)
Definition sernet.c:1127
void flush_packets(void)
Definition sernet.c:379
void init_connections(void)
Definition sernet.c:1355
static void really_close_connections(void)
Definition sernet.c:307
int server_make_connection(int new_sock, const char *client_addr, const char *client_ip)
Definition sernet.c:1067
void handle_conn_pong(struct connection *pconn)
Definition sernet.c:1431
static int socklan
Definition sernet.c:102
static int * listen_socks
Definition sernet.c:100
static char * current_internal
Definition sernet.c:157
static int listen_count
Definition sernet.c:101
static bool get_packet(struct connection *pconn, struct packet_to_handle *ppacket)
Definition sernet.c:454
static void send_ping_times_to_all(void)
Definition sernet.c:1459
enum server_events server_sniff_all_input(void)
Definition sernet.c:524
static void close_connection(struct connection *pconn)
Definition sernet.c:228
void handle_client_heartbeat(struct connection *pconn)
Definition sernet.c:1451
void readline_atexit(void)
Definition sernet.c:209
void close_connections_and_socket(void)
Definition sernet.c:259
static void finish_processing_request(struct connection *pconn)
Definition sernet.c:1401
static void start_processing_request(struct connection *pconn, int request_id)
Definition sernet.c:1386
static void handle_stdin_close(void)
Definition sernet.c:144
static const char * makeup_connection_name(int *id)
Definition sernet.c:955
static int server_accept_connection(int sockfd)
Definition sernet.c:982
static void get_lanserver_announcement(void)
Definition sernet.c:1483
static bool no_input
Definition sernet.c:135
static void incoming_client_packets(struct connection *pconn)
Definition sernet.c:467
#define SERVER_LAN_TTL
Definition sernet.h:25
server_events
Definition sernet.h:28
@ S_E_OTHERWISE
Definition sernet.h:30
@ S_E_END_OF_TURN_TIMEOUT
Definition sernet.h:29
@ S_E_FORCE_END_OF_SNIFF
Definition sernet.h:31
#define BUF_SIZE
Definition sernet.h:22
#define SERVER_LAN_VERSION
Definition sernet.h:26
#define SERVER_LAN_PORT
Definition sernet.h:24
bool make_dir(const char *pathname)
Definition shared.c:1772
char * get_multicast_group(bool ipv6_preferred)
Definition shared.c:1665
char * freeciv_storage_dir(void)
Definition shared.c:672
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
size_t size
Definition specvec.h:72
bool force_end_of_sniff
Definition srv_main.c:185
void save_game_auto(const char *save_reason, enum autosave_type type)
Definition srv_main.c:1732
void set_server_state(enum server_states newstate)
Definition srv_main.c:331
struct server_arguments srvarg
Definition srv_main.c:173
bool server_packet_input(struct connection *pconn, void *packet, int type)
Definition srv_main.c:1983
void server_quit(void)
Definition srv_main.c:1810
enum server_states server_state(void)
Definition srv_main.c:323
enum cmdlevel access_level_for_next_connection(void)
Definition stdinhand.c:1435
bool handle_stdin_input_free(struct connection *caller, char *str)
Definition stdinhand.c:4370
int tcptimeout
Definition game.h:194
struct civ_game::@30::@34 server
struct conn_list * glob_observers
Definition game.h:98
int netwait
Definition game.h:167
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
unsigned autosaves
Definition game.h:184
struct timer * save_timer
Definition game.h:216
time_t last_ping
Definition game.h:209
int additional_phase_seconds
Definition game.h:211
int maxconnectionsperhost
Definition game.h:154
int pingtimeout
Definition game.h:172
struct timer * phase_timer
Definition game.h:210
int pingtime
Definition game.h:171
struct conn_list * all_connections
Definition game.h:96
struct packet_timeout_info tinfo
Definition game.h:91
int save_frequency
Definition game.h:183
int currently_processed_request_id
Definition connection.h:203
time_t auth_settime
Definition connection.h:218
struct player * playing
Definition connection.h:156
enum cmdlevel access_level
Definition connection.h:182
struct conn_list * self
Definition connection.h:168
struct timer_list * ping_timers
Definition connection.h:210
bool is_closing
Definition connection.h:236
bool observer
Definition connection.h:152
char username[MAX_LEN_NAME]
Definition connection.h:169
enum gui_type client_gui
Definition connection.h:184
struct connection::@57::@63 server
struct timer * last_write
Definition connection.h:160
enum auth_status status
Definition connection.h:222
char ipaddr[MAX_LEN_ADDR]
Definition connection.h:226
void(* incoming_packet_notify)(struct connection *pc, int packet_type, int size)
Definition connection.h:253
void(* outgoing_packet_notify)(struct connection *pc, int packet_type, int size, int request_id)
Definition connection.h:261
struct socket_packet_buffer * send_buffer
Definition connection.h:159
char capability[MAX_LEN_CAPSTR]
Definition connection.h:176
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition connection.h:186
char addr[MAX_LEN_ADDR]
Definition connection.h:170
double ping_time
Definition connection.h:166
struct socket_packet_buffer * buffer
Definition connection.h:158
int last_request_id_seen
Definition connection.h:206
struct conn_pattern_list * ignore_list
Definition connection.h:232
enum cmdlevel granted_access_level
Definition connection.h:229
float ping_time[MAX_NUM_CONNECTIONS]
int conn_id[MAX_NUM_CONNECTIONS]
enum packet_type type
Definition sernet.c:448
char * bind_addr
Definition srv_main.h:34
enum announce_type announce
Definition srv_main.h:60
char identity_name[256]
Definition srv_main.h:31
Definition timing.c:81
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
int fc_gethostname(char *buf, size_t len)
Definition support.c:1016
const char * fc_strerror(fc_errno err)
Definition support.c:610
fc_errno fc_get_errno(void)
Definition support.c:593
#define sz_strlcpy(dest, src)
Definition support.h:167
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int fc_errno
Definition support.h:115
struct timer * timer_new(enum timer_timetype type, enum timer_use use)
Definition timing.c:157
void timer_destroy(struct timer *t)
Definition timing.c:191
void timer_start(struct timer *t)
Definition timing.c:224
double timer_read_seconds(struct timer *t)
Definition timing.c:344
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use)
Definition timing.c:176
@ TIMER_ACTIVE
Definition timing.h:45
@ TIMER_USER
Definition timing.h:41
struct sockaddr saddr
Definition netintf.h:71
struct sockaddr_in saddr_in4
Definition netintf.h:72
void send_updated_vote_totals(struct conn_list *dest)
Definition voting.c:866