Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/sernet.c Source File

Freeciv-3.1

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