Made ruleset comments about extra activity graphic value "None" more verbose.
[freeciv.git] / server / sernet.c
blob1ce6df85581206ffb5dbbb05ab8dd5c3e84ac053
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include "fc_prehdrs.h"
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
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
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"
72 /* common */
73 #include "dataio.h"
74 #include "events.h"
75 #include "game.h"
76 #include "packets.h"
78 /* server/scripting */
79 #include "script_server.h"
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"
92 #include "sernet.h"
94 static struct connection connections[MAX_NUM_CONNECTIONS];
96 #ifdef GENERATING_MAC /* mac network globals */
97 TEndpointInfo serv_info;
98 EndpointRef serv_ep;
99 #else
100 static int *listen_socks;
101 static int listen_count;
102 static int socklan;
103 #endif
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
123 #define PROCESSING_TIME_STATISTICS 0
125 static int server_accept_connection(int sockfd);
126 static void start_processing_request(struct connection *pconn,
127 int request_id);
128 static void finish_processing_request(struct connection *pconn);
129 static void connection_ping(struct connection *pconn);
130 static void send_ping_times_to_all(void);
132 static void get_lanserver_announcement(void);
133 static void send_lanserver_response(void);
135 static bool no_input = FALSE;
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 /*****************************************************************************
142 This happens if you type an EOF character with nothing on the current line.
143 *****************************************************************************/
144 static void handle_stdin_close(void)
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 */
155 #endif /* FREECIV_HAVE_LIBREADLINE || (!FREECIV_SOCKET_ZERO_NOT_STDIN && !FREECIV_HAVE_LIBREADLINE) */
157 #ifdef FREECIV_HAVE_LIBREADLINE
158 /****************************************************************************/
160 #define HISTORY_FILENAME "freeciv-server_history"
161 #define HISTORY_LENGTH 100
163 static char *history_file = NULL;
165 static bool readline_handled_input = FALSE;
167 static bool readline_initialized = FALSE;
169 /*****************************************************************************
170 Readline callback for input.
171 *****************************************************************************/
172 static void handle_readline_input_callback(char *line)
174 char *line_internal;
176 if (no_input)
177 return;
179 if (!line) {
180 handle_stdin_close(); /* maybe print an 'are you sure?' message? */
181 return;
184 if (line[0] != '\0')
185 add_history(line);
187 con_prompt_enter(); /* just got an 'Enter' hit */
188 line_internal = local_to_internal_string_malloc(line);
189 (void) handle_stdin_input(NULL, line_internal);
190 free(line_internal);
191 free(line);
193 readline_handled_input = TRUE;
195 #endif /* FREECIV_HAVE_LIBREADLINE */
197 /****************************************************************************
198 Close the connection (very low-level). See also
199 server_conn_close_callback().
200 ****************************************************************************/
201 static void close_connection(struct connection *pconn)
203 if (!pconn) {
204 return;
207 if (pconn->server.ping_timers != NULL) {
208 timer_list_destroy(pconn->server.ping_timers);
209 pconn->server.ping_timers = NULL;
212 conn_pattern_list_destroy(pconn->server.ignore_list);
213 pconn->server.ignore_list = NULL;
215 /* safe to do these even if not in lists: */
216 conn_list_remove(game.glob_observers, pconn);
217 conn_list_remove(game.all_connections, pconn);
218 conn_list_remove(game.est_connections, pconn);
220 pconn->playing = NULL;
221 pconn->access_level = ALLOW_NONE;
222 connection_common_close(pconn);
224 send_updated_vote_totals(NULL);
227 /*****************************************************************************
228 Close all network stuff: connections, listening sockets, metaserver
229 connection...
230 *****************************************************************************/
231 void close_connections_and_socket(void)
233 int i;
235 lsend_packet_server_shutdown(game.all_connections);
237 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
238 if (connections[i].used) {
239 close_connection(&connections[i]);
241 conn_list_destroy(connections[i].self);
244 /* Remove the game connection lists and make sure they are empty. */
245 conn_list_destroy(game.glob_observers);
246 conn_list_destroy(game.all_connections);
247 conn_list_destroy(game.est_connections);
249 for (i = 0; i < listen_count; i++) {
250 fc_closesocket(listen_socks[i]);
252 FC_FREE(listen_socks);
254 if (srvarg.announce != ANNOUNCE_NONE) {
255 fc_closesocket(socklan);
258 #ifdef FREECIV_HAVE_LIBREADLINE
259 if (history_file) {
260 write_history(history_file);
261 history_truncate_file(history_file, HISTORY_LENGTH);
262 free(history_file);
263 history_file = NULL;
264 clear_history();
266 #endif /* FREECIV_HAVE_LIBREADLINE */
268 send_server_info_to_metaserver(META_GOODBYE);
269 server_close_meta();
271 packets_deinit();
272 fc_shutdown_network();
275 /****************************************************************************
276 Now really close connections marked as 'is_closing'.
277 Do this here to avoid recursive sending.
278 ****************************************************************************/
279 static void really_close_connections(void)
281 struct connection *closing[MAX_NUM_CONNECTIONS];
282 struct connection *pconn;
283 int i, num;
285 do {
286 num = 0;
288 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
289 pconn = connections + i;
290 if (pconn->used && pconn->server.is_closing) {
291 closing[num++] = pconn;
292 /* Remove closing connections from the lists (hard detach)
293 * to avoid sending to closing connections. */
294 conn_list_remove(game.glob_observers, pconn);
295 conn_list_remove(game.est_connections, pconn);
296 conn_list_remove(game.all_connections, pconn);
297 if (NULL != conn_get_player(pconn)) {
298 conn_list_remove(conn_get_player(pconn)->connections, pconn);
303 for (i = 0; i < num; i++) {
304 /* Now really close them. */
305 pconn = closing[i];
306 lost_connection_to_client(pconn);
307 close_connection(pconn);
309 } while (0 < num); /* May some errors occurred, let's check. */
312 /****************************************************************************
313 Break a client connection. You should almost always use
314 connection_close_server() instead of calling this function directly.
315 ****************************************************************************/
316 static void server_conn_close_callback(struct connection *pconn)
318 /* Do as little as possible here to avoid recursive evil. */
319 pconn->server.is_closing = TRUE;
322 /****************************************************************************
323 If a connection lags too much this function is called and we try to cut
325 ****************************************************************************/
326 static void cut_lagging_connection(struct connection *pconn)
328 if (!pconn->server.is_closing
329 && game.server.tcptimeout != 0
330 && pconn->last_write
331 && conn_list_size(game.all_connections) > 1
332 && pconn->access_level != ALLOW_HACK
333 && timer_read_seconds(pconn->last_write) > game.server.tcptimeout) {
334 /* Cut the connections to players who lag too much. This
335 * usually happens because client animation slows the client
336 * too much and it can't keep up with the server. We don't
337 * cut HACK connections, or cut in single-player games, since
338 * it wouldn't help the game progress. For other connections
339 * the best thing to do when they lag too much is to be
340 * disconnected and reconnect. */
341 log_verbose("connection (%s) cut due to lagging player",
342 conn_description(pconn));
343 connection_close_server(pconn, _("lagging connection"));
347 /****************************************************************************
348 Attempt to flush all information in the send buffers for upto 'netwait'
349 seconds.
350 *****************************************************************************/
351 void flush_packets(void)
353 int i;
354 int max_desc;
355 fd_set writefs, exceptfs;
356 struct timeval tv;
357 time_t start;
359 (void) time(&start);
361 for(;;) {
362 tv.tv_sec = (game.server.netwait - (time(NULL) - start));
363 tv.tv_usec=0;
365 if (tv.tv_sec < 0)
366 return;
368 FC_FD_ZERO(&writefs);
369 FC_FD_ZERO(&exceptfs);
370 max_desc=-1;
372 for(i=0; i<MAX_NUM_CONNECTIONS; i++) {
373 struct connection *pconn = &connections[i];
374 if (pconn->used
375 && !pconn->server.is_closing
376 && 0 < pconn->send_buffer->ndata) {
377 FD_SET(pconn->sock, &writefs);
378 FD_SET(pconn->sock, &exceptfs);
379 max_desc=MAX(pconn->sock, max_desc);
383 if (max_desc == -1) {
384 return;
387 if(fc_select(max_desc+1, NULL, &writefs, &exceptfs, &tv)<=0) {
388 return;
391 for(i=0; i<MAX_NUM_CONNECTIONS; i++) { /* check for freaky players */
392 struct connection *pconn = &connections[i];
393 if (pconn->used && !pconn->server.is_closing) {
394 if(FD_ISSET(pconn->sock, &exceptfs)) {
395 log_verbose("connection (%s) cut due to exception data",
396 conn_description(pconn));
397 connection_close_server(pconn, _("network exception"));
398 } else {
399 if(pconn->send_buffer && pconn->send_buffer->ndata > 0) {
400 if(FD_ISSET(pconn->sock, &writefs)) {
401 flush_connection_send_buffer_all(pconn);
402 } else {
403 cut_lagging_connection(pconn);
412 struct packet_to_handle {
413 void *data;
414 enum packet_type type;
417 /*****************************************************************************
418 Simplify a loop by wrapping get_packet_from_connection.
419 *****************************************************************************/
420 static bool get_packet(struct connection *pconn,
421 struct packet_to_handle *ppacket)
423 ppacket->data = get_packet_from_connection(pconn, &ppacket->type);
425 return NULL != ppacket->data;
428 /*****************************************************************************
429 Handle all incoming packets on a client connection.
430 Precondition - we have read_socket_data.
431 Postcondition - there are no more packets to handle on this connection.
432 *****************************************************************************/
433 static void incoming_client_packets(struct connection *pconn)
435 struct packet_to_handle packet;
436 #if PROCESSING_TIME_STATISTICS
437 struct timer *request_time = NULL;
438 #endif
440 while (get_packet(pconn, &packet)) {
441 bool command_ok;
443 #if PROCESSING_TIME_STATISTICS
444 int request_id;
446 request_time = timer_renew(request_time, TIMER_USER, TIMER_ACTIVE);
447 timer_start(request_time);
448 #endif /* PROCESSING_TIME_STATISTICS */
450 pconn->server.last_request_id_seen
451 = get_next_request_id(pconn->server.last_request_id_seen);
453 #if PROCESSING_TIME_STATISTICS
454 request_id = pconn->server.last_request_id_seen;
455 #endif /* PROCESSING_TIME_STATISTICS */
457 connection_do_buffer(pconn);
458 start_processing_request(pconn, pconn->server.last_request_id_seen);
460 command_ok = server_packet_input(pconn, packet.data, packet.type);
461 free(packet.data);
463 finish_processing_request(pconn);
464 connection_do_unbuffer(pconn);
466 #if PROCESSING_TIME_STATISTICS
467 log_verbose("processed request %d in %gms", request_id,
468 timer_read_seconds(request_time) * 1000.0);
469 #endif /* PROCESSING_TIME_STATISTICS */
471 if (!command_ok) {
472 connection_close_server(pconn, _("rejected"));
476 #if PROCESSING_TIME_STATISTICS
477 timer_destroy(request_time);
478 #endif /* PROCESSING_TIME_STATISTICS */
482 /*****************************************************************************
483 Get and handle:
484 - new connections,
485 - input from connections,
486 - input from server operator in stdin
488 This function also handles prompt printing, via the con_prompt_*
489 functions. That is, other functions should not need to do so. --dwp
490 *****************************************************************************/
491 enum server_events server_sniff_all_input(void)
493 int i, s;
494 int max_desc;
495 bool excepting;
496 fd_set readfs, writefs, exceptfs;
497 struct timeval tv;
498 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
499 char *bufptr;
500 #endif
502 con_prompt_init();
504 #ifdef FREECIV_HAVE_LIBREADLINE
506 if (!no_input && !readline_initialized) {
507 char *home_dir = user_home_dir();
509 if (home_dir) {
510 int fcdl = strlen(home_dir) + 1 + strlen(".freeciv") + 1;
511 char *fc_dir = fc_malloc(fcdl);
513 if (fc_dir != NULL) {
514 fc_snprintf(fc_dir, fcdl, "%s/.freeciv", home_dir);
516 if (make_dir(fc_dir)) {
517 history_file
518 = fc_malloc(strlen(fc_dir) + 1 + strlen(HISTORY_FILENAME) + 1);
519 if (history_file) {
520 strcpy(history_file, fc_dir);
521 strcat(history_file, "/");
522 strcat(history_file, HISTORY_FILENAME);
523 using_history();
524 read_history(history_file);
527 FC_FREE(fc_dir);
531 rl_initialize();
532 rl_callback_handler_install((char *) "> ",
533 handle_readline_input_callback);
534 rl_attempted_completion_function = freeciv_completion;
536 readline_initialized = TRUE;
537 atexit(rl_callback_handler_remove);
540 #endif /* FREECIV_HAVE_LIBREADLINE */
542 while (TRUE) {
543 con_prompt_on(); /* accepting new input */
545 if (force_end_of_sniff) {
546 force_end_of_sniff = FALSE;
547 con_prompt_off();
548 return S_E_FORCE_END_OF_SNIFF;
551 get_lanserver_announcement();
553 /* end server if no players for 'srvarg.quitidle' seconds,
554 * but only if at least one player has previously connected. */
555 if (srvarg.quitidle != 0) {
556 static time_t last_noplayers;
557 static bool conns;
559 if (conn_list_size(game.est_connections) > 0) {
560 conns = TRUE;
562 if (conns && conn_list_size(game.est_connections) == 0) {
563 if (last_noplayers != 0) {
564 if (time(NULL) > last_noplayers + srvarg.quitidle) {
565 save_game_auto("Lost all connections", AS_QUITIDLE);
567 if (srvarg.exit_on_end) {
568 log_normal(_("Shutting down for lack of players."));
569 set_meta_message_string("shutting down for lack of players");
570 } else {
571 log_normal(_("Restarting for lack of players."));
572 set_meta_message_string("restarting for lack of players");
574 (void) send_server_info_to_metaserver(META_INFO);
576 set_server_state(S_S_OVER);
577 force_end_of_sniff = TRUE;
579 if (srvarg.exit_on_end) {
580 /* No need for anything more; just quit. */
581 server_quit();
584 /* Do not restart before someone has connected and left again */
585 conns = FALSE;
587 } else {
588 last_noplayers = time(NULL);
590 if (srvarg.exit_on_end) {
591 log_normal(_("Shutting down in %d seconds for lack of players."),
592 srvarg.quitidle);
594 set_meta_message_string(N_("shutting down soon for lack of players"));
595 } else {
596 log_normal(_("Restarting in %d seconds for lack of players."),
597 srvarg.quitidle);
599 set_meta_message_string(N_("restarting soon for lack of players"));
601 (void) send_server_info_to_metaserver(META_INFO);
603 } else {
604 last_noplayers = 0;
608 /* Pinging around for statistics */
609 if (time(NULL) > (game.server.last_ping + game.server.pingtime)) {
610 /* send data about the previous run */
611 send_ping_times_to_all();
613 conn_list_iterate(game.all_connections, pconn) {
614 if ((!pconn->server.is_closing
615 && 0 < timer_list_size(pconn->server.ping_timers)
616 && timer_read_seconds(timer_list_front
617 (pconn->server.ping_timers))
618 > game.server.pingtimeout)
619 || pconn->ping_time > game.server.pingtimeout) {
620 /* cut mute players, except for hack-level ones */
621 if (pconn->access_level == ALLOW_HACK) {
622 log_verbose("connection (%s) [hack-level] ping timeout ignored",
623 conn_description(pconn));
624 } else {
625 log_verbose("connection (%s) cut due to ping timeout",
626 conn_description(pconn));
627 connection_close_server(pconn, _("ping timeout"));
629 } else if (pconn->established) {
630 /* We don't send ping to connection not established, because
631 * we wouldn't be able to handle asynchronous ping/pong with
632 * different packet header size. */
633 connection_ping(pconn);
635 } conn_list_iterate_end;
636 game.server.last_ping = time(NULL);
639 /* if we've waited long enough after a failure, respond to the client */
640 conn_list_iterate(game.all_connections, pconn) {
641 if (srvarg.auth_enabled
642 && !pconn->server.is_closing
643 && pconn->server.status != AS_ESTABLISHED) {
644 auth_process_status(pconn);
646 } conn_list_iterate_end
648 /* Don't wait if timeout == -1 (i.e. on auto games) */
649 if (S_S_RUNNING == server_state() && game.info.timeout == -1) {
650 call_ai_refresh();
651 script_server_signal_emit("pulse", 0);
652 (void) send_server_info_to_metaserver(META_REFRESH);
653 return S_E_END_OF_TURN_TIMEOUT;
656 tv.tv_sec = 1;
657 tv.tv_usec = 0;
659 FC_FD_ZERO(&readfs);
660 FC_FD_ZERO(&writefs);
661 FC_FD_ZERO(&exceptfs);
663 if (!no_input) {
664 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
665 fc_init_console();
666 #else /* FREECIV_SOCKET_ZERO_NOT_STDIN */
667 # if !defined(__VMS)
668 FD_SET(0, &readfs);
669 # endif /* VMS */
670 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
673 max_desc = 0;
674 for (i = 0; i < listen_count; i++) {
675 FD_SET(listen_socks[i], &readfs);
676 FD_SET(listen_socks[i], &exceptfs);
677 max_desc = MAX(max_desc, listen_socks[i]);
680 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
681 struct connection *pconn = connections + i;
683 if (pconn->used && !pconn->server.is_closing) {
684 FD_SET(pconn->sock, &readfs);
685 if (0 < pconn->send_buffer->ndata) {
686 FD_SET(pconn->sock, &writefs);
688 FD_SET(pconn->sock, &exceptfs);
689 max_desc = MAX(pconn->sock, max_desc);
692 con_prompt_off(); /* output doesn't generate a new prompt */
694 if (fc_select(max_desc + 1, &readfs, &writefs, &exceptfs, &tv) == 0) {
695 /* timeout */
696 call_ai_refresh();
697 script_server_signal_emit("pulse", 0);
698 (void) send_server_info_to_metaserver(META_REFRESH);
699 if (current_turn_timeout() > 0
700 && S_S_RUNNING == server_state()
701 && game.server.phase_timer
702 && (timer_read_seconds(game.server.phase_timer)
703 > game.tinfo.seconds_to_phasedone)) {
704 con_prompt_off();
705 return S_E_END_OF_TURN_TIMEOUT;
707 if ((game.server.autosaves & (1 << AS_TIMER))
708 && S_S_RUNNING == server_state()
709 && (timer_read_seconds(game.server.save_timer)
710 >= game.server.save_frequency * 60)) {
711 save_game_auto("Timer", AS_TIMER);
712 game.server.save_timer = timer_renew(game.server.save_timer,
713 TIMER_USER, TIMER_ACTIVE);
714 timer_start(game.server.save_timer);
717 if (!no_input) {
718 #if defined(__VMS)
720 struct {
721 short numchars;
722 char firstchar;
723 char reserved;
724 int reserved2;
725 } ttchar;
726 unsigned long status;
728 status = sys$qiow(EFN$C_ENF, tt_chan,
729 IO$_SENSEMODE | IO$M_TYPEAHDCNT, 0, 0, 0,
730 &ttchar, sizeof(ttchar), 0, 0, 0, 0);
731 if (!$VMS_STATUS_SUCCESS(status)) {
732 lib$stop(status);
734 if (ttchar.numchars) {
735 FD_SET(0, &readfs);
736 } else {
737 continue;
740 #else /* !__VMS */
741 #ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
742 really_close_connections();
743 continue;
744 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
745 #endif /* !__VMS */
749 excepting = FALSE;
750 for (i = 0; i < listen_count; i++) {
751 if (FD_ISSET(listen_socks[i], &exceptfs)) {
752 excepting = TRUE;
753 break;
756 if (excepting) { /* handle Ctrl-Z suspend/resume */
757 continue;
759 for (i = 0; i < listen_count; i++) {
760 s = listen_socks[i];
761 if (FD_ISSET(s, &readfs)) { /* new players connects */
762 log_verbose("got new connection");
763 if (-1 == server_accept_connection(s)) {
764 /* There will be a log_error() message from
765 * server_accept_connection() if something
766 * goes wrong, so no need to make another
767 * error-level message here. */
768 log_verbose("failed accepting connection");
772 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
773 /* check for freaky players */
774 struct connection *pconn = &connections[i];
776 if (pconn->used
777 && !pconn->server.is_closing
778 && FD_ISSET(pconn->sock, &exceptfs)) {
779 log_verbose("connection (%s) cut due to exception data",
780 conn_description(pconn));
781 connection_close_server(pconn, _("network exception"));
784 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
785 if (!no_input && (bufptr = fc_read_console())) {
786 char *bufptr_internal = local_to_internal_string_malloc(bufptr);
788 con_prompt_enter(); /* will need a new prompt, regardless */
789 handle_stdin_input(NULL, bufptr_internal);
790 free(bufptr_internal);
792 #else /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
793 if (!no_input && FD_ISSET(0, &readfs)) { /* input from server operator */
794 #ifdef FREECIV_HAVE_LIBREADLINE
795 rl_callback_read_char();
796 if (readline_handled_input) {
797 readline_handled_input = FALSE;
798 con_prompt_enter_clear();
800 continue;
801 #else /* !FREECIV_HAVE_LIBREADLINE */
802 ssize_t didget;
803 char *buffer = NULL; /* Must be NULL when calling getline() */
804 char *buf_internal;
806 #ifdef HAVE_GETLINE
807 size_t len = 0;
809 didget = getline(&buffer, &len, stdin);
810 if (didget >= 1) {
811 buffer[didget-1] = '\0'; /* overwrite newline character */
812 didget--;
813 log_debug("Got line: \"%s\" (%ld, %ld)", buffer,
814 (long int) didget, (long int) len);
816 #else /* HAVE_GETLINE */
817 buffer = malloc(BUF_SIZE + 1);
819 didget = read(0, buffer, BUF_SIZE);
820 if (didget > 0) {
821 buffer[didget] = '\0';
822 } else {
823 didget = -1; /* error or end-of-file: closing stdin... */
825 #endif /* HAVE_GETLINE */
826 if (didget < 0) {
827 handle_stdin_close();
830 con_prompt_enter(); /* will need a new prompt, regardless */
832 if (didget >= 0) {
833 buf_internal = local_to_internal_string_malloc(buffer);
834 handle_stdin_input(NULL, buf_internal);
835 free(buf_internal);
837 free(buffer);
838 #endif /* !FREECIV_HAVE_LIBREADLINE */
839 } else
840 #endif /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
842 { /* input from a player */
843 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
844 struct connection *pconn = connections + i;
845 int nb;
847 if (!pconn->used
848 || pconn->server.is_closing
849 || !FD_ISSET(pconn->sock, &readfs)) {
850 continue;
853 nb = read_socket_data(pconn->sock, pconn->buffer);
854 if (0 <= nb) {
855 /* We read packets; now handle them. */
856 incoming_client_packets(pconn);
857 } else if (-2 == nb) {
858 connection_close_server(pconn, _("client disconnected"));
859 } else {
860 /* Read failure; the connection is closed. */
861 connection_close_server(pconn, _("read error"));
865 for (i = 0; i < MAX_NUM_CONNECTIONS; i++) {
866 struct connection *pconn = &connections[i];
868 if (pconn->used
869 && !pconn->server.is_closing
870 && pconn->send_buffer
871 && pconn->send_buffer->ndata > 0) {
872 if (FD_ISSET(pconn->sock, &writefs)) {
873 flush_connection_send_buffer_all(pconn);
874 } else {
875 cut_lagging_connection(pconn);
879 really_close_connections();
880 break;
883 con_prompt_off();
885 call_ai_refresh();
886 script_server_signal_emit("pulse", 0);
888 if (current_turn_timeout() > 0
889 && S_S_RUNNING == server_state()
890 && game.server.phase_timer
891 && (timer_read_seconds(game.server.phase_timer)
892 > game.tinfo.seconds_to_phasedone)) {
893 return S_E_END_OF_TURN_TIMEOUT;
895 if ((game.server.autosaves & (1 << AS_TIMER))
896 && S_S_RUNNING == server_state()
897 && (timer_read_seconds(game.server.save_timer)
898 >= game.server.save_frequency * 60)) {
899 save_game_auto("Timer", AS_TIMER);
900 game.server.save_timer = timer_renew(game.server.save_timer,
901 TIMER_USER, TIMER_ACTIVE);
902 timer_start(game.server.save_timer);
905 return S_E_OTHERWISE;
908 /********************************************************************
909 Make up a name for the connection, before we get any data from
910 it to use as a sensible name. Name will be 'c' + integer,
911 guaranteed not to be the same as any other connection name,
912 nor player name nor user name, nor connection id (avoid possible
913 confusions). Returns pointer to static buffer, and fills in
914 (*id) with chosen value.
915 ********************************************************************/
916 static const char *makeup_connection_name(int *id)
918 static unsigned short i = 0;
919 static char name[MAX_LEN_NAME];
921 for(;;) {
922 if (i==(unsigned short)-1) i++; /* don't use 0 */
923 fc_snprintf(name, sizeof(name), "c%u", (unsigned int)++i);
924 if (NULL == player_by_name(name)
925 && NULL == player_by_user(name)
926 && NULL == conn_by_number(i)
927 && NULL == conn_by_user(name)) {
928 *id = i;
929 return name;
934 /********************************************************************
935 Server accepts connection from client:
936 Low level socket stuff, and basic-initialize the connection struct.
937 Returns 0 on success, -1 on failure (bad accept(), or too many
938 connections).
939 ********************************************************************/
940 static int server_accept_connection(int sockfd)
942 /* This used to have size_t for some platforms. If this is necessary
943 * it should be done with a configure check not a platform check. */
944 socklen_t fromlen;
946 int new_sock;
947 union fc_sockaddr fromend;
948 bool nameinfo = FALSE;
949 #ifdef FREECIV_IPV6_SUPPORT
950 char host[NI_MAXHOST], service[NI_MAXSERV];
951 char dst[INET6_ADDRSTRLEN];
952 #else /* IPv6 support */
953 struct hostent *from;
954 const char *host = NULL;
955 const char *dst;
956 #endif /* IPv6 support */
958 fromlen = sizeof(fromend);
960 if ((new_sock = accept(sockfd, &fromend.saddr, &fromlen)) == -1) {
961 log_error("accept failed: %s", fc_strerror(fc_get_errno()));
962 return -1;
965 #ifdef FREECIV_IPV6_SUPPORT
966 if (fromend.saddr.sa_family == AF_INET6) {
967 inet_ntop(AF_INET6, &fromend.saddr_in6.sin6_addr,
968 dst, sizeof(dst));
969 } else if (fromend.saddr.sa_family == AF_INET) {
970 inet_ntop(AF_INET, &fromend.saddr_in4.sin_addr, dst, sizeof(dst));
971 } else {
972 fc_assert(FALSE);
974 log_error("Unsupported address family in server_accept_connection()");
976 return -1;
978 #else /* IPv6 support */
979 dst = inet_ntoa(fromend.saddr_in4.sin_addr);
980 #endif /* IPv6 support */
982 if (0 != game.server.maxconnectionsperhost) {
983 int count = 0;
985 conn_list_iterate(game.all_connections, pconn) {
986 if (0 != strcmp(dst, pconn->server.ipaddr)) {
987 continue;
989 if (++count >= game.server.maxconnectionsperhost) {
990 log_verbose("Rejecting new connection from %s: maximum number of "
991 "connections for this address exceeded (%d).",
992 dst, game.server.maxconnectionsperhost);
994 /* Disconnect the accepted socket. */
995 fc_closesocket(new_sock);
997 return -1;
999 } conn_list_iterate_end;
1002 #ifdef FREECIV_IPV6_SUPPORT
1003 nameinfo = (0 == getnameinfo(&fromend.saddr, fromlen, host, NI_MAXHOST,
1004 service, NI_MAXSERV, NI_NUMERICSERV)
1005 && '\0' != host[0]);
1006 #else /* IPv6 support */
1007 from = gethostbyaddr((char *) &fromend.saddr_in4.sin_addr,
1008 sizeof(fromend.saddr_in4.sin_addr), AF_INET);
1009 if (NULL != from && '\0' != from->h_name[0]) {
1010 host = from->h_name;
1011 nameinfo = TRUE;
1013 #endif /* IPv6 support */
1015 return server_make_connection(new_sock,
1016 (nameinfo ? host : dst), dst);
1019 /********************************************************************
1020 Server accepts connection from client:
1021 Low level socket stuff, and basic-initialize the connection struct.
1022 Returns 0 on success, -1 on failure (bad accept(), or too many
1023 connections).
1024 ********************************************************************/
1025 int server_make_connection(int new_sock, const char *client_addr, const char *client_ip)
1027 struct timer *timer;
1028 int i;
1030 fc_nonblock(new_sock);
1032 for(i=0; i<MAX_NUM_CONNECTIONS; i++) {
1033 struct connection *pconn = &connections[i];
1034 if (!pconn->used) {
1035 connection_common_init(pconn);
1036 pconn->sock = new_sock;
1037 pconn->observer = FALSE;
1038 pconn->playing = NULL;
1039 pconn->capability[0] = '\0';
1040 pconn->access_level = access_level_for_next_connection();
1041 pconn->notify_of_writable_data = NULL;
1042 pconn->server.currently_processed_request_id = 0;
1043 pconn->server.last_request_id_seen = 0;
1044 pconn->server.auth_tries = 0;
1045 pconn->server.auth_settime = 0;
1046 pconn->server.status = AS_NOT_ESTABLISHED;
1047 pconn->server.ping_timers = timer_list_new_full(timer_destroy);
1048 pconn->server.granted_access_level = pconn->access_level;
1049 pconn->server.ignore_list =
1050 conn_pattern_list_new_full(conn_pattern_destroy);
1051 pconn->server.is_closing = FALSE;
1052 pconn->ping_time = -1.0;
1053 pconn->incoming_packet_notify = NULL;
1054 pconn->outgoing_packet_notify = NULL;
1056 sz_strlcpy(pconn->username, makeup_connection_name(&pconn->id));
1057 sz_strlcpy(pconn->addr, client_addr);
1058 sz_strlcpy(pconn->server.ipaddr, client_ip);
1060 conn_list_append(game.all_connections, pconn);
1062 log_verbose("connection (%s) from %s (%s)",
1063 pconn->username, pconn->addr, pconn->server.ipaddr);
1064 /* Give a ping timeout to send the PACKET_SERVER_JOIN_REQ, or close
1065 * the mute connection. This timer will be canceled into
1066 * connecthand.c:handle_login_request(). */
1067 timer = timer_new(TIMER_USER, TIMER_ACTIVE);
1068 timer_start(timer);
1069 timer_list_append(pconn->server.ping_timers, timer);
1070 return 0;
1074 log_error("maximum number of connections reached");
1075 fc_closesocket(new_sock);
1076 return -1;
1079 /********************************************************************
1080 open server socket to be used to accept client connections
1081 and open a server socket for server LAN announcements.
1082 ********************************************************************/
1083 int server_open_socket(void)
1085 /* setup socket address */
1086 union fc_sockaddr addr;
1087 #ifdef HAVE_IP_MREQN
1088 struct ip_mreqn mreq4;
1089 #else
1090 struct ip_mreq mreq4;
1091 #endif
1092 const char *cause, *group;
1093 int j, on, s;
1094 int lan_family;
1095 struct fc_sockaddr_list *list;
1096 int name_count;
1097 fc_errno eno = 0;
1098 union fc_sockaddr *problematic = NULL;
1100 #ifdef FREECIV_IPV6_SUPPORT
1101 struct ipv6_mreq mreq6;
1102 #endif
1104 log_verbose("Server attempting to listen on %s:%d",
1105 srvarg.bind_addr ? srvarg.bind_addr : "(any)",
1106 srvarg.port);
1108 /* Any supported family will do */
1109 list = net_lookup_service(srvarg.bind_addr, srvarg.port, FC_ADDR_ANY);
1111 name_count = fc_sockaddr_list_size(list);
1113 /* Lookup addresses to bind. */
1114 if (name_count <= 0) {
1115 log_fatal(_("Server: bad address: <%s:%d>."),
1116 srvarg.bind_addr ? srvarg.bind_addr : "(none)", srvarg.port);
1117 exit(EXIT_FAILURE);
1120 cause = "internal"; /* If cause is not overwritten but gets printed... */
1121 on = 1;
1123 /* Loop to create sockets, bind, listen. */
1124 listen_socks = fc_calloc(name_count, sizeof(listen_socks[0]));
1125 listen_count = 0;
1127 fc_sockaddr_list_iterate(list, paddr) {
1128 /* Create socket for client connections. */
1129 s = socket(paddr->saddr.sa_family, SOCK_STREAM, 0);
1130 if (s == -1) {
1131 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1132 * Kernel might have disabled AF_INET6. */
1133 eno = fc_get_errno();
1134 cause = "socket";
1135 problematic = paddr;
1136 continue;
1139 #ifndef FREECIV_HAVE_WINSOCK
1140 /* SO_REUSEADDR considered harmful on Win, necessary otherwise */
1141 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1142 (char *)&on, sizeof(on)) == -1) {
1143 log_error("setsockopt SO_REUSEADDR failed: %s",
1144 fc_strerror(fc_get_errno()));
1145 sockaddr_debug(paddr, LOG_NORMAL);
1147 #endif /* FREECIV_HAVE_WINSOCK */
1149 /* AF_INET6 sockets should use IPv6 only,
1150 * without stealing IPv4 from AF_INET sockets. */
1151 #ifdef FREECIV_IPV6_SUPPORT
1152 if (paddr->saddr.sa_family == AF_INET6) {
1153 #ifdef IPV6_V6ONLY
1154 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
1155 (char *)&on, sizeof(on)) == -1) {
1156 log_error("setsockopt IPV6_V6ONLY failed: %s",
1157 fc_strerror(fc_get_errno()));
1158 sockaddr_debug(paddr, LOG_DEBUG);
1160 #endif /* IPV6_V6ONLY */
1162 #endif /* IPv6 support */
1164 if (bind(s, &paddr->saddr, sockaddr_size(paddr)) == -1) {
1165 eno = fc_get_errno();
1166 cause = "bind";
1167 problematic = paddr;
1169 if (eno == EADDRNOTAVAIL) {
1170 /* Close only this socket. This address is not available.
1171 * This can happen with the IPv6 wildcard address if this
1172 * machine has no IPv6 interfaces. */
1173 /* If you change this logic, be sure to make clientside checking
1174 * of acceptable port to match. */
1175 fc_closesocket(s);
1176 continue;
1177 } else {
1178 /* Close all sockets. Another program might have bound to
1179 * one of our addresses, and might hijack some of our
1180 * connections. */
1181 fc_closesocket(s);
1182 for (j = 0; j < listen_count; j++) {
1183 fc_closesocket(listen_socks[j]);
1185 listen_count = 0;
1186 break;
1190 if (listen(s, MAX_NUM_CONNECTIONS) == -1) {
1191 eno = fc_get_errno();
1192 cause = "listen";
1193 problematic = paddr;
1194 fc_closesocket(s);
1195 continue;
1198 listen_socks[listen_count++] = s;
1199 } fc_sockaddr_list_iterate_end;
1201 if (listen_count == 0) {
1202 log_fatal("%s failure: %s (%d failed)", cause, fc_strerror(eno), name_count);
1203 if (problematic != NULL) {
1204 sockaddr_debug(problematic, LOG_NORMAL);
1206 fc_sockaddr_list_iterate(list, paddr) {
1207 /* Do not list already logged 'problematic' again */
1208 if (paddr != problematic) {
1209 sockaddr_debug(paddr, LOG_DEBUG);
1211 } fc_sockaddr_list_iterate_end;
1212 exit(EXIT_FAILURE);
1215 fc_sockaddr_list_destroy(list);
1217 connections_set_close_callback(server_conn_close_callback);
1219 if (srvarg.announce == ANNOUNCE_NONE) {
1220 return 0;
1223 #ifdef FREECIV_IPV6_SUPPORT
1224 if (srvarg.announce == ANNOUNCE_IPV6) {
1225 lan_family = AF_INET6;
1226 } else
1227 #endif /* IPV6 support */
1229 lan_family = AF_INET;
1232 /* Create socket for server LAN announcements */
1233 if ((socklan = socket(lan_family, SOCK_DGRAM, 0)) < 0) {
1234 log_error("Announcement socket failed: %s", fc_strerror(fc_get_errno()));
1235 return 0; /* FIXME: Should this cause hard error as exit(EXIT_FAILURE).
1236 * It's failure to do as commandline parameters requested after all */
1239 if (setsockopt(socklan, SOL_SOCKET, SO_REUSEADDR,
1240 (char *)&on, sizeof(on)) == -1) {
1241 log_error("SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1244 fc_nonblock(socklan);
1246 group = get_multicast_group(srvarg.announce == ANNOUNCE_IPV6);
1248 memset(&addr, 0, sizeof(addr));
1250 addr.saddr.sa_family = lan_family;
1252 #ifdef FREECIV_IPV6_SUPPORT
1253 if (addr.saddr.sa_family == AF_INET6) {
1254 addr.saddr_in6.sin6_family = AF_INET6;
1255 addr.saddr_in6.sin6_port = htons(SERVER_LAN_PORT);
1256 addr.saddr_in6.sin6_addr = in6addr_any;
1257 } else
1258 #endif /* IPv6 support */
1259 if (addr.saddr.sa_family == AF_INET) {
1260 addr.saddr_in4.sin_family = AF_INET;
1261 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT);
1262 addr.saddr_in4.sin_addr.s_addr = htonl(INADDR_ANY);
1263 } else {
1264 fc_assert(FALSE);
1266 log_error("Unsupported address family in server_open_socket()");
1269 if (bind(socklan, &addr.saddr, sockaddr_size(&addr)) < 0) {
1270 log_error("Announcement socket binding failed: %s", fc_strerror(fc_get_errno()));
1273 #ifndef FREECIV_IPV6_SUPPORT
1274 if (addr.saddr.sa_family == AF_INET) {
1275 #ifdef HAVE_INET_ATON
1276 inet_aton(group, &mreq4.imr_multiaddr);
1277 #else /* HAVE_INET_ATON */
1278 mreq4.imr_multiaddr.s_addr = inet_addr(group);
1279 #endif /* HAVE_INET_ATON */
1280 #else /* IPv6 support */
1281 if (addr.saddr.sa_family == AF_INET6) {
1282 inet_pton(AF_INET6, group, &mreq6.ipv6mr_multiaddr.s6_addr);
1283 mreq6.ipv6mr_interface = 0; /* TODO: Interface selection */
1284 if (setsockopt(socklan, IPPROTO_IPV6, FC_IPV6_ADD_MEMBERSHIP,
1285 (const char*)&mreq6, sizeof(mreq6)) < 0) {
1286 log_error("FC_IPV6_ADD_MEMBERSHIP (%s) failed: %s",
1287 group, fc_strerror(fc_get_errno()));
1289 } else if (addr.saddr.sa_family == AF_INET) {
1290 inet_pton(AF_INET, group, &mreq4.imr_multiaddr.s_addr);
1291 #endif /* IPv6 support */
1292 #ifdef HAVE_IP_MREQN
1293 mreq4.imr_address.s_addr = htonl(INADDR_ANY);
1294 mreq4.imr_ifindex = 0;
1295 #else
1296 mreq4.imr_interface.s_addr = htonl(INADDR_ANY);
1297 #endif
1299 if (setsockopt(socklan, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1300 (const char*)&mreq4, sizeof(mreq4)) < 0) {
1301 log_error("IP_ADD_MEMBERSHIP (%s) failed: %s",
1302 group, fc_strerror(fc_get_errno()));
1304 } else {
1305 fc_assert(FALSE);
1307 log_error("Unsupported address family for broadcasting.");
1310 return 0;
1314 /********************************************************************
1315 Initialize connection related stuff. Attention: Logging is not
1316 available within this functions!
1317 ********************************************************************/
1318 void init_connections(void)
1320 int i;
1322 game.all_connections = conn_list_new();
1323 game.est_connections = conn_list_new();
1324 game.glob_observers = conn_list_new();
1326 for(i=0; i<MAX_NUM_CONNECTIONS; i++) {
1327 struct connection *pconn = &connections[i];
1328 pconn->used = FALSE;
1329 pconn->self = conn_list_new();
1330 conn_list_prepend(pconn->self, pconn);
1332 #if defined(__VMS)
1334 unsigned long status;
1335 $DESCRIPTOR (tt_desc, "SYS$INPUT");
1336 status = sys$assign(&tt_desc,&tt_chan,0,0);
1337 if (!$VMS_STATUS_SUCCESS(status)) lib$stop(status);
1339 #endif /* VMS */
1342 /**************************************************************************
1343 Starts processing of request packet from client.
1344 **************************************************************************/
1345 static void start_processing_request(struct connection *pconn,
1346 int request_id)
1348 fc_assert_ret(request_id);
1349 fc_assert_ret(pconn->server.currently_processed_request_id == 0);
1350 log_debug("start processing packet %d from connection %d",
1351 request_id, pconn->id);
1352 conn_compression_freeze(pconn);
1353 send_packet_processing_started(pconn);
1354 pconn->server.currently_processed_request_id = request_id;
1357 /**************************************************************************
1358 Finish processing of request packet from client.
1359 **************************************************************************/
1360 static void finish_processing_request(struct connection *pconn)
1362 if (!pconn || !pconn->used) {
1363 return;
1365 fc_assert_ret(pconn->server.currently_processed_request_id);
1366 log_debug("finish processing packet %d from connection %d",
1367 pconn->server.currently_processed_request_id, pconn->id);
1368 send_packet_processing_finished(pconn);
1369 pconn->server.currently_processed_request_id = 0;
1370 conn_compression_thaw(pconn);
1373 /****************************************************************************
1374 Ping a connection.
1375 ****************************************************************************/
1376 static void connection_ping(struct connection *pconn)
1378 struct timer *timer = timer_new(TIMER_USER, TIMER_ACTIVE);
1380 log_debug("sending ping to %s (open=%d)", conn_description(pconn),
1381 timer_list_size(pconn->server.ping_timers));
1382 timer_start(timer);
1383 timer_list_append(pconn->server.ping_timers, timer);
1384 send_packet_conn_ping(pconn);
1387 /**************************************************************************
1388 Handle response to ping.
1389 **************************************************************************/
1390 void handle_conn_pong(struct connection *pconn)
1392 struct timer *timer;
1394 if (timer_list_size(pconn->server.ping_timers) == 0) {
1395 log_error("got unexpected pong from %s", conn_description(pconn));
1396 return;
1399 timer = timer_list_front(pconn->server.ping_timers);
1400 pconn->ping_time = timer_read_seconds(timer);
1401 timer_list_pop_front(pconn->server.ping_timers);
1402 log_debug("got pong from %s (open=%d); ping time = %fs",
1403 conn_description(pconn),
1404 timer_list_size(pconn->server.ping_timers), pconn->ping_time);
1407 /**************************************************************************
1408 Handle client's regular hearbeat
1409 **************************************************************************/
1410 void handle_client_heartbeat(struct connection *pconn)
1412 log_debug("Received heartbeat");
1415 /**************************************************************************
1416 Send ping time info about all connections to all connections.
1417 **************************************************************************/
1418 static void send_ping_times_to_all(void)
1420 struct packet_conn_ping_info packet;
1421 int i;
1423 i = 0;
1424 conn_list_iterate(game.est_connections, pconn) {
1425 if (!pconn->used) {
1426 continue;
1428 fc_assert(i < ARRAY_SIZE(packet.conn_id));
1429 packet.conn_id[i] = pconn->id;
1430 packet.ping_time[i] = pconn->ping_time;
1431 i++;
1432 } conn_list_iterate_end;
1433 packet.connections = i;
1435 lsend_packet_conn_ping_info(game.est_connections, &packet);
1438 /********************************************************************
1439 Listen for UDP packets multicasted from clients requesting
1440 announcement of servers on the LAN.
1441 ********************************************************************/
1442 static void get_lanserver_announcement(void)
1444 char msgbuf[128];
1445 struct data_in din;
1446 int type;
1447 fd_set readfs, exceptfs;
1448 struct timeval tv;
1450 if (srvarg.announce == ANNOUNCE_NONE) {
1451 return;
1454 FD_ZERO(&readfs);
1455 FD_ZERO(&exceptfs);
1456 FD_SET(socklan, &exceptfs);
1457 FD_SET(socklan, &readfs);
1459 tv.tv_sec = 0;
1460 tv.tv_usec = 0;
1462 while (fc_select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) {
1463 if (errno != EINTR) {
1464 log_error("select failed: %s", fc_strerror(fc_get_errno()));
1465 return;
1467 /* EINTR can happen sometimes, especially when compiling with -pg.
1468 * Generally we just want to run select again. */
1471 if (FD_ISSET(socklan, &readfs)) {
1472 if (0 < recvfrom(socklan, msgbuf, sizeof(msgbuf), 0, NULL, NULL)) {
1473 dio_input_init(&din, msgbuf, 1);
1474 dio_get_uint8(&din, &type);
1475 if (type == SERVER_LAN_VERSION) {
1476 log_debug("Received request for server LAN announcement.");
1477 send_lanserver_response();
1478 } else {
1479 log_debug("Received invalid request for server LAN announcement.");
1485 /********************************************************************
1486 This function broadcasts an UDP packet to clients with
1487 that requests information about the server state.
1488 ********************************************************************/
1489 static void send_lanserver_response(void)
1491 #ifndef FREECIV_HAVE_WINSOCK
1492 unsigned char buffer[MAX_LEN_PACKET];
1493 #else /* FREECIV_HAVE_WINSOCK */
1494 char buffer[MAX_LEN_PACKET];
1495 #endif /* FREECIV_HAVE_WINSOCK */
1496 char hostname[512];
1497 char port[256];
1498 char version[256];
1499 char players[256];
1500 int nhumans;
1501 char humans[256];
1502 char status[256];
1503 struct data_out dout;
1504 union fc_sockaddr addr;
1505 int socksend, setting = 1;
1506 const char *group;
1507 size_t size;
1508 #ifndef FREECIV_HAVE_WINSOCK
1509 unsigned char ttl;
1510 #endif
1512 /* Create a socket to broadcast to client. */
1513 if ((socksend = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1514 log_error("Lan response socket failed: %s", fc_strerror(fc_get_errno()));
1515 return;
1518 /* Set the UDP Multicast group IP address of the packet. */
1519 group = get_multicast_group(srvarg.announce == ANNOUNCE_IPV6);
1520 memset(&addr, 0, sizeof(addr));
1521 addr.saddr_in4.sin_family = AF_INET;
1522 addr.saddr_in4.sin_addr.s_addr = inet_addr(group);
1523 addr.saddr_in4.sin_port = htons(SERVER_LAN_PORT + 1);
1525 /* this setsockopt call fails on Windows 98, so we stick with the default
1526 * value of 1 on Windows, which should be fine in most cases */
1527 #ifndef FREECIV_HAVE_WINSOCK
1528 /* Set the Time-to-Live field for the packet. */
1529 ttl = SERVER_LAN_TTL;
1530 if (setsockopt(socksend, IPPROTO_IP, IP_MULTICAST_TTL,
1531 (const char*)&ttl, sizeof(ttl))) {
1532 log_error("setsockopt failed: %s", fc_strerror(fc_get_errno()));
1533 return;
1535 #endif /* FREECIV_HAVE_WINSOCK */
1537 if (setsockopt(socksend, SOL_SOCKET, SO_BROADCAST,
1538 (const char*)&setting, sizeof(setting))) {
1539 log_error("Lan response setsockopt failed: %s", fc_strerror(fc_get_errno()));
1540 return;
1543 /* Create a description of server state to send to clients. */
1544 if (srvarg.identity_name[0] != '\0') {
1545 sz_strlcpy(hostname, srvarg.identity_name);
1546 } else if (fc_gethostname(hostname, sizeof(hostname)) != 0) {
1547 sz_strlcpy(hostname, "none");
1550 fc_snprintf(version, sizeof(version), "%d.%d.%d%s",
1551 MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION, VERSION_LABEL);
1553 switch (server_state()) {
1554 case S_S_INITIAL:
1555 /* TRANS: Game state for local server */
1556 fc_snprintf(status, sizeof(status), _("Pregame"));
1557 break;
1558 case S_S_RUNNING:
1559 /* TRANS: Game state for local server */
1560 fc_snprintf(status, sizeof(status), _("Running"));
1561 break;
1562 case S_S_OVER:
1563 /* TRANS: Game state for local server */
1564 fc_snprintf(status, sizeof(status), _("Game over"));
1565 break;
1568 fc_snprintf(players, sizeof(players), "%d",
1569 normal_player_count());
1571 nhumans = 0;
1572 players_iterate(pplayer) {
1573 if (pplayer->is_alive && !pplayer->ai_controlled) {
1574 nhumans++;
1576 } players_iterate_end;
1577 fc_snprintf(humans, sizeof(humans), "%d", nhumans);
1579 fc_snprintf(port, sizeof(port), "%d",
1580 srvarg.port );
1582 dio_output_init(&dout, buffer, sizeof(buffer));
1583 dio_put_uint8(&dout, SERVER_LAN_VERSION);
1584 dio_put_string(&dout, hostname);
1585 dio_put_string(&dout, port);
1586 dio_put_string(&dout, version);
1587 dio_put_string(&dout, status);
1588 dio_put_string(&dout, players);
1589 dio_put_string(&dout, humans);
1590 dio_put_string(&dout, get_meta_message_string());
1591 size = dio_output_used(&dout);
1593 /* Sending packet to client with the information gathered above. */
1594 if (sendto(socksend, buffer, size, 0, &addr.saddr,
1595 sockaddr_size(&addr)) < 0) {
1596 log_error("landserver response sendto failed: %s",
1597 fc_strerror(fc_get_errno()));
1598 return;
1601 fc_closesocket(socksend);