Freeciv-3.3
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
96static int *listen_socks;
97static int listen_count;
98static int socklan;
99
100#if defined(__VMS)
101# if defined(_VAX_)
102# define lib$stop LIB$STOP
103# define sys$qiow SYS$QIOW
104# define sys$assign SYS$ASSIGN
105# endif
106# include <descrip.h>
107# include <iodef.h>
108# include <stsdef.h>
109# include <starlet.h>
110# include <lib$routines.h>
111# include <efndef.h>
112 static unsigned long int tt_chan;
113 static char input_char = 0;
114 static char got_input = 0;
116#endif
117
118#define PROCESSING_TIME_STATISTICS 0
119
120static int server_accept_connection(int sockfd);
121static void start_processing_request(struct connection *pconn,
122 int request_id);
123static void finish_processing_request(struct connection *pconn);
124static void connection_ping(struct connection *pconn);
125static void send_ping_times_to_all(void);
126
127static void get_lanserver_announcement(void);
128static void send_lanserver_response(void);
129
130static bool no_input = FALSE;
131
132/* Avoid compiler warning about defined, but unused function
133 * by defining it only when needed */
134#if defined(FREECIV_HAVE_LIBREADLINE) || \
135 (!defined(FREECIV_SOCKET_ZERO_NOT_STDIN) && !defined(FREECIV_HAVE_LIBREADLINE))
136/*************************************************************************/
139static void handle_stdin_close(void)
140{
141 /* Note this function may be called even if FREECIV_SOCKET_ZERO_NOT_STDIN, so
142 * the preprocessor check has to come inside the function body. But
143 * perhaps we want to do this even when FREECIV_SOCKET_ZERO_NOT_STDIN? */
144#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
145 log_normal(_("Server cannot read standard input. Ignoring input."));
146 no_input = TRUE;
147#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
148}
149
150#endif /* FREECIV_HAVE_LIBREADLINE || (!FREECIV_SOCKET_ZERO_NOT_STDIN && !FREECIV_HAVE_LIBREADLINE) */
151
152static char *current_internal = NULL;
153
154#ifdef FREECIV_HAVE_LIBREADLINE
155/****************************************************************************/
156
157#define HISTORY_FILENAME "freeciv-server_history"
158#define HISTORY_LENGTH 100
159
160static char *history_file = NULL;
161static bool readline_handled_input = FALSE;
162static bool readline_initialized = FALSE;
163
164/*************************************************************************/
167static void handle_readline_input_callback(char *line)
168{
169 if (no_input) {
170 return;
171 }
172
173 if (!line) {
174 handle_stdin_close(); /* maybe print an 'are you sure?' message? */
175 return;
176 }
177
178 if (line[0] != '\0') {
180 }
181
182 con_prompt_enter(); /* just got an 'Enter' hit */
184 free(line); /* This is already freed if we exit() with /quit command */
187
189}
190#endif /* FREECIV_HAVE_LIBREADLINE */
191
192/*************************************************************************/
205{
206#ifdef FREECIV_HAVE_LIBREADLINE
210 }
211#endif /* FREECIV_HAVE_LIBREADLINE */
212
213 if (current_internal != NULL) {
216 }
217}
218
219/*************************************************************************/
224{
225 if (!pconn) {
226 return;
227 }
228
229 if (pconn->server.ping_timers != NULL) {
230 timer_list_destroy(pconn->server.ping_timers);
231 pconn->server.ping_timers = NULL;
232 }
233
234 conn_pattern_list_destroy(pconn->server.ignore_list);
235 pconn->server.ignore_list = NULL;
236
237 /* safe to do these even if not in lists: */
242
243 pconn->playing = NULL;
244 pconn->client_gui = GUI_STUB;
245 pconn->access_level = ALLOW_NONE;
247
249}
250
251/*************************************************************************/
256{
257 int i;
258
260
261 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
262 if (connections[i].used) {
264 }
266 }
267
268 /* Remove the game connection lists and make sure they are empty. */
273
274 for (i = 0; i < listen_count; i++) {
276 }
278
281 }
282
283#ifdef FREECIV_HAVE_LIBREADLINE
284 if (history_file) {
290 }
291#endif /* FREECIV_HAVE_LIBREADLINE */
292
295
298}
299
300/*************************************************************************/
305{
306 struct connection *closing[MAX_NUM_CONNECTIONS];
307 struct connection *pconn;
308 int i, num;
309
310 do {
311 num = 0;
312
313 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
314 pconn = connections + i;
315 if (pconn->used && pconn->server.is_closing) {
316 closing[num++] = pconn;
317 /* Remove closing connections from the lists (hard detach)
318 * to avoid sending to closing connections. */
323 if (NULL != conn_get_player(pconn)) {
325 }
326 }
327 }
328
329 for (i = 0; i < num; i++) {
330 /* Now really close them. */
331 pconn = closing[i];
334 }
335 } while (0 < num); /* May some errors occurred, let's check. */
336}
337
338/*************************************************************************/
343{
344 /* Do as little as possible here to avoid recursive evil. */
345 pconn->server.is_closing = TRUE;
346}
347
348/*************************************************************************/
352{
353 if (!pconn->server.is_closing
354 && game.server.tcptimeout != 0
355 && pconn->last_write
357 && pconn->access_level != ALLOW_HACK
358 && timer_read_seconds(pconn->last_write) > game.server.tcptimeout) {
359 /* Cut the connections to players who lag too much. This
360 * usually happens because client animation slows the client
361 * too much and it can't keep up with the server. We don't
362 * cut HACK connections, or cut in single-player games, since
363 * it wouldn't help the game progress. For other connections
364 * the best thing to do when they lag too much is to be
365 * disconnected and reconnect. */
366 log_verbose("connection (%s) cut due to lagging player",
368 connection_close_server(pconn, _("lagging connection"));
369 }
370}
371
372/*************************************************************************/
377{
378 int i;
379 int max_desc;
382 time_t start;
383
384 (void) time(&start);
385
386 for (;;) {
387 /* Can't assign to tv.tv_sec directly on systems where it's unsigned */
388 signed signsecs = (game.server.netwait - (time(NULL) - start));
389
390 if (signsecs < 0) {
391 return;
392 }
393
394 tv.tv_usec = 0;
395 tv.tv_sec = signsecs;
396
399 max_desc = -1;
400
401 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
402 struct connection *pconn = &connections[i];
403
404 if (pconn->used
405 && !pconn->server.is_closing
406 && 0 < pconn->send_buffer->ndata) {
407 FD_SET(pconn->sock, &writefs);
408 FD_SET(pconn->sock, &exceptfs);
409 max_desc = MAX(pconn->sock, max_desc);
410 }
411 }
412
413 if (max_desc == -1) {
414 return;
415 }
416
417 if (fc_select(max_desc + 1, NULL, &writefs, &exceptfs, &tv) <= 0) {
418 return;
419 }
420
421 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) { /* check for freaky players */
422 struct connection *pconn = &connections[i];
423
424 if (pconn->used && !pconn->server.is_closing) {
425 if (FD_ISSET(pconn->sock, &exceptfs)) {
426 log_verbose("connection (%s) cut due to exception data",
428 connection_close_server(pconn, _("network exception"));
429 } else {
430 if (pconn->send_buffer && pconn->send_buffer->ndata > 0) {
431 if (FD_ISSET(pconn->sock, &writefs)) {
433 } else {
435 }
436 }
437 }
438 }
439 }
440 }
441}
442
444 void *data;
446};
447
448/*************************************************************************/
451static bool get_packet(struct connection *pconn,
453{
455
456 return NULL != ppacket->data;
457}
458
459/*************************************************************************/
465{
466 struct packet_to_handle packet;
467#if PROCESSING_TIME_STATISTICS
468 struct timer *request_time = NULL;
469#endif
470
471 while (get_packet(pconn, &packet)) {
472 bool command_ok;
473
474#if PROCESSING_TIME_STATISTICS
475 int request_id;
476
478 request_time != NULL ? NULL : "request");
480#endif /* PROCESSING_TIME_STATISTICS */
481
482 pconn->server.last_request_id_seen
483 = get_next_request_id(pconn->server.last_request_id_seen);
484
485#if PROCESSING_TIME_STATISTICS
486 request_id = pconn->server.last_request_id_seen;
487#endif /* PROCESSING_TIME_STATISTICS */
488
490 start_processing_request(pconn, pconn->server.last_request_id_seen);
491
492 command_ok = server_packet_input(pconn, packet.data, packet.type);
493 packet_destroy(packet.data, packet.type);
494
497
498#if PROCESSING_TIME_STATISTICS
499 log_verbose("processed request %d in %gms", request_id,
501#endif /* PROCESSING_TIME_STATISTICS */
502
503 if (!command_ok) {
504 connection_close_server(pconn, _("rejected"));
505 }
506 }
507
508#if PROCESSING_TIME_STATISTICS
510#endif /* PROCESSING_TIME_STATISTICS */
511}
512
513/*************************************************************************/
523{
524 int i, s;
525 int max_desc;
526 bool excepting;
529#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
530 char *bufptr;
531#endif
532
534
535#ifdef FREECIV_HAVE_LIBREADLINE
536 {
539
540 if (storage_dir != NULL) {
541 int fcdl = strlen(storage_dir) + 1;
542 char *fc_dir = fc_malloc(fcdl);
543
544 if (fc_dir != nullptr) {
546
550 if (history_file != nullptr) {
552 strcat(history_file, "/");
556 }
557 }
558
560 }
561 }
562
564 rl_callback_handler_install((char *) "> ",
567
570 }
571 }
572#endif /* FREECIV_HAVE_LIBREADLINE */
573
574 while (TRUE) {
575 int selret;
576
577 con_prompt_on(); /* accepting new input */
578
579 if (force_end_of_sniff) {
583 }
584
586
587 /* end server if no players for 'srvarg.quitidle' seconds,
588 * but only if at least one player has previously connected. */
589 if (srvarg.quitidle != 0) {
590 static time_t last_noplayers;
591 static bool conns;
592
594 conns = TRUE;
595 }
597 if (last_noplayers != 0) {
598 if (time(NULL) > last_noplayers + srvarg.quitidle) {
599 save_game_auto("Lost all connections", AS_QUITIDLE);
600
601 if (srvarg.exit_on_end) {
602 log_normal(_("Shutting down for lack of players."));
603 set_meta_message_string("shutting down for lack of players");
604 } else {
605 log_normal(_("Restarting for lack of players."));
606 set_meta_message_string("restarting for lack of players");
607 }
609
612
613 if (srvarg.exit_on_end) {
614 /* No need for anything more; just quit. */
615 server_quit();
616 }
617
618 /* Do not restart before someone has connected and left again */
619 conns = FALSE;
620 }
621 } else {
622 last_noplayers = time(NULL);
623
624 if (srvarg.exit_on_end) {
625 log_normal(_("Shutting down in %d seconds for lack of players."),
627
628 set_meta_message_string(N_("shutting down soon for lack of players"));
629 } else {
630 log_normal(_("Restarting in %d seconds for lack of players."),
632
633 set_meta_message_string(N_("restarting soon for lack of players"));
634 }
636 }
637 } else {
638 last_noplayers = 0;
639 }
640 }
641
642 /* Pinging around for statistics */
643 if (time(NULL) > (game.server.last_ping + game.server.pingtime)) {
644 /* send data about the previous run */
646
648 if ((!pconn->server.is_closing
649 && 0 < timer_list_size(pconn->server.ping_timers)
651 (pconn->server.ping_timers))
653 || pconn->ping_time > game.server.pingtimeout) {
654 /* cut mute players, except for hack-level ones */
655 if (pconn->access_level == ALLOW_HACK) {
656 log_verbose("connection (%s) [hack-level] ping timeout ignored",
658 } else {
659 log_verbose("connection (%s) cut due to ping timeout",
661 connection_close_server(pconn, _("ping timeout"));
662 }
663 } else if (pconn->established) {
664 /* We don't send ping to connection not established, because
665 * we wouldn't be able to handle asynchronous ping/pong with
666 * different packet header size. */
668 }
670 game.server.last_ping = time(NULL);
671 }
672
673 /* if we've waited long enough after a failure, respond to the client */
676 && !pconn->server.is_closing
677 && pconn->server.status != AS_ESTABLISHED) {
679 }
681
682 /* Don't wait if timeout == -1 (i.e. on auto games) */
683 if (S_S_RUNNING == server_state() && game.info.timeout == -1) {
688 }
689
690 tv.tv_sec = 1;
691 tv.tv_usec = 0;
692
696
697 if (!no_input) {
698#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
700#else /* FREECIV_SOCKET_ZERO_NOT_STDIN */
701# if !defined(__VMS)
702 FD_SET(0, &readfs);
703# endif /* VMS */
704#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
705 }
706
707 max_desc = 0;
708 for (i = 0; i < listen_count; i++) {
712 }
713
714 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
715 struct connection *pconn = connections + i;
716
717 if (pconn->used && !pconn->server.is_closing) {
718 FD_SET(pconn->sock, &readfs);
719 if (0 < pconn->send_buffer->ndata) {
720 FD_SET(pconn->sock, &writefs);
721 }
722 FD_SET(pconn->sock, &exceptfs);
723 max_desc = MAX(pconn->sock, max_desc);
724 }
725 }
726 con_prompt_off(); /* output doesn't generate a new prompt */
727
729 if (selret == 0) {
730 /* timeout */
734 if (current_turn_timeout() > 0
741
743 }
744 if ((game.server.autosaves & (1 << AS_TIMER))
747 >= game.server.save_frequency * 60)) {
748 save_game_auto("Timer", AS_TIMER);
752 ? NULL : "save interval");
754 }
755
756 if (!no_input) {
757#if defined(__VMS)
758 {
759 struct {
760 short numchars;
761 char firstchar;
762 char reserved;
763 int reserved2;
764 } ttchar;
765 unsigned long status;
766
767 status = sys$qiow(EFN$C_ENF, tt_chan,
769 &ttchar, sizeof(ttchar), 0, 0, 0, 0);
770 if (!$VMS_STATUS_SUCCESS(status)) {
771 lib$stop(status);
772 }
773 if (ttchar.numchars) {
774 FD_SET(0, &readfs);
775 } else {
776 continue;
777 }
778 }
779#else /* !__VMS */
780#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
782 continue;
783#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
784#endif /* !__VMS */
785 }
786 } else if (selret < 0) {
787 log_error("fc_select() failed: %s", fc_strerror(fc_get_errno()));
788 }
789
791 for (i = 0; i < listen_count; i++) {
793 excepting = TRUE;
794 break;
795 }
796 }
797 if (excepting) { /* handle Ctrl-Z suspend/resume */
798 continue;
799 }
800 for (i = 0; i < listen_count; i++) {
801 s = listen_socks[i];
802 if (FD_ISSET(s, &readfs)) { /* new players connects */
803 log_verbose("got new connection");
804 if (-1 == server_accept_connection(s)) {
805 /* There will be a log_error() message from
806 * server_accept_connection() if something
807 * goes wrong, so no need to make another
808 * error-level message here. */
809 log_verbose("failed accepting connection");
810 }
811 }
812 }
813 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
814 /* check for freaky players */
815 struct connection *pconn = &connections[i];
816
817 if (pconn->used
818 && !pconn->server.is_closing
819 && FD_ISSET(pconn->sock, &exceptfs)) {
820 log_verbose("connection (%s) cut due to exception data",
822 connection_close_server(pconn, _("network exception"));
823 }
824 }
825#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
826 if (!no_input && (bufptr = fc_read_console())) {
828
829 con_prompt_enter(); /* Will need a new prompt, regardless */
832 }
833#else /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
834 if (!no_input && FD_ISSET(0, &readfs)) { /* input from server operator */
835#ifdef FREECIV_HAVE_LIBREADLINE
840 }
841 continue;
842#else /* !FREECIV_HAVE_LIBREADLINE */
844 char *buffer;
845
846#ifdef HAVE_GETLINE
847 size_t len = 0;
848
849 buffer = NULL; /* Must be NULL when calling getline() */
851 if (didget >= 1) {
852 buffer[--didget] = '\0'; /* Overwrite newline character */
853 log_debug("Got line: \"%s\" (" SIZE_T_PRINTF ", " SIZE_T_PRINTF ")", buffer,
854 didget, len);
855 }
856#else /* HAVE_GETLINE */
857 buffer = malloc(BUF_SIZE + 1);
858
859 didget = read(0, buffer, BUF_SIZE);
860 if (didget > 0) {
861 buffer[didget] = '\0';
862 } else {
863 didget = -1; /* Error or end-of-file: closing stdin... */
864 }
865#endif /* HAVE_GETLINE */
866 if (didget < 0) {
868 }
869
870 con_prompt_enter(); /* Will need a new prompt, regardless */
871
872 if (didget >= 0) {
876 }
877 free(buffer);
878#endif /* !FREECIV_HAVE_LIBREADLINE */
879 } else
880#endif /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
881
882 { /* Input from a player */
883 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
884 struct connection *pconn = connections + i;
885 int nb;
886
887 if (!pconn->used
888 || pconn->server.is_closing
889 || !FD_ISSET(pconn->sock, &readfs)) {
890 continue;
891 }
892
893 nb = read_socket_data(pconn->sock, pconn->buffer);
894 if (0 <= nb) {
895 /* We read packets; now handle them. */
897 } else if (-2 == nb) {
898 connection_close_server(pconn, _("client disconnected"));
899 } else {
900 /* Read failure; the connection is closed. */
901 connection_close_server(pconn, _("read error"));
902 }
903 }
904
905 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
906 struct connection *pconn = &connections[i];
907
908 if (pconn->used
909 && !pconn->server.is_closing
910 && pconn->send_buffer
911 && pconn->send_buffer->ndata > 0) {
912 if (FD_ISSET(pconn->sock, &writefs)) {
914 } else {
916 }
917 }
918 }
920 break;
921 }
922 }
924
927
928 if (current_turn_timeout() > 0
935 }
936 if ((game.server.autosaves & (1 << AS_TIMER))
939 >= game.server.save_frequency * 60)) {
940 save_game_auto("Timer", AS_TIMER);
944 ? NULL : "save interval");
946 }
947
948 return S_E_OTHERWISE;
949}
950
951/*************************************************************************/
959static const char *makeup_connection_name(int *id)
960{
961 static unsigned short i = 0;
962 static char name[MAX_LEN_NAME];
963
964 for (;;) {
965 if (i == (unsigned short) - 1) {
966 /* don't use 0 */
967 i++;
968 }
969 fc_snprintf(name, sizeof(name), "c%u", (unsigned int)++i);
970 if (NULL == player_by_name(name)
972 && NULL == conn_by_number(i)
973 && NULL == conn_by_user(name)) {
974 *id = i;
975 return name;
976 }
977 }
978}
979
980/*************************************************************************/
987{
988 /* This used to have size_t for some platforms. If this is necessary
989 * it should be done with a configure check not a platform check. */
991
992 int new_sock;
993 union fc_sockaddr fromend;
994 bool nameinfo = FALSE;
995#ifdef FREECIV_IPV6_SUPPORT
996 char host[NI_MAXHOST], service[NI_MAXSERV];
997 char dst[INET6_ADDRSTRLEN];
998#else /* IPv6 support */
999 struct hostent *from;
1000 const char *host = NULL;
1001 const char *dst;
1002#endif /* IPv6 support */
1003
1004 fromlen = sizeof(fromend);
1005
1006 if ((new_sock = accept(sockfd, &fromend.saddr, &fromlen)) == -1) {
1007 log_error("accept failed: %s", fc_strerror(fc_get_errno()));
1008 return -1;
1009 }
1010
1011#ifdef FREECIV_IPV6_SUPPORT
1012 if (fromend.saddr.sa_family == AF_INET6) {
1013 inet_ntop(AF_INET6, &fromend.saddr_in6.sin6_addr,
1014 dst, sizeof(dst));
1015 } else if (fromend.saddr.sa_family == AF_INET) {
1016 inet_ntop(AF_INET, &fromend.saddr_in4.sin_addr, dst, sizeof(dst));
1017 } else {
1019
1020 log_error("Unsupported address family in server_accept_connection()");
1021
1022 return -1;
1023 }
1024#else /* IPv6 support */
1025 dst = inet_ntoa(fromend.saddr_in4.sin_addr);
1026#endif /* IPv6 support */
1027
1029 int count = 0;
1030
1032 if (0 != strcmp(dst, pconn->server.ipaddr)) {
1033 continue;
1034 }
1035 if (++count >= game.server.maxconnectionsperhost) {
1036 log_verbose("Rejecting new connection from %s: maximum number of "
1037 "connections for this address exceeded (%d).",
1039
1040 /* Disconnect the accepted socket. */
1042
1043 return -1;
1044 }
1046 }
1047
1048#ifdef FREECIV_IPV6_SUPPORT
1049 nameinfo = (0 == getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
1051 && '\0' != host[0]);
1052#else /* IPv6 support */
1053 from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
1054 sizeof(fromend.saddr_in4.sin_addr), AF_INET);
1055 if (NULL != from && '\0' != from->h_name[0]) {
1056 host = from->h_name;
1057 nameinfo = TRUE;
1058 }
1059#endif /* IPv6 support */
1060
1062 (nameinfo ? host : dst), dst);
1063}
1064
1065/*************************************************************************/
1072 const char *client_ip)
1073{
1074 struct timer *timer;
1075 int i;
1076
1078
1079 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
1080 struct connection *pconn = &connections[i];
1081
1082 if (!pconn->used) {
1084 pconn->sock = new_sock;
1085 pconn->observer = FALSE;
1086 pconn->playing = NULL;
1087 pconn->capability[0] = '\0';
1088 pconn->access_level = access_level_for_next_connection();
1089 pconn->notify_of_writable_data = NULL;
1090 pconn->server.currently_processed_request_id = 0;
1091 pconn->server.last_request_id_seen = 0;
1092 pconn->server.auth_tries = 0;
1093 pconn->server.auth_settime = 0;
1094 pconn->server.status = AS_NOT_ESTABLISHED;
1095 pconn->server.ping_timers = timer_list_new_full(timer_destroy);
1096 pconn->server.granted_access_level = pconn->access_level;
1097 pconn->server.ignore_list =
1099 pconn->server.is_closing = FALSE;
1100 pconn->ping_time = -1.0;
1101 pconn->incoming_packet_notify = NULL;
1102 pconn->outgoing_packet_notify = NULL;
1103
1104 sz_strlcpy(pconn->username, makeup_connection_name(&pconn->id));
1106 sz_strlcpy(pconn->server.ipaddr, client_ip);
1107
1109
1110 log_verbose("connection (%s) from %s (%s)",
1111 pconn->username, pconn->addr, pconn->server.ipaddr);
1112 /* Give a ping timeout to send the PACKET_SERVER_JOIN_REQ, or close
1113 * the mute connection. This timer will be canceled into
1114 * connecthand.c:handle_login_request(). */
1115 timer = timer_new(TIMER_USER, TIMER_ACTIVE, "ping timer");
1117 timer_list_append(pconn->server.ping_timers, timer);
1118
1119 return 0;
1120 }
1121 }
1122
1123 log_error("maximum number of connections reached");
1125
1126 return -1;
1127}
1128
1129/*************************************************************************/
1134{
1135 /* setup socket address */
1136 union fc_sockaddr addr;
1137#ifdef HAVE_IP_MREQN
1138 struct ip_mreqn mreq4;
1139#else
1140 struct ip_mreq mreq4;
1141#endif
1142 const char *cause, *group;
1143 int j, on, s;
1144 int lan_family;
1145 struct fc_sockaddr_list *list;
1146 int name_count;
1147 fc_errno eno = 0;
1148 union fc_sockaddr *problematic = NULL;
1149
1150#ifdef FREECIV_IPV6_SUPPORT
1151 struct ipv6_mreq mreq6;
1152#endif
1153
1154 log_verbose("Server attempting to listen on %s:%d",
1155 srvarg.bind_addr ? srvarg.bind_addr : "(any)",
1156 srvarg.port);
1157
1158 /* Any supported family will do */
1160
1162
1163 /* Lookup addresses to bind. */
1164 if (name_count <= 0) {
1165 log_fatal(_("Server: bad address: <%s:%d>."),
1166 srvarg.bind_addr ? srvarg.bind_addr : "(none)", srvarg.port);
1168 }
1169
1170 cause = "internal"; /* If cause is not overwritten but gets printed... */
1171 on = 1;
1172
1173 /* Loop to create sockets, bind, listen. */
1175 listen_count = 0;
1176
1178 /* Create socket for client connections. */
1179 s = socket(paddr->saddr.sa_family, SOCK_STREAM, 0);
1180 if (s == -1) {
1181 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1182 * Kernel might have disabled AF_INET6. */
1183 eno = fc_get_errno();
1184 cause = "socket";
1186 continue;
1187 }
1188
1189#ifndef FREECIV_HAVE_WINSOCK
1190 /* SO_REUSEADDR considered harmful on Win, necessary otherwise */
1192 (char *)&on, sizeof(on)) == -1) {
1193 log_error("setsockopt SO_REUSEADDR failed: %s",
1196 }
1197#endif /* FREECIV_HAVE_WINSOCK */
1198
1199 /* AF_INET6 sockets should use IPv6 only,
1200 * without stealing IPv4 from AF_INET sockets. */
1201#ifdef FREECIV_IPV6_SUPPORT
1202 if (paddr->saddr.sa_family == AF_INET6) {
1203#ifdef IPV6_V6ONLY
1205 (char *)&on, sizeof(on)) == -1) {
1206 log_error("setsockopt IPV6_V6ONLY failed: %s",
1209 }
1210#endif /* IPV6_V6ONLY */
1211 }
1212#endif /* IPv6 support */
1213
1214 if (bind(s, &paddr->saddr, sockaddr_size(paddr)) == -1) {
1215 eno = fc_get_errno();
1216 cause = "bind";
1218
1219 if (eno == EADDRNOTAVAIL) {
1220 /* Close only this socket. This address is not available.
1221 * This can happen with the IPv6 wildcard address if this
1222 * machine has no IPv6 interfaces. */
1223 /* If you change this logic, be sure to make clientside checking
1224 * of acceptable port to match. */
1225 fc_closesocket(s);
1226 continue;
1227 } else {
1228 /* Close all sockets. Another program might have bound to
1229 * one of our addresses, and might hijack some of our
1230 * connections. */
1231 fc_closesocket(s);
1232 for (j = 0; j < listen_count; j++) {
1234 }
1235 listen_count = 0;
1236 break;
1237 }
1238 }
1239
1240 if (listen(s, MAX_NUM_CONNECTIONS) == -1) {
1241 eno = fc_get_errno();
1242 cause = "listen";
1244 fc_closesocket(s);
1245 continue;
1246 }
1247
1250
1251 if (listen_count == 0) {
1252 log_fatal("%s failure: %s (%d failed)", cause, fc_strerror(eno), name_count);
1253 if (problematic != NULL) {
1255 }
1257 /* Do not list already logged 'problematic' again */
1258 if (paddr != problematic) {
1260 }
1263 }
1264
1266
1268
1269 if (srvarg.announce == ANNOUNCE_NONE) {
1270 return 0;
1271 }
1272
1273#ifdef FREECIV_IPV6_SUPPORT
1274 if (srvarg.announce == ANNOUNCE_IPV6) {
1276 } else
1277#endif /* IPV6 support */
1278 {
1280 }
1281
1282 /* Create socket for server LAN announcements */
1283 if ((socklan = socket(lan_family, SOCK_DGRAM, 0)) < 0) {
1284 log_error("Announcement socket failed: %s", fc_strerror(fc_get_errno()));
1285 return 0; /* FIXME: Should this cause hard error as exit(EXIT_FAILURE).
1286 * It's a failure to do as commandline parameters requested
1287 * after all */
1288 }
1289
1291 (char *)&on, sizeof(on)) == -1) {
1292 log_error("SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1293 }
1294
1296
1298
1299 memset(&addr, 0, sizeof(addr));
1300
1301 addr.saddr.sa_family = lan_family;
1302
1303#ifdef FREECIV_IPV6_SUPPORT
1304 if (addr.saddr.sa_family == AF_INET6) {
1305 addr.saddr_in6.sin6_family = AF_INET6;
1306 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT);
1307 addr.saddr_in6.sin6_addr = in6addr_any;
1308 } else
1309#endif /* IPv6 support */
1310 if (addr.saddr.sa_family == AF_INET) {
1311 addr.saddr_in4.sin_family = AF_INET;
1312 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT);
1313 addr.saddr_in4.sin_addr.s_addr = htonl(INADDR_ANY);
1314 } else {
1316
1317 log_error("Unsupported address family in server_open_socket()");
1318 }
1319
1320 if (bind(socklan, &addr.saddr, sockaddr_size(&addr)) < 0) {
1321 log_error("Announcement socket binding failed: %s", fc_strerror(fc_get_errno()));
1322 }
1323
1324#ifdef FREECIV_IPV6_SUPPORT
1325 if (addr.saddr.sa_family == AF_INET6) {
1326 inet_pton(AF_INET6, group, &mreq6.ipv6mr_multiaddr.s6_addr);
1327 mreq6.ipv6mr_interface = 0; /* TODO: Interface selection */
1329 (const char*)&mreq6, sizeof(mreq6)) < 0) {
1330 log_error("FC_IPV6_ADD_MEMBERSHIP (%s) failed: %s",
1331 group, fc_strerror(fc_get_errno()));
1332 }
1333 } else
1334#endif /* IPV6 Support */
1335 if (addr.saddr.sa_family == AF_INET) {
1336 fc_inet_aton(group, &mreq4.imr_multiaddr, FALSE);
1337#ifdef HAVE_IP_MREQN
1338 mreq4.imr_address.s_addr = htonl(INADDR_ANY);
1339 mreq4.imr_ifindex = 0;
1340#else
1341 mreq4.imr_interface.s_addr = htonl(INADDR_ANY);
1342#endif
1343
1345 (const char*)&mreq4, sizeof(mreq4)) < 0) {
1346 log_error("IP_ADD_MEMBERSHIP (%s) failed: %s",
1347 group, fc_strerror(fc_get_errno()));
1348 }
1349 } else {
1351
1352 log_error("Unsupported address family for broadcasting.");
1353 }
1354
1355 return 0;
1356}
1357
1358/*************************************************************************/
1363{
1364 int i;
1365
1370
1371 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
1372 struct connection *pconn = &connections[i];
1373
1374 pconn->used = FALSE;
1375 pconn->self = conn_list_new();
1377 }
1378#if defined(__VMS)
1379 {
1380 unsigned long status;
1381
1382 $DESCRIPTOR (tt_desc, "SYS$INPUT");
1383 status = sys$assign(&tt_desc, &tt_chan, 0, 0);
1386 }
1387 }
1388#endif /* VMS */
1389}
1390
1391/*************************************************************************/
1395 int request_id)
1396{
1398 fc_assert_ret(pconn->server.currently_processed_request_id == 0);
1399 log_debug("start processing packet %d from connection %d",
1400 request_id, pconn->id);
1403 pconn->server.currently_processed_request_id = request_id;
1404}
1405
1406/*************************************************************************/
1410{
1411 if (!pconn || !pconn->used) {
1412 return;
1413 }
1414
1415 fc_assert_ret(pconn->server.currently_processed_request_id);
1416
1417 log_debug("finish processing packet %d from connection %d",
1418 pconn->server.currently_processed_request_id, pconn->id);
1420 pconn->server.currently_processed_request_id = 0;
1422}
1423
1424/*************************************************************************/
1428{
1429 struct timer *timer = timer_new(TIMER_USER, TIMER_ACTIVE, "connection ping");
1430
1431 log_debug("sending ping to %s (open=%d)", conn_description(pconn),
1432 timer_list_size(pconn->server.ping_timers));
1434 timer_list_append(pconn->server.ping_timers, timer);
1436}
1437
1438/*************************************************************************/
1442{
1443 struct timer *timer;
1444
1445 if (timer_list_size(pconn->server.ping_timers) == 0) {
1446 log_error("got unexpected pong from %s", conn_description(pconn));
1447 return;
1448 }
1449
1450 timer = timer_list_front(pconn->server.ping_timers);
1451 pconn->ping_time = timer_read_seconds(timer);
1452 timer_list_pop_front(pconn->server.ping_timers);
1453 log_debug("got pong from %s (open=%d); ping time = %fs",
1455 timer_list_size(pconn->server.ping_timers), pconn->ping_time);
1456}
1457
1458/*************************************************************************/
1462{
1463 log_debug("Received heartbeat");
1464}
1465
1466/*************************************************************************/
1469static void send_ping_times_to_all(void)
1470{
1471 struct packet_conn_ping_info packet;
1472 int i;
1473
1474 i = 0;
1476 if (!pconn->used) {
1477 continue;
1478 }
1479 fc_assert(i < ARRAY_SIZE(packet.conn_id));
1480 packet.conn_id[i] = pconn->id;
1481 packet.ping_time[i] = pconn->ping_time;
1482 i++;
1484 packet.connections = i;
1485
1487}
1488
1489/*************************************************************************/
1494{
1496 fc_timeval tv;
1497 char msgbuf[128];
1498 struct data_in din;
1499 int type;
1500
1501 if (srvarg.announce == ANNOUNCE_NONE) {
1502 return;
1503 }
1504
1505 FD_ZERO(&readfs);
1506 FD_ZERO(&exceptfs);
1509
1510 tv.tv_sec = 0;
1511 tv.tv_usec = 0;
1512
1513 while (fc_select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) {
1514 if (errno != EINTR) {
1515 log_error("select failed: %s", fc_strerror(fc_get_errno()));
1516 return;
1517 }
1518 /* EINTR can happen sometimes, especially when compiling with -pg.
1519 * Generally we just want to run select again. */
1520 }
1521
1522 /* We would need a raw network connection for broadcast messages */
1523 if (FD_ISSET(socklan, &readfs)) {
1524 if (0 < recvfrom(socklan, msgbuf, sizeof(msgbuf), 0, NULL, NULL)) {
1527 if (type == SERVER_LAN_VERSION) {
1528 log_debug("Received request for server LAN announcement.");
1530 } else {
1531 log_debug("Received invalid request for server LAN announcement.");
1532 }
1533 }
1534 }
1535}
1536
1537/*************************************************************************/
1541/* We would need a raw network connection for broadcast messages */
1543{
1544#ifndef FREECIV_HAVE_WINSOCK
1545 unsigned char buffer[MAX_LEN_PACKET];
1546#else /* FREECIV_HAVE_WINSOCK */
1547 char buffer[MAX_LEN_PACKET];
1548#endif /* FREECIV_HAVE_WINSOCK */
1549 char hostname[512];
1550 char port[256];
1551 char version[256];
1552 char players[256];
1553 int nhumans;
1554 char humans[256];
1555 char status[256];
1556 struct raw_data_out dout;
1557 union fc_sockaddr addr;
1558 int socksend, setting = 1;
1559 const char *group;
1560 size_t size;
1561#ifndef FREECIV_HAVE_WINSOCK
1562 unsigned char ttl;
1563#endif
1565
1566 /* Create a socket to broadcast to client. */
1567 if ((socksend = socket(addr_fam, SOCK_DGRAM, 0)) < 0) {
1568 log_error("Lan response socket failed: %s", fc_strerror(fc_get_errno()));
1569 return;
1570 }
1571
1572 /* Set the UDP Multicast group IP address of the packet. */
1574 memset(&addr, 0, sizeof(addr));
1575#ifdef FREECIV_IPV6_SUPPORT
1576 if (addr_fam == AF_INET6) {
1577 addr.saddr_in6.sin6_family = AF_INET6;
1578 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT + 1);
1579 inet_pton(addr_fam, group, &addr.saddr_in6.sin6_addr);
1580 } else
1581#endif /* FREECIV_IPV6_SUPPORT */
1582 {
1583 addr.saddr_in4.sin_family = AF_INET;
1584 addr.saddr_in4.sin_addr.s_addr = inet_addr(group);
1585 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT + 1);
1586 }
1587
1588 /* This setsockopt call fails on Windows 98, so we stick with the default
1589 * value of 1 on Windows, which should be fine in most cases */
1590#ifndef FREECIV_HAVE_WINSOCK
1591 {
1592 int proto;
1593
1594#ifdef FREECIV_IPV6_SUPPORT
1595 if (addr_fam == AF_INET6) {
1597 } else
1598#endif /* FREECIV_IPV6_SUPPORT */
1599 {
1600 proto = IPPROTO_IP;
1601 }
1602
1603 /* Set the Time-to-Live field for the packet. */
1606 (const char*)&ttl, sizeof(ttl))) {
1607 log_error("setsockopt failed: %s", fc_strerror(fc_get_errno()));
1608 return;
1609 }
1610 }
1611#endif /* FREECIV_HAVE_WINSOCK */
1612
1614 (const char*)&setting, sizeof(setting))) {
1615 log_error("Lan response setsockopt failed: %s", fc_strerror(fc_get_errno()));
1616 return;
1617 }
1618
1619 /* Create a description of server state to send to clients. */
1620 if (srvarg.identity_name[0] != '\0') {
1622 } else if (fc_gethostname(hostname, sizeof(hostname)) != 0) {
1623 sz_strlcpy(hostname, "none");
1624 }
1625
1626 fc_snprintf(version, sizeof(version), "%d.%d.%d%s",
1628
1629 switch (server_state()) {
1630 case S_S_INITIAL:
1631 /* TRANS: Game state for local server */
1632 fc_snprintf(status, sizeof(status), _("Pregame"));
1633 break;
1634 case S_S_RUNNING:
1635 /* TRANS: Game state for local server */
1636 fc_snprintf(status, sizeof(status), _("Running"));
1637 break;
1638 case S_S_OVER:
1639 /* TRANS: Game state for local server */
1640 fc_snprintf(status, sizeof(status), _("Game over"));
1641 break;
1642 }
1643
1644 fc_snprintf(players, sizeof(players), "%d",
1646
1647 nhumans = 0;
1648 players_iterate(pplayer) {
1649 if (pplayer->is_alive && is_human(pplayer)) {
1650 nhumans++;
1651 }
1653 fc_snprintf(humans, sizeof(humans), "%d", nhumans);
1654
1655 fc_snprintf(port, sizeof(port), "%d",
1656 srvarg.port);
1657
1658 dio_output_init(&dout, buffer, sizeof(buffer));
1661 dio_put_string_raw(&dout, port);
1662 dio_put_string_raw(&dout, version);
1663 dio_put_string_raw(&dout, status);
1664 dio_put_string_raw(&dout, players);
1665 dio_put_string_raw(&dout, humans);
1668
1669 /* Sending packet to client with the information gathered above. */
1670 if (sendto(socksend, buffer, size, 0, &addr.saddr,
1671 sockaddr_size(&addr)) < 0) {
1672 log_error("landserver response sendto failed: %s",
1674 return;
1675 }
1676
1678}
void call_ai_refresh(void)
Definition aiiface.c:254
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
char * incite_cost
Definition comments.c:76
#define MAX_LEN_PACKET
Definition conn_types.h:29
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:763
struct connection * conn_by_user(const char *user_name)
Definition connection.c:377
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:230
int get_next_request_id(int old_request_id)
Definition connection.c:530
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
void conn_pattern_destroy(struct conn_pattern *ppattern)
Definition connection.c:809
void connection_common_init(struct connection *pconn)
Definition connection.c:603
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
void connection_common_close(struct connection *pconn)
Definition connection.c:630
void conn_compression_freeze(struct connection *pconn)
Definition connection.c:694
struct connection * conn_by_number(int id)
Definition connection.c:421
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:336
@ AS_NOT_ESTABLISHED
Definition connection.h:93
@ AS_ESTABLISHED
Definition connection.h:97
bool conn_compression_thaw(struct connection *pconn)
Definition packets.c:194
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
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
int dio_put_uint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:265
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Definition dataio_raw.c:171
int dio_put_string_raw(struct raw_data_out *dout, const char *value)
Definition dataio_raw.c:512
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:598
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:61
int current_turn_timeout(void)
Definition game.c:853
@ AS_QUITIDLE
Definition game.h:62
@ AS_TIMER
Definition game.h:64
GType type
Definition repodlgs.c:1313
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define log_fatal(message,...)
Definition log.h:101
#define log_debug(message,...)
Definition log.h:116
#define log_normal(message,...)
Definition log.h:108
@ LOG_DEBUG
Definition log.h:35
@ LOG_NORMAL
Definition log.h:33
#define log_error(message,...)
Definition log.h:104
#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:180
void server_close_meta(void)
Definition meta.c:455
const char * get_meta_message_string(void)
Definition meta.c:115
bool send_server_info_to_metaserver(enum meta_flag flag)
Definition meta.c:491
@ 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:90
void packet_destroy(void *packet, enum packet_type type)
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:127
struct player * player_by_name(const char *name)
Definition player.c:881
struct player * player_by_user(const char *name)
Definition player.c:940
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define is_human(plr)
Definition player.h:231
int normal_player_count(void)
Definition plrhand.c:3209
void script_server_signal_emit(const char *signal_name,...)
static void cut_lagging_connection(struct connection *pconn)
Definition sernet.c:351
static void connection_ping(struct connection *pconn)
Definition sernet.c:1427
static void server_conn_close_callback(struct connection *pconn)
Definition sernet.c:342
static void send_lanserver_response(void)
Definition sernet.c:1542
static struct connection connections[MAX_NUM_CONNECTIONS]
Definition sernet.c:94
int server_open_socket(void)
Definition sernet.c:1133
void flush_packets(void)
Definition sernet.c:376
void init_connections(void)
Definition sernet.c:1362
static void really_close_connections(void)
Definition sernet.c:304
int server_make_connection(int new_sock, const char *client_addr, const char *client_ip)
Definition sernet.c:1071
void handle_conn_pong(struct connection *pconn)
Definition sernet.c:1441
static int socklan
Definition sernet.c:98
static int * listen_socks
Definition sernet.c:96
static char * current_internal
Definition sernet.c:152
static int listen_count
Definition sernet.c:97
static bool get_packet(struct connection *pconn, struct packet_to_handle *ppacket)
Definition sernet.c:451
static void send_ping_times_to_all(void)
Definition sernet.c:1469
enum server_events server_sniff_all_input(void)
Definition sernet.c:522
static void close_connection(struct connection *pconn)
Definition sernet.c:223
void handle_client_heartbeat(struct connection *pconn)
Definition sernet.c:1461
void readline_atexit(void)
Definition sernet.c:204
void close_connections_and_socket(void)
Definition sernet.c:255
static void finish_processing_request(struct connection *pconn)
Definition sernet.c:1409
static void start_processing_request(struct connection *pconn, int request_id)
Definition sernet.c:1394
static void handle_stdin_close(void)
Definition sernet.c:139
static const char * makeup_connection_name(int *id)
Definition sernet.c:959
static int server_accept_connection(int sockfd)
Definition sernet.c:986
static void get_lanserver_announcement(void)
Definition sernet.c:1493
static bool no_input
Definition sernet.c:130
static void incoming_client_packets(struct connection *pconn)
Definition sernet.c:464
#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, int mode)
Definition shared.c:1779
char * get_multicast_group(bool ipv6_preferred)
Definition shared.c:1667
char * freeciv_storage_dir(void)
Definition shared.c:671
#define ARRAY_SIZE(x)
Definition shared.h:85
#define DIRMODE_DEFAULT
Definition shared.h:258
#define MAX(x, y)
Definition shared.h:54
size_t size
Definition specvec.h:72
bool force_end_of_sniff
Definition srv_main.c:193
void save_game_auto(const char *save_reason, enum autosave_type type)
Definition srv_main.c:1837
void set_server_state(enum server_states newstate)
Definition srv_main.c:346
struct server_arguments srvarg
Definition srv_main.c:181
bool server_packet_input(struct connection *pconn, void *packet, int type)
Definition srv_main.c:2092
void fc__noreturn server_quit(void)
Definition srv_main.c:1915
enum server_states server_state(void)
Definition srv_main.c:338
enum cmdlevel access_level_for_next_connection(void)
Definition stdinhand.c:1437
bool handle_stdin_input_free(struct connection *caller, char *str)
Definition stdinhand.c:4437
int tcptimeout
Definition game.h:202
struct conn_list * glob_observers
Definition game.h:98
int netwait
Definition game.h:175
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
unsigned autosaves
Definition game.h:192
struct timer * save_timer
Definition game.h:224
time_t last_ping
Definition game.h:217
int additional_phase_seconds
Definition game.h:219
int maxconnectionsperhost
Definition game.h:162
int pingtimeout
Definition game.h:180
struct conn_list * web_client_connections
Definition game.h:99
struct timer * phase_timer
Definition game.h:218
int pingtime
Definition game.h:179
struct conn_list * all_connections
Definition game.h:96
struct civ_game::@32::@36 server
struct packet_timeout_info tinfo
Definition game.h:91
int save_frequency
Definition game.h:191
enum auth_status status
Definition connection.h:217
struct socket_packet_buffer * buffer
Definition connection.h:153
float ping_time[MAX_NUM_CONNECTIONS]
int conn_id[MAX_NUM_CONNECTIONS]
enum packet_type type
Definition sernet.c:445
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:960
int fc_gethostname(char *buf, size_t len)
Definition support.c:1007
const char * fc_strerror(fc_errno err)
Definition support.c:609
fc_errno fc_get_errno(void)
Definition support.c:592
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int fc_errno
Definition support.h:140
void timer_destroy(struct timer *t)
Definition timing.c:208
void timer_start(struct timer *t)
Definition timing.c:263
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:160
double timer_read_seconds(struct timer *t)
Definition timing.c:379
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use, const char *name)
Definition timing.c:180
@ TIMER_ACTIVE
Definition timing.h:46
@ TIMER_USER
Definition timing.h:42
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