Freeciv-3.2
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 */
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;
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) {
179 handle_stdin_close(); /* maybe print an 'are you sure?' message? */
180 return;
181 }
182
183 if (line[0] != '\0') {
185 }
186
187 con_prompt_enter(); /* just got an 'Enter' hit */
189 free(line); /* This is already freed if we exit() with /quit command */
192
194}
195#endif /* FREECIV_HAVE_LIBREADLINE */
196
197/*************************************************************************/
210{
211#ifdef FREECIV_HAVE_LIBREADLINE
215 }
216#endif /* FREECIV_HAVE_LIBREADLINE */
217
218 if (current_internal != NULL) {
221 }
222}
223
224/*************************************************************************/
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: */
247
248 pconn->playing = NULL;
249 pconn->client_gui = GUI_STUB;
250 pconn->access_level = ALLOW_NONE;
252
254}
255
256/*************************************************************************/
261{
262 int i;
263
265
266 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
267 if (connections[i].used) {
269 }
271 }
272
273 /* Remove the game connection lists and make sure they are empty. */
278
279 for (i = 0; i < listen_count; i++) {
281 }
283
286 }
287
288#ifdef FREECIV_HAVE_LIBREADLINE
289 if (history_file) {
295 }
296#endif /* FREECIV_HAVE_LIBREADLINE */
297
300
303}
304
305/*************************************************************************/
310{
311 struct connection *closing[MAX_NUM_CONNECTIONS];
312 struct connection *pconn;
313 int i, num;
314
315 do {
316 num = 0;
317
318 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
319 pconn = connections + i;
320 if (pconn->used && pconn->server.is_closing) {
321 closing[num++] = pconn;
322 /* Remove closing connections from the lists (hard detach)
323 * to avoid sending to closing connections. */
328 if (NULL != conn_get_player(pconn)) {
330 }
331 }
332 }
333
334 for (i = 0; i < num; i++) {
335 /* Now really close them. */
336 pconn = closing[i];
339 }
340 } while (0 < num); /* May some errors occurred, let's check. */
341}
342
343/*************************************************************************/
348{
349 /* Do as little as possible here to avoid recursive evil. */
350 pconn->server.is_closing = TRUE;
351}
352
353/*************************************************************************/
357{
358 if (!pconn->server.is_closing
359 && game.server.tcptimeout != 0
360 && pconn->last_write
362 && pconn->access_level != ALLOW_HACK
363 && timer_read_seconds(pconn->last_write) > game.server.tcptimeout) {
364 /* Cut the connections to players who lag too much. This
365 * usually happens because client animation slows the client
366 * too much and it can't keep up with the server. We don't
367 * cut HACK connections, or cut in single-player games, since
368 * it wouldn't help the game progress. For other connections
369 * the best thing to do when they lag too much is to be
370 * disconnected and reconnect. */
371 log_verbose("connection (%s) cut due to lagging player",
373 connection_close_server(pconn, _("lagging connection"));
374 }
375}
376
377/*************************************************************************/
382{
383 int i;
384 int max_desc;
387 time_t start;
388
389 (void) time(&start);
390
391 for (;;) {
392 /* Can't assign to tv.tv_sec directly on systems where it's unsigned */
393 signed signsecs = (game.server.netwait - (time(NULL) - start));
394
395 if (signsecs < 0) {
396 return;
397 }
398
399 tv.tv_usec = 0;
400 tv.tv_sec = signsecs;
401
404 max_desc = -1;
405
406 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
407 struct connection *pconn = &connections[i];
408
409 if (pconn->used
410 && !pconn->server.is_closing
411 && 0 < pconn->send_buffer->ndata) {
412 FD_SET(pconn->sock, &writefs);
413 FD_SET(pconn->sock, &exceptfs);
414 max_desc = MAX(pconn->sock, max_desc);
415 }
416 }
417
418 if (max_desc == -1) {
419 return;
420 }
421
422 if (fc_select(max_desc + 1, NULL, &writefs, &exceptfs, &tv) <= 0) {
423 return;
424 }
425
426 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) { /* check for freaky players */
427 struct connection *pconn = &connections[i];
428
429 if (pconn->used && !pconn->server.is_closing) {
430 if (FD_ISSET(pconn->sock, &exceptfs)) {
431 log_verbose("connection (%s) cut due to exception data",
433 connection_close_server(pconn, _("network exception"));
434 } else {
435 if (pconn->send_buffer && pconn->send_buffer->ndata > 0) {
436 if (FD_ISSET(pconn->sock, &writefs)) {
438 } else {
440 }
441 }
442 }
443 }
444 }
445 }
446}
447
449 void *data;
451};
452
453/*************************************************************************/
456static bool get_packet(struct connection *pconn,
458{
460
461 return NULL != ppacket->data;
462}
463
464/*************************************************************************/
470{
471 struct packet_to_handle packet;
472#if PROCESSING_TIME_STATISTICS
473 struct timer *request_time = NULL;
474#endif
475
476 while (get_packet(pconn, &packet)) {
477 bool command_ok;
478
479#if PROCESSING_TIME_STATISTICS
480 int request_id;
481
483 request_time != NULL ? NULL : "request");
485#endif /* PROCESSING_TIME_STATISTICS */
486
487 pconn->server.last_request_id_seen
488 = get_next_request_id(pconn->server.last_request_id_seen);
489
490#if PROCESSING_TIME_STATISTICS
491 request_id = pconn->server.last_request_id_seen;
492#endif /* PROCESSING_TIME_STATISTICS */
493
495 start_processing_request(pconn, pconn->server.last_request_id_seen);
496
497 command_ok = server_packet_input(pconn, packet.data, packet.type);
498 free(packet.data);
499
502
503#if PROCESSING_TIME_STATISTICS
504 log_verbose("processed request %d in %gms", request_id,
506#endif /* PROCESSING_TIME_STATISTICS */
507
508 if (!command_ok) {
509 connection_close_server(pconn, _("rejected"));
510 }
511 }
512
513#if PROCESSING_TIME_STATISTICS
515#endif /* PROCESSING_TIME_STATISTICS */
516}
517
518/*************************************************************************/
528{
529 int i, s;
530 int max_desc;
531 bool excepting;
534#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
535 char *bufptr;
536#endif
537
539
540#ifdef FREECIV_HAVE_LIBREADLINE
541 {
544
545 if (storage_dir != NULL) {
546 int fcdl = strlen(storage_dir) + 1;
547 char *fc_dir = fc_malloc(fcdl);
548
549 if (fc_dir != NULL) {
551
552 if (make_dir(fc_dir)) {
555 if (history_file) {
557 strcat(history_file, "/");
561 }
562 }
564 }
565 }
566
568 rl_callback_handler_install((char *) "> ",
571
574 }
575 }
576#endif /* FREECIV_HAVE_LIBREADLINE */
577
578 while (TRUE) {
579 int selret;
580
581 con_prompt_on(); /* accepting new input */
582
583 if (force_end_of_sniff) {
587 }
588
590
591 /* end server if no players for 'srvarg.quitidle' seconds,
592 * but only if at least one player has previously connected. */
593 if (srvarg.quitidle != 0) {
594 static time_t last_noplayers;
595 static bool conns;
596
598 conns = TRUE;
599 }
601 if (last_noplayers != 0) {
603 save_game_auto("Lost all connections", AS_QUITIDLE);
604
605 if (srvarg.exit_on_end) {
606 log_normal(_("Shutting down for lack of players."));
607 set_meta_message_string("shutting down for lack of players");
608 } else {
609 log_normal(_("Restarting for lack of players."));
610 set_meta_message_string("restarting for lack of players");
611 }
613
616
617 if (srvarg.exit_on_end) {
618 /* No need for anything more; just quit. */
619 server_quit();
620 }
621
622 /* Do not restart before someone has connected and left again */
623 conns = FALSE;
624 }
625 } else {
627
628 if (srvarg.exit_on_end) {
629 log_normal(_("Shutting down in %d seconds for lack of players."),
631
632 set_meta_message_string(N_("shutting down soon for lack of players"));
633 } else {
634 log_normal(_("Restarting in %d seconds for lack of players."),
636
637 set_meta_message_string(N_("restarting soon for lack of players"));
638 }
640 }
641 } else {
642 last_noplayers = 0;
643 }
644 }
645
646 /* Pinging around for statistics */
648 /* send data about the previous run */
650
652 if ((!pconn->server.is_closing
653 && 0 < timer_list_size(pconn->server.ping_timers)
655 (pconn->server.ping_timers))
657 || pconn->ping_time > game.server.pingtimeout) {
658 /* cut mute players, except for hack-level ones */
659 if (pconn->access_level == ALLOW_HACK) {
660 log_verbose("connection (%s) [hack-level] ping timeout ignored",
662 } else {
663 log_verbose("connection (%s) cut due to ping timeout",
665 connection_close_server(pconn, _("ping timeout"));
666 }
667 } else if (pconn->established) {
668 /* We don't send ping to connection not established, because
669 * we wouldn't be able to handle asynchronous ping/pong with
670 * different packet header size. */
672 }
675 }
676
677 /* if we've waited long enough after a failure, respond to the client */
680 && !pconn->server.is_closing
681 && pconn->server.status != AS_ESTABLISHED) {
683 }
685
686 /* Don't wait if timeout == -1 (i.e. on auto games) */
687 if (S_S_RUNNING == server_state() && game.info.timeout == -1) {
692 }
693
694 tv.tv_sec = 1;
695 tv.tv_usec = 0;
696
700
701 if (!no_input) {
702#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
704#else /* FREECIV_SOCKET_ZERO_NOT_STDIN */
705# if !defined(__VMS)
706 FD_SET(0, &readfs);
707# endif /* VMS */
708#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
709 }
710
711 max_desc = 0;
712 for (i = 0; i < listen_count; i++) {
716 }
717
718 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
719 struct connection *pconn = connections + i;
720
721 if (pconn->used && !pconn->server.is_closing) {
722 FD_SET(pconn->sock, &readfs);
723 if (0 < pconn->send_buffer->ndata) {
724 FD_SET(pconn->sock, &writefs);
725 }
726 FD_SET(pconn->sock, &exceptfs);
727 max_desc = MAX(pconn->sock, max_desc);
728 }
729 }
730 con_prompt_off(); /* output doesn't generate a new prompt */
731
733 if (selret == 0) {
734 /* timeout */
738 if (current_turn_timeout() > 0
745
747 }
748 if ((game.server.autosaves & (1 << AS_TIMER))
751 >= game.server.save_frequency * 60)) {
752 save_game_auto("Timer", AS_TIMER);
756 ? NULL : "save interval");
758 }
759
760 if (!no_input) {
761#if defined(__VMS)
762 {
763 struct {
764 short numchars;
765 char firstchar;
766 char reserved;
767 int reserved2;
768 } ttchar;
769 unsigned long status;
770
771 status = sys$qiow(EFN$C_ENF, tt_chan,
773 &ttchar, sizeof(ttchar), 0, 0, 0, 0);
774 if (!$VMS_STATUS_SUCCESS(status)) {
775 lib$stop(status);
776 }
777 if (ttchar.numchars) {
778 FD_SET(0, &readfs);
779 } else {
780 continue;
781 }
782 }
783#else /* !__VMS */
784#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
786 continue;
787#endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
788#endif /* !__VMS */
789 }
790 } else if (selret < 0) {
791 log_error("fc_select() failed: %s", fc_strerror(fc_get_errno()));
792 }
793
795 for (i = 0; i < listen_count; i++) {
797 excepting = TRUE;
798 break;
799 }
800 }
801 if (excepting) { /* handle Ctrl-Z suspend/resume */
802 continue;
803 }
804 for (i = 0; i < listen_count; i++) {
805 s = listen_socks[i];
806 if (FD_ISSET(s, &readfs)) { /* new players connects */
807 log_verbose("got new connection");
808 if (-1 == server_accept_connection(s)) {
809 /* There will be a log_error() message from
810 * server_accept_connection() if something
811 * goes wrong, so no need to make another
812 * error-level message here. */
813 log_verbose("failed accepting connection");
814 }
815 }
816 }
817 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
818 /* check for freaky players */
819 struct connection *pconn = &connections[i];
820
821 if (pconn->used
822 && !pconn->server.is_closing
823 && FD_ISSET(pconn->sock, &exceptfs)) {
824 log_verbose("connection (%s) cut due to exception data",
826 connection_close_server(pconn, _("network exception"));
827 }
828 }
829#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
830 if (!no_input && (bufptr = fc_read_console())) {
832
833 con_prompt_enter(); /* Will need a new prompt, regardless */
836 }
837#else /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
838 if (!no_input && FD_ISSET(0, &readfs)) { /* input from server operator */
839#ifdef FREECIV_HAVE_LIBREADLINE
844 }
845 continue;
846#else /* !FREECIV_HAVE_LIBREADLINE */
848 char *buffer;
849
850#ifdef HAVE_GETLINE
851 size_t len = 0;
852
853 buffer = NULL; /* Must be NULL when calling getline() */
855 if (didget >= 1) {
856 buffer[--didget] = '\0'; /* Overwrite newline character */
857 log_debug("Got line: \"%s\" (" SIZE_T_PRINTF ", " SIZE_T_PRINTF ")", buffer,
858 didget, len);
859 }
860#else /* HAVE_GETLINE */
861 buffer = malloc(BUF_SIZE + 1);
862
863 didget = read(0, buffer, BUF_SIZE);
864 if (didget > 0) {
865 buffer[didget] = '\0';
866 } else {
867 didget = -1; /* Error or end-of-file: closing stdin... */
868 }
869#endif /* HAVE_GETLINE */
870 if (didget < 0) {
872 }
873
874 con_prompt_enter(); /* Will need a new prompt, regardless */
875
876 if (didget >= 0) {
880 }
881 free(buffer);
882#endif /* !FREECIV_HAVE_LIBREADLINE */
883 } else
884#endif /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
885
886 { /* Input from a player */
887 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
888 struct connection *pconn = connections + i;
889 int nb;
890
891 if (!pconn->used
892 || pconn->server.is_closing
893 || !FD_ISSET(pconn->sock, &readfs)) {
894 continue;
895 }
896
897 nb = read_socket_data(pconn->sock, pconn->buffer);
898 if (0 <= nb) {
899 /* We read packets; now handle them. */
901 } else if (-2 == nb) {
902 connection_close_server(pconn, _("client disconnected"));
903 } else {
904 /* Read failure; the connection is closed. */
905 connection_close_server(pconn, _("read error"));
906 }
907 }
908
909 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
910 struct connection *pconn = &connections[i];
911
912 if (pconn->used
913 && !pconn->server.is_closing
914 && pconn->send_buffer
915 && pconn->send_buffer->ndata > 0) {
916 if (FD_ISSET(pconn->sock, &writefs)) {
918 } else {
920 }
921 }
922 }
924 break;
925 }
926 }
928
931
932 if (current_turn_timeout() > 0
939 }
940 if ((game.server.autosaves & (1 << AS_TIMER))
943 >= game.server.save_frequency * 60)) {
944 save_game_auto("Timer", AS_TIMER);
948 ? NULL : "save interval");
950 }
951
952 return S_E_OTHERWISE;
953}
954
955/*************************************************************************/
963static const char *makeup_connection_name(int *id)
964{
965 static unsigned short i = 0;
966 static char name[MAX_LEN_NAME];
967
968 for (;;) {
969 if (i == (unsigned short) - 1) {
970 /* don't use 0 */
971 i++;
972 }
973 fc_snprintf(name, sizeof(name), "c%u", (unsigned int)++i);
974 if (NULL == player_by_name(name)
976 && NULL == conn_by_number(i)
977 && NULL == conn_by_user(name)) {
978 *id = i;
979 return name;
980 }
981 }
982}
983
984/*************************************************************************/
991{
992 /* This used to have size_t for some platforms. If this is necessary
993 * it should be done with a configure check not a platform check. */
995
996 int new_sock;
997 union fc_sockaddr fromend;
998 bool nameinfo = FALSE;
999#ifdef FREECIV_IPV6_SUPPORT
1000 char host[NI_MAXHOST], service[NI_MAXSERV];
1001 char dst[INET6_ADDRSTRLEN];
1002#else /* IPv6 support */
1003 struct hostent *from;
1004 const char *host = NULL;
1005 const char *dst;
1006#endif /* IPv6 support */
1007
1008 fromlen = sizeof(fromend);
1009
1010 if ((new_sock = accept(sockfd, &fromend.saddr, &fromlen)) == -1) {
1011 log_error("accept failed: %s", fc_strerror(fc_get_errno()));
1012 return -1;
1013 }
1014
1015#ifdef FREECIV_IPV6_SUPPORT
1016 if (fromend.saddr.sa_family == AF_INET6) {
1017 inet_ntop(AF_INET6, &fromend.saddr_in6.sin6_addr,
1018 dst, sizeof(dst));
1019 } else if (fromend.saddr.sa_family == AF_INET) {
1020 inet_ntop(AF_INET, &fromend.saddr_in4.sin_addr, dst, sizeof(dst));
1021 } else {
1023
1024 log_error("Unsupported address family in server_accept_connection()");
1025
1026 return -1;
1027 }
1028#else /* IPv6 support */
1029 dst = inet_ntoa(fromend.saddr_in4.sin_addr);
1030#endif /* IPv6 support */
1031
1033 int count = 0;
1034
1036 if (0 != strcmp(dst, pconn->server.ipaddr)) {
1037 continue;
1038 }
1039 if (++count >= game.server.maxconnectionsperhost) {
1040 log_verbose("Rejecting new connection from %s: maximum number of "
1041 "connections for this address exceeded (%d).",
1043
1044 /* Disconnect the accepted socket. */
1046
1047 return -1;
1048 }
1050 }
1051
1052#ifdef FREECIV_IPV6_SUPPORT
1053 nameinfo = (0 == getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
1055 && '\0' != host[0]);
1056#else /* IPv6 support */
1057 from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
1058 sizeof(fromend.saddr_in4.sin_addr), AF_INET);
1059 if (NULL != from && '\0' != from->h_name[0]) {
1060 host = from->h_name;
1061 nameinfo = TRUE;
1062 }
1063#endif /* IPv6 support */
1064
1066 (nameinfo ? host : dst), dst);
1067}
1068
1069/*************************************************************************/
1076 const char *client_ip)
1077{
1078 struct timer *timer;
1079 int i;
1080
1082
1083 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
1084 struct connection *pconn = &connections[i];
1085
1086 if (!pconn->used) {
1088 pconn->sock = new_sock;
1089 pconn->observer = FALSE;
1090 pconn->playing = NULL;
1091 pconn->capability[0] = '\0';
1092 pconn->access_level = access_level_for_next_connection();
1093 pconn->notify_of_writable_data = NULL;
1094 pconn->server.currently_processed_request_id = 0;
1095 pconn->server.last_request_id_seen = 0;
1096 pconn->server.auth_tries = 0;
1097 pconn->server.auth_settime = 0;
1098 pconn->server.status = AS_NOT_ESTABLISHED;
1099 pconn->server.ping_timers = timer_list_new_full(timer_destroy);
1100 pconn->server.granted_access_level = pconn->access_level;
1101 pconn->server.ignore_list =
1103 pconn->server.is_closing = FALSE;
1104 pconn->ping_time = -1.0;
1105 pconn->incoming_packet_notify = NULL;
1106 pconn->outgoing_packet_notify = NULL;
1107
1108 sz_strlcpy(pconn->username, makeup_connection_name(&pconn->id));
1110 sz_strlcpy(pconn->server.ipaddr, client_ip);
1111
1113
1114 log_verbose("connection (%s) from %s (%s)",
1115 pconn->username, pconn->addr, pconn->server.ipaddr);
1116 /* Give a ping timeout to send the PACKET_SERVER_JOIN_REQ, or close
1117 * the mute connection. This timer will be canceled into
1118 * connecthand.c:handle_login_request(). */
1119 timer = timer_new(TIMER_USER, TIMER_ACTIVE, "ping timer");
1121 timer_list_append(pconn->server.ping_timers, timer);
1122
1123 return 0;
1124 }
1125 }
1126
1127 log_error("maximum number of connections reached");
1129
1130 return -1;
1131}
1132
1133/*************************************************************************/
1138{
1139 /* setup socket address */
1140 union fc_sockaddr addr;
1141#ifdef HAVE_IP_MREQN
1142 struct ip_mreqn mreq4;
1143#else
1144 struct ip_mreq mreq4;
1145#endif
1146 const char *cause, *group;
1147 int j, on, s;
1148 int lan_family;
1149 struct fc_sockaddr_list *list;
1150 int name_count;
1151 fc_errno eno = 0;
1152 union fc_sockaddr *problematic = NULL;
1153
1154#ifdef FREECIV_IPV6_SUPPORT
1155 struct ipv6_mreq mreq6;
1156#endif
1157
1158 log_verbose("Server attempting to listen on %s:%d",
1159 srvarg.bind_addr ? srvarg.bind_addr : "(any)",
1160 srvarg.port);
1161
1162 /* Any supported family will do */
1164
1166
1167 /* Lookup addresses to bind. */
1168 if (name_count <= 0) {
1169 log_fatal(_("Server: bad address: <%s:%d>."),
1170 srvarg.bind_addr ? srvarg.bind_addr : "(none)", srvarg.port);
1172 }
1173
1174 cause = "internal"; /* If cause is not overwritten but gets printed... */
1175 on = 1;
1176
1177 /* Loop to create sockets, bind, listen. */
1179 listen_count = 0;
1180
1182 /* Create socket for client connections. */
1183 s = socket(paddr->saddr.sa_family, SOCK_STREAM, 0);
1184 if (s == -1) {
1185 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1186 * Kernel might have disabled AF_INET6. */
1187 eno = fc_get_errno();
1188 cause = "socket";
1190 continue;
1191 }
1192
1193#ifndef FREECIV_HAVE_WINSOCK
1194 /* SO_REUSEADDR considered harmful on Win, necessary otherwise */
1196 (char *)&on, sizeof(on)) == -1) {
1197 log_error("setsockopt SO_REUSEADDR failed: %s",
1200 }
1201#endif /* FREECIV_HAVE_WINSOCK */
1202
1203 /* AF_INET6 sockets should use IPv6 only,
1204 * without stealing IPv4 from AF_INET sockets. */
1205#ifdef FREECIV_IPV6_SUPPORT
1206 if (paddr->saddr.sa_family == AF_INET6) {
1207#ifdef IPV6_V6ONLY
1209 (char *)&on, sizeof(on)) == -1) {
1210 log_error("setsockopt IPV6_V6ONLY failed: %s",
1213 }
1214#endif /* IPV6_V6ONLY */
1215 }
1216#endif /* IPv6 support */
1217
1218 if (bind(s, &paddr->saddr, sockaddr_size(paddr)) == -1) {
1219 eno = fc_get_errno();
1220 cause = "bind";
1222
1223 if (eno == EADDRNOTAVAIL) {
1224 /* Close only this socket. This address is not available.
1225 * This can happen with the IPv6 wildcard address if this
1226 * machine has no IPv6 interfaces. */
1227 /* If you change this logic, be sure to make clientside checking
1228 * of acceptable port to match. */
1229 fc_closesocket(s);
1230 continue;
1231 } else {
1232 /* Close all sockets. Another program might have bound to
1233 * one of our addresses, and might hijack some of our
1234 * connections. */
1235 fc_closesocket(s);
1236 for (j = 0; j < listen_count; j++) {
1238 }
1239 listen_count = 0;
1240 break;
1241 }
1242 }
1243
1244 if (listen(s, MAX_NUM_CONNECTIONS) == -1) {
1245 eno = fc_get_errno();
1246 cause = "listen";
1248 fc_closesocket(s);
1249 continue;
1250 }
1251
1254
1255 if (listen_count == 0) {
1256 log_fatal("%s failure: %s (%d failed)", cause, fc_strerror(eno), name_count);
1257 if (problematic != NULL) {
1259 }
1261 /* Do not list already logged 'problematic' again */
1262 if (paddr != problematic) {
1264 }
1267 }
1268
1270
1272
1273 if (srvarg.announce == ANNOUNCE_NONE) {
1274 return 0;
1275 }
1276
1277#ifdef FREECIV_IPV6_SUPPORT
1278 if (srvarg.announce == ANNOUNCE_IPV6) {
1280 } else
1281#endif /* IPV6 support */
1282 {
1284 }
1285
1286 /* Create socket for server LAN announcements */
1287 if ((socklan = socket(lan_family, SOCK_DGRAM, 0)) < 0) {
1288 log_error("Announcement socket failed: %s", fc_strerror(fc_get_errno()));
1289 return 0; /* FIXME: Should this cause hard error as exit(EXIT_FAILURE).
1290 * It's a failure to do as commandline parameters requested
1291 * after all */
1292 }
1293
1295 (char *)&on, sizeof(on)) == -1) {
1296 log_error("SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1297 }
1298
1300
1302
1303 memset(&addr, 0, sizeof(addr));
1304
1305 addr.saddr.sa_family = lan_family;
1306
1307#ifdef FREECIV_IPV6_SUPPORT
1308 if (addr.saddr.sa_family == AF_INET6) {
1309 addr.saddr_in6.sin6_family = AF_INET6;
1310 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT);
1311 addr.saddr_in6.sin6_addr = in6addr_any;
1312 } else
1313#endif /* IPv6 support */
1314 if (addr.saddr.sa_family == AF_INET) {
1315 addr.saddr_in4.sin_family = AF_INET;
1316 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT);
1317 addr.saddr_in4.sin_addr.s_addr = htonl(INADDR_ANY);
1318 } else {
1320
1321 log_error("Unsupported address family in server_open_socket()");
1322 }
1323
1324 if (bind(socklan, &addr.saddr, sockaddr_size(&addr)) < 0) {
1325 log_error("Announcement socket binding failed: %s", fc_strerror(fc_get_errno()));
1326 }
1327
1328#ifdef FREECIV_IPV6_SUPPORT
1329 if (addr.saddr.sa_family == AF_INET6) {
1330 inet_pton(AF_INET6, group, &mreq6.ipv6mr_multiaddr.s6_addr);
1331 mreq6.ipv6mr_interface = 0; /* TODO: Interface selection */
1333 (const char*)&mreq6, sizeof(mreq6)) < 0) {
1334 log_error("FC_IPV6_ADD_MEMBERSHIP (%s) failed: %s",
1335 group, fc_strerror(fc_get_errno()));
1336 }
1337 } else
1338#endif /* IPV6 Support */
1339 if (addr.saddr.sa_family == AF_INET) {
1340 fc_inet_aton(group, &mreq4.imr_multiaddr, FALSE);
1341#ifdef HAVE_IP_MREQN
1342 mreq4.imr_address.s_addr = htonl(INADDR_ANY);
1343 mreq4.imr_ifindex = 0;
1344#else
1345 mreq4.imr_interface.s_addr = htonl(INADDR_ANY);
1346#endif
1347
1349 (const char*)&mreq4, sizeof(mreq4)) < 0) {
1350 log_error("IP_ADD_MEMBERSHIP (%s) failed: %s",
1351 group, fc_strerror(fc_get_errno()));
1352 }
1353 } else {
1355
1356 log_error("Unsupported address family for broadcasting.");
1357 }
1358
1359 return 0;
1360}
1361
1362/*************************************************************************/
1367{
1368 int i;
1369
1374
1375 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
1376 struct connection *pconn = &connections[i];
1377
1378 pconn->used = FALSE;
1379 pconn->self = conn_list_new();
1381 }
1382#if defined(__VMS)
1383 {
1384 unsigned long status;
1385
1386 $DESCRIPTOR (tt_desc, "SYS$INPUT");
1387 status = sys$assign(&tt_desc, &tt_chan, 0, 0);
1390 }
1391 }
1392#endif /* VMS */
1393}
1394
1395/*************************************************************************/
1399 int request_id)
1400{
1402 fc_assert_ret(pconn->server.currently_processed_request_id == 0);
1403 log_debug("start processing packet %d from connection %d",
1404 request_id, pconn->id);
1407 pconn->server.currently_processed_request_id = request_id;
1408}
1409
1410/*************************************************************************/
1414{
1415 if (!pconn || !pconn->used) {
1416 return;
1417 }
1418
1419 fc_assert_ret(pconn->server.currently_processed_request_id);
1420
1421 log_debug("finish processing packet %d from connection %d",
1422 pconn->server.currently_processed_request_id, pconn->id);
1424 pconn->server.currently_processed_request_id = 0;
1426}
1427
1428/*************************************************************************/
1432{
1433 struct timer *timer = timer_new(TIMER_USER, TIMER_ACTIVE, "connection ping");
1434
1435 log_debug("sending ping to %s (open=%d)", conn_description(pconn),
1436 timer_list_size(pconn->server.ping_timers));
1438 timer_list_append(pconn->server.ping_timers, timer);
1440}
1441
1442/*************************************************************************/
1446{
1447 struct timer *timer;
1448
1449 if (timer_list_size(pconn->server.ping_timers) == 0) {
1450 log_error("got unexpected pong from %s", conn_description(pconn));
1451 return;
1452 }
1453
1454 timer = timer_list_front(pconn->server.ping_timers);
1455 pconn->ping_time = timer_read_seconds(timer);
1456 timer_list_pop_front(pconn->server.ping_timers);
1457 log_debug("got pong from %s (open=%d); ping time = %fs",
1459 timer_list_size(pconn->server.ping_timers), pconn->ping_time);
1460}
1461
1462/*************************************************************************/
1466{
1467 log_debug("Received heartbeat");
1468}
1469
1470/*************************************************************************/
1473static void send_ping_times_to_all(void)
1474{
1475 struct packet_conn_ping_info packet;
1476 int i;
1477
1478 i = 0;
1480 if (!pconn->used) {
1481 continue;
1482 }
1483 fc_assert(i < ARRAY_SIZE(packet.conn_id));
1484 packet.conn_id[i] = pconn->id;
1485 packet.ping_time[i] = pconn->ping_time;
1486 i++;
1488 packet.connections = i;
1489
1491}
1492
1493/*************************************************************************/
1498{
1500 fc_timeval tv;
1501 char msgbuf[128];
1502 struct data_in din;
1503 int type;
1504
1505 if (srvarg.announce == ANNOUNCE_NONE) {
1506 return;
1507 }
1508
1509 FD_ZERO(&readfs);
1510 FD_ZERO(&exceptfs);
1513
1514 tv.tv_sec = 0;
1515 tv.tv_usec = 0;
1516
1517 while (fc_select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) {
1518 if (errno != EINTR) {
1519 log_error("select failed: %s", fc_strerror(fc_get_errno()));
1520 return;
1521 }
1522 /* EINTR can happen sometimes, especially when compiling with -pg.
1523 * Generally we just want to run select again. */
1524 }
1525
1526 /* We would need a raw network connection for broadcast messages */
1527 if (FD_ISSET(socklan, &readfs)) {
1528 if (0 < recvfrom(socklan, msgbuf, sizeof(msgbuf), 0, NULL, NULL)) {
1531 if (type == SERVER_LAN_VERSION) {
1532 log_debug("Received request for server LAN announcement.");
1534 } else {
1535 log_debug("Received invalid request for server LAN announcement.");
1536 }
1537 }
1538 }
1539}
1540
1541/*************************************************************************/
1545/* We would need a raw network connection for broadcast messages */
1547{
1548#ifndef FREECIV_HAVE_WINSOCK
1549 unsigned char buffer[MAX_LEN_PACKET];
1550#else /* FREECIV_HAVE_WINSOCK */
1551 char buffer[MAX_LEN_PACKET];
1552#endif /* FREECIV_HAVE_WINSOCK */
1553 char hostname[512];
1554 char port[256];
1555 char version[256];
1556 char players[256];
1557 int nhumans;
1558 char humans[256];
1559 char status[256];
1560 struct raw_data_out dout;
1561 union fc_sockaddr addr;
1562 int socksend, setting = 1;
1563 const char *group;
1564 size_t size;
1565#ifndef FREECIV_HAVE_WINSOCK
1566 unsigned char ttl;
1567#endif
1569
1570 /* Create a socket to broadcast to client. */
1571 if ((socksend = socket(addr_fam, SOCK_DGRAM, 0)) < 0) {
1572 log_error("Lan response socket failed: %s", fc_strerror(fc_get_errno()));
1573 return;
1574 }
1575
1576 /* Set the UDP Multicast group IP address of the packet. */
1578 memset(&addr, 0, sizeof(addr));
1579#ifdef FREECIV_IPV6_SUPPORT
1580 if (addr_fam == AF_INET6) {
1581 addr.saddr_in6.sin6_family = AF_INET6;
1582 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT + 1);
1583 inet_pton(addr_fam, group, &addr.saddr_in6.sin6_addr);
1584 } else
1585#endif /* FREECIV_IPV6_SUPPORT */
1586 {
1587 addr.saddr_in4.sin_family = AF_INET;
1588 addr.saddr_in4.sin_addr.s_addr = inet_addr(group);
1589 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT + 1);
1590 }
1591
1592 /* This setsockopt call fails on Windows 98, so we stick with the default
1593 * value of 1 on Windows, which should be fine in most cases */
1594#ifndef FREECIV_HAVE_WINSOCK
1595 {
1596 int proto;
1597
1598#ifdef FREECIV_IPV6_SUPPORT
1599 if (addr_fam == AF_INET6) {
1601 } else
1602#endif /* FREECIV_IPV6_SUPPORT */
1603 {
1604 proto = IPPROTO_IP;
1605 }
1606
1607 /* Set the Time-to-Live field for the packet. */
1610 (const char*)&ttl, sizeof(ttl))) {
1611 log_error("setsockopt failed: %s", fc_strerror(fc_get_errno()));
1612 return;
1613 }
1614 }
1615#endif /* FREECIV_HAVE_WINSOCK */
1616
1618 (const char*)&setting, sizeof(setting))) {
1619 log_error("Lan response setsockopt failed: %s", fc_strerror(fc_get_errno()));
1620 return;
1621 }
1622
1623 /* Create a description of server state to send to clients. */
1624 if (srvarg.identity_name[0] != '\0') {
1626 } else if (fc_gethostname(hostname, sizeof(hostname)) != 0) {
1627 sz_strlcpy(hostname, "none");
1628 }
1629
1630 fc_snprintf(version, sizeof(version), "%d.%d.%d%s",
1632
1633 switch (server_state()) {
1634 case S_S_INITIAL:
1635 /* TRANS: Game state for local server */
1636 fc_snprintf(status, sizeof(status), _("Pregame"));
1637 break;
1638 case S_S_RUNNING:
1639 /* TRANS: Game state for local server */
1640 fc_snprintf(status, sizeof(status), _("Running"));
1641 break;
1642 case S_S_OVER:
1643 /* TRANS: Game state for local server */
1644 fc_snprintf(status, sizeof(status), _("Game over"));
1645 break;
1646 }
1647
1648 fc_snprintf(players, sizeof(players), "%d",
1650
1651 nhumans = 0;
1652 players_iterate(pplayer) {
1653 if (pplayer->is_alive && is_human(pplayer)) {
1654 nhumans++;
1655 }
1657 fc_snprintf(humans, sizeof(humans), "%d", nhumans);
1658
1659 fc_snprintf(port, sizeof(port), "%d",
1660 srvarg.port);
1661
1662 dio_output_init(&dout, buffer, sizeof(buffer));
1665 dio_put_string_raw(&dout, port);
1666 dio_put_string_raw(&dout, version);
1667 dio_put_string_raw(&dout, status);
1668 dio_put_string_raw(&dout, players);
1669 dio_put_string_raw(&dout, humans);
1672
1673 /* Sending packet to client with the information gathered above. */
1674 if (sendto(socksend, buffer, size, 0, &addr.saddr,
1675 sockaddr_size(&addr)) < 0) {
1676 log_error("landserver response sendto failed: %s",
1678 return;
1679 }
1680
1682}
void call_ai_refresh(void)
Definition aiiface.c:256
void auth_process_status(struct connection *pconn)
Definition auth.c:207
static struct ai_type * self
Definition classicai.c:45
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:75
#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:62
int current_turn_timeout(void)
Definition game.c:848
@ 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: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: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
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:537
#define players_iterate(_pplayer)
Definition player.h:532
#define is_human(plr)
Definition player.h:229
int normal_player_count(void)
Definition plrhand.c:3204
void script_server_signal_emit(const char *signal_name,...)
static void cut_lagging_connection(struct connection *pconn)
Definition sernet.c:356
static void connection_ping(struct connection *pconn)
Definition sernet.c:1431
static void server_conn_close_callback(struct connection *pconn)
Definition sernet.c:347
static void send_lanserver_response(void)
Definition sernet.c:1546
static struct connection connections[MAX_NUM_CONNECTIONS]
Definition sernet.c:94
int server_open_socket(void)
Definition sernet.c:1137
void flush_packets(void)
Definition sernet.c:381
void init_connections(void)
Definition sernet.c:1366
static void really_close_connections(void)
Definition sernet.c:309
int server_make_connection(int new_sock, const char *client_addr, const char *client_ip)
Definition sernet.c:1075
void handle_conn_pong(struct connection *pconn)
Definition sernet.c:1445
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:456
static void send_ping_times_to_all(void)
Definition sernet.c:1473
enum server_events server_sniff_all_input(void)
Definition sernet.c:527
static void close_connection(struct connection *pconn)
Definition sernet.c:228
void handle_client_heartbeat(struct connection *pconn)
Definition sernet.c:1465
void readline_atexit(void)
Definition sernet.c:209
void close_connections_and_socket(void)
Definition sernet.c:260
static void finish_processing_request(struct connection *pconn)
Definition sernet.c:1413
static void start_processing_request(struct connection *pconn, int request_id)
Definition sernet.c:1398
static void handle_stdin_close(void)
Definition sernet.c:144
static const char * makeup_connection_name(int *id)
Definition sernet.c:963
static int server_accept_connection(int sockfd)
Definition sernet.c:990
static void get_lanserver_announcement(void)
Definition sernet.c:1497
static bool no_input
Definition sernet.c:135
static void incoming_client_packets(struct connection *pconn)
Definition sernet.c:469
#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:1782
char * get_multicast_group(bool ipv6_preferred)
Definition shared.c:1674
char * freeciv_storage_dir(void)
Definition shared.c:678
#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:188
void save_game_auto(const char *save_reason, enum autosave_type type)
Definition srv_main.c:1797
void set_server_state(enum server_states newstate)
Definition srv_main.c:341
struct server_arguments srvarg
Definition srv_main.c:176
bool server_packet_input(struct connection *pconn, void *packet, int type)
Definition srv_main.c:2051
void fc__noreturn server_quit(void)
Definition srv_main.c:1875
enum server_states server_state(void)
Definition srv_main.c:333
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:199
struct conn_list * glob_observers
Definition game.h:98
int netwait
Definition game.h:172
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
unsigned autosaves
Definition game.h:189
struct timer * save_timer
Definition game.h:221
time_t last_ping
Definition game.h:214
int additional_phase_seconds
Definition game.h:216
int maxconnectionsperhost
Definition game.h:159
int pingtimeout
Definition game.h:177
struct conn_list * web_client_connections
Definition game.h:99
struct timer * phase_timer
Definition game.h:215
int pingtime
Definition game.h:176
struct conn_list * all_connections
Definition game.h:96
struct civ_game::@31::@35 server
struct packet_timeout_info tinfo
Definition game.h:91
int save_frequency
Definition game.h:188
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:450
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:974
int fc_gethostname(char *buf, size_t len)
Definition support.c:1021
const char * fc_strerror(fc_errno err)
Definition support.c:611
fc_errno fc_get_errno(void)
Definition support.c:594
#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:264
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:384
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