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)
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 ***********************************************************************/
15 #include <fc_config.h>
18 #include "fc_prehdrs.h"
26 #ifdef FREECIV_HAVE_SYS_TYPES_H
27 #include <sys/types.h>
29 #ifdef HAVE_SYS_SOCKET_H
30 #include <sys/socket.h>
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
35 #ifdef HAVE_ARPA_INET_H
36 #include <arpa/inet.h>
44 #ifdef FREECIV_HAVE_LIBREADLINE
45 #include <readline/history.h>
46 #include <readline/readline.h>
48 #ifdef HAVE_SYS_SELECT_H
49 #include <sys/select.h>
51 #ifdef HAVE_SYS_TIME_H
62 #include "capability.h"
78 /* server/scripting */
79 #include "script_server.h"
84 #include "connecthand.h"
89 #include "stdinhand.h"
94 static struct connection connections
[MAX_NUM_CONNECTIONS
];
96 #ifdef GENERATING_MAC /* mac network globals */
97 TEndpointInfo serv_info
;
100 static int *listen_socks
;
101 static int listen_count
;
107 # define lib$stop LIB$STOP
108 # define sys$qiow SYS$QIOW
109 # define sys$assign SYS$ASSIGN
111 # include <descrip.h>
114 # include <starlet.h>
115 # include <lib$routines.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();
123 #define PROCESSING_TIME_STATISTICS 0
125 static int server_accept_connection(int sockfd
);
126 static void start_processing_request(struct connection
*pconn
,
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."));
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
)
180 handle_stdin_close(); /* maybe print an 'are you sure?' message? */
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
);
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
)
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
230 *****************************************************************************/
231 void close_connections_and_socket(void)
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
260 write_history(history_file
);
261 history_truncate_file(history_file
, HISTORY_LENGTH
);
266 #endif /* FREECIV_HAVE_LIBREADLINE */
268 send_server_info_to_metaserver(META_GOODBYE
);
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
;
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. */
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
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'
350 *****************************************************************************/
351 void flush_packets(void)
355 fd_set writefs
, exceptfs
;
362 tv
.tv_sec
= (game
.server
.netwait
- (time(NULL
) - start
));
368 FC_FD_ZERO(&writefs
);
369 FC_FD_ZERO(&exceptfs
);
372 for(i
=0; i
<MAX_NUM_CONNECTIONS
; i
++) {
373 struct connection
*pconn
= &connections
[i
];
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) {
387 if(fc_select(max_desc
+1, NULL
, &writefs
, &exceptfs
, &tv
)<=0) {
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"));
399 if(pconn
->send_buffer
&& pconn
->send_buffer
->ndata
> 0) {
400 if(FD_ISSET(pconn
->sock
, &writefs
)) {
401 flush_connection_send_buffer_all(pconn
);
403 cut_lagging_connection(pconn
);
412 struct packet_to_handle
{
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
;
440 while (get_packet(pconn
, &packet
)) {
443 #if PROCESSING_TIME_STATISTICS
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
);
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 */
472 connection_close_server(pconn
, _("rejected"));
476 #if PROCESSING_TIME_STATISTICS
477 timer_destroy(request_time
);
478 #endif /* PROCESSING_TIME_STATISTICS */
482 /*****************************************************************************
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)
496 fd_set readfs
, writefs
, exceptfs
;
498 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
504 #ifdef FREECIV_HAVE_LIBREADLINE
506 if (!no_input
&& !readline_initialized
) {
507 char *home_dir
= user_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
)) {
518 = fc_malloc(strlen(fc_dir
) + 1 + strlen(HISTORY_FILENAME
) + 1);
520 strcpy(history_file
, fc_dir
);
521 strcat(history_file
, "/");
522 strcat(history_file
, HISTORY_FILENAME
);
524 read_history(history_file
);
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 */
543 con_prompt_on(); /* accepting new input */
545 if (force_end_of_sniff
) {
546 force_end_of_sniff
= FALSE
;
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
;
559 if (conn_list_size(game
.est_connections
) > 0) {
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");
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. */
584 /* Do not restart before someone has connected and left again */
588 last_noplayers
= time(NULL
);
590 if (srvarg
.exit_on_end
) {
591 log_normal(_("Shutting down in %d seconds for lack of players."),
594 set_meta_message_string(N_("shutting down soon for lack of players"));
596 log_normal(_("Restarting in %d seconds for lack of players."),
599 set_meta_message_string(N_("restarting soon for lack of players"));
601 (void) send_server_info_to_metaserver(META_INFO
);
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
));
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) {
651 script_server_signal_emit("pulse", 0);
652 (void) send_server_info_to_metaserver(META_REFRESH
);
653 return S_E_END_OF_TURN_TIMEOUT
;
660 FC_FD_ZERO(&writefs
);
661 FC_FD_ZERO(&exceptfs
);
664 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
666 #else /* FREECIV_SOCKET_ZERO_NOT_STDIN */
670 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
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) {
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
)) {
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
);
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
)) {
734 if (ttchar
.numchars
) {
741 #ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
742 really_close_connections();
744 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
750 for (i
= 0; i
< listen_count
; i
++) {
751 if (FD_ISSET(listen_socks
[i
], &exceptfs
)) {
756 if (excepting
) { /* handle Ctrl-Z suspend/resume */
759 for (i
= 0; i
< listen_count
; 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
];
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();
801 #else /* !FREECIV_HAVE_LIBREADLINE */
803 char *buffer
= NULL
; /* Must be NULL when calling getline() */
809 didget
= getline(&buffer
, &len
, stdin
);
811 buffer
[didget
-1] = '\0'; /* overwrite newline character */
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
);
821 buffer
[didget
] = '\0';
823 didget
= -1; /* error or end-of-file: closing stdin... */
825 #endif /* HAVE_GETLINE */
827 handle_stdin_close();
830 con_prompt_enter(); /* will need a new prompt, regardless */
833 buf_internal
= local_to_internal_string_malloc(buffer
);
834 handle_stdin_input(NULL
, buf_internal
);
838 #endif /* !FREECIV_HAVE_LIBREADLINE */
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
;
848 || pconn
->server
.is_closing
849 || !FD_ISSET(pconn
->sock
, &readfs
)) {
853 nb
= read_socket_data(pconn
->sock
, pconn
->buffer
);
855 /* We read packets; now handle them. */
856 incoming_client_packets(pconn
);
857 } else if (-2 == nb
) {
858 connection_close_server(pconn
, _("client disconnected"));
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
];
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
);
875 cut_lagging_connection(pconn
);
879 really_close_connections();
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
];
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
)) {
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
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. */
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
;
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()));
965 #ifdef FREECIV_IPV6_SUPPORT
966 if (fromend
.saddr
.sa_family
== AF_INET6
) {
967 inet_ntop(AF_INET6
, &fromend
.saddr_in6
.sin6_addr
,
969 } else if (fromend
.saddr
.sa_family
== AF_INET
) {
970 inet_ntop(AF_INET
, &fromend
.saddr_in4
.sin_addr
, dst
, sizeof(dst
));
974 log_error("Unsupported address family in server_accept_connection()");
978 #else /* IPv6 support */
979 dst
= inet_ntoa(fromend
.saddr_in4
.sin_addr
);
980 #endif /* IPv6 support */
982 if (0 != game
.server
.maxconnectionsperhost
) {
985 conn_list_iterate(game
.all_connections
, pconn
) {
986 if (0 != strcmp(dst
, pconn
->server
.ipaddr
)) {
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
);
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
;
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
1024 ********************************************************************/
1025 int server_make_connection(int new_sock
, const char *client_addr
, const char *client_ip
)
1027 struct timer
*timer
;
1030 fc_nonblock(new_sock
);
1032 for(i
=0; i
<MAX_NUM_CONNECTIONS
; i
++) {
1033 struct connection
*pconn
= &connections
[i
];
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
);
1069 timer_list_append(pconn
->server
.ping_timers
, timer
);
1074 log_error("maximum number of connections reached");
1075 fc_closesocket(new_sock
);
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
;
1090 struct ip_mreq mreq4
;
1092 const char *cause
, *group
;
1095 struct fc_sockaddr_list
*list
;
1098 union fc_sockaddr
*problematic
= NULL
;
1100 #ifdef FREECIV_IPV6_SUPPORT
1101 struct ipv6_mreq mreq6
;
1104 log_verbose("Server attempting to listen on %s:%d",
1105 srvarg
.bind_addr
? srvarg
.bind_addr
: "(any)",
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
);
1120 cause
= "internal"; /* If cause is not overwritten but gets printed... */
1123 /* Loop to create sockets, bind, listen. */
1124 listen_socks
= fc_calloc(name_count
, sizeof(listen_socks
[0]));
1127 fc_sockaddr_list_iterate(list
, paddr
) {
1128 /* Create socket for client connections. */
1129 s
= socket(paddr
->saddr
.sa_family
, SOCK_STREAM
, 0);
1131 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1132 * Kernel might have disabled AF_INET6. */
1133 eno
= fc_get_errno();
1135 problematic
= paddr
;
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
) {
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();
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. */
1178 /* Close all sockets. Another program might have bound to
1179 * one of our addresses, and might hijack some of our
1182 for (j
= 0; j
< listen_count
; j
++) {
1183 fc_closesocket(listen_socks
[j
]);
1190 if (listen(s
, MAX_NUM_CONNECTIONS
) == -1) {
1191 eno
= fc_get_errno();
1193 problematic
= paddr
;
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
;
1215 fc_sockaddr_list_destroy(list
);
1217 connections_set_close_callback(server_conn_close_callback
);
1219 if (srvarg
.announce
== ANNOUNCE_NONE
) {
1223 #ifdef FREECIV_IPV6_SUPPORT
1224 if (srvarg
.announce
== ANNOUNCE_IPV6
) {
1225 lan_family
= AF_INET6
;
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
;
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
);
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;
1296 mreq4
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
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()));
1307 log_error("Unsupported address family for broadcasting.");
1314 /********************************************************************
1315 Initialize connection related stuff. Attention: Logging is not
1316 available within this functions!
1317 ********************************************************************/
1318 void init_connections(void)
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
);
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
);
1342 /**************************************************************************
1343 Starts processing of request packet from client.
1344 **************************************************************************/
1345 static void start_processing_request(struct connection
*pconn
,
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
) {
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 /****************************************************************************
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
));
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
));
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
;
1424 conn_list_iterate(game
.est_connections
, pconn
) {
1428 fc_assert(i
< ARRAY_SIZE(packet
.conn_id
));
1429 packet
.conn_id
[i
] = pconn
->id
;
1430 packet
.ping_time
[i
] = pconn
->ping_time
;
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)
1447 fd_set readfs
, exceptfs
;
1450 if (srvarg
.announce
== ANNOUNCE_NONE
) {
1456 FD_SET(socklan
, &exceptfs
);
1457 FD_SET(socklan
, &readfs
);
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()));
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();
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 */
1503 struct data_out dout
;
1504 union fc_sockaddr addr
;
1505 int socksend
, setting
= 1;
1508 #ifndef FREECIV_HAVE_WINSOCK
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()));
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()));
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()));
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()) {
1555 /* TRANS: Game state for local server */
1556 fc_snprintf(status
, sizeof(status
), _("Pregame"));
1559 /* TRANS: Game state for local server */
1560 fc_snprintf(status
, sizeof(status
), _("Running"));
1563 /* TRANS: Game state for local server */
1564 fc_snprintf(status
, sizeof(status
), _("Game over"));
1568 fc_snprintf(players
, sizeof(players
), "%d",
1569 normal_player_count());
1572 players_iterate(pplayer
) {
1573 if (pplayer
->is_alive
&& !pplayer
->ai_controlled
) {
1576 } players_iterate_end
;
1577 fc_snprintf(humans
, sizeof(humans
), "%d", nhumans
);
1579 fc_snprintf(port
, sizeof(port
), "%d",
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()));
1601 fc_closesocket(socksend
);