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
->client_gui
= GUI_STUB
;
222 pconn
->access_level
= ALLOW_NONE
;
223 connection_common_close(pconn
);
225 send_updated_vote_totals(NULL
);
228 /*****************************************************************************
229 Close all network stuff: connections, listening sockets, metaserver
231 *****************************************************************************/
232 void close_connections_and_socket(void)
236 lsend_packet_server_shutdown(game
.all_connections
);
238 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
239 if (connections
[i
].used
) {
240 close_connection(&connections
[i
]);
242 conn_list_destroy(connections
[i
].self
);
245 /* Remove the game connection lists and make sure they are empty. */
246 conn_list_destroy(game
.glob_observers
);
247 conn_list_destroy(game
.all_connections
);
248 conn_list_destroy(game
.est_connections
);
250 for (i
= 0; i
< listen_count
; i
++) {
251 fc_closesocket(listen_socks
[i
]);
253 FC_FREE(listen_socks
);
255 if (srvarg
.announce
!= ANNOUNCE_NONE
) {
256 fc_closesocket(socklan
);
259 #ifdef FREECIV_HAVE_LIBREADLINE
261 write_history(history_file
);
262 history_truncate_file(history_file
, HISTORY_LENGTH
);
267 #endif /* FREECIV_HAVE_LIBREADLINE */
269 send_server_info_to_metaserver(META_GOODBYE
);
273 fc_shutdown_network();
276 /****************************************************************************
277 Now really close connections marked as 'is_closing'.
278 Do this here to avoid recursive sending.
279 ****************************************************************************/
280 static void really_close_connections(void)
282 struct connection
*closing
[MAX_NUM_CONNECTIONS
];
283 struct connection
*pconn
;
289 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
290 pconn
= connections
+ i
;
291 if (pconn
->used
&& pconn
->server
.is_closing
) {
292 closing
[num
++] = pconn
;
293 /* Remove closing connections from the lists (hard detach)
294 * to avoid sending to closing connections. */
295 conn_list_remove(game
.glob_observers
, pconn
);
296 conn_list_remove(game
.est_connections
, pconn
);
297 conn_list_remove(game
.all_connections
, pconn
);
298 if (NULL
!= conn_get_player(pconn
)) {
299 conn_list_remove(conn_get_player(pconn
)->connections
, pconn
);
304 for (i
= 0; i
< num
; i
++) {
305 /* Now really close them. */
307 lost_connection_to_client(pconn
);
308 close_connection(pconn
);
310 } while (0 < num
); /* May some errors occurred, let's check. */
313 /****************************************************************************
314 Break a client connection. You should almost always use
315 connection_close_server() instead of calling this function directly.
316 ****************************************************************************/
317 static void server_conn_close_callback(struct connection
*pconn
)
319 /* Do as little as possible here to avoid recursive evil. */
320 pconn
->server
.is_closing
= TRUE
;
323 /****************************************************************************
324 If a connection lags too much this function is called and we try to cut
326 ****************************************************************************/
327 static void cut_lagging_connection(struct connection
*pconn
)
329 if (!pconn
->server
.is_closing
330 && game
.server
.tcptimeout
!= 0
332 && conn_list_size(game
.all_connections
) > 1
333 && pconn
->access_level
!= ALLOW_HACK
334 && timer_read_seconds(pconn
->last_write
) > game
.server
.tcptimeout
) {
335 /* Cut the connections to players who lag too much. This
336 * usually happens because client animation slows the client
337 * too much and it can't keep up with the server. We don't
338 * cut HACK connections, or cut in single-player games, since
339 * it wouldn't help the game progress. For other connections
340 * the best thing to do when they lag too much is to be
341 * disconnected and reconnect. */
342 log_verbose("connection (%s) cut due to lagging player",
343 conn_description(pconn
));
344 connection_close_server(pconn
, _("lagging connection"));
348 /****************************************************************************
349 Attempt to flush all information in the send buffers for upto 'netwait'
351 *****************************************************************************/
352 void flush_packets(void)
356 fd_set writefs
, exceptfs
;
363 tv
.tv_sec
= (game
.server
.netwait
- (time(NULL
) - start
));
370 FC_FD_ZERO(&writefs
);
371 FC_FD_ZERO(&exceptfs
);
374 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
375 struct connection
*pconn
= &connections
[i
];
378 && !pconn
->server
.is_closing
379 && 0 < pconn
->send_buffer
->ndata
) {
380 FD_SET(pconn
->sock
, &writefs
);
381 FD_SET(pconn
->sock
, &exceptfs
);
382 max_desc
= MAX(pconn
->sock
, max_desc
);
386 if (max_desc
== -1) {
390 if (fc_select(max_desc
+ 1, NULL
, &writefs
, &exceptfs
, &tv
) <= 0) {
394 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) { /* check for freaky players */
395 struct connection
*pconn
= &connections
[i
];
397 if (pconn
->used
&& !pconn
->server
.is_closing
) {
398 if (FD_ISSET(pconn
->sock
, &exceptfs
)) {
399 log_verbose("connection (%s) cut due to exception data",
400 conn_description(pconn
));
401 connection_close_server(pconn
, _("network exception"));
403 if (pconn
->send_buffer
&& pconn
->send_buffer
->ndata
> 0) {
404 if (FD_ISSET(pconn
->sock
, &writefs
)) {
405 flush_connection_send_buffer_all(pconn
);
407 cut_lagging_connection(pconn
);
416 struct packet_to_handle
{
418 enum packet_type type
;
421 /*****************************************************************************
422 Simplify a loop by wrapping get_packet_from_connection.
423 *****************************************************************************/
424 static bool get_packet(struct connection
*pconn
,
425 struct packet_to_handle
*ppacket
)
427 ppacket
->data
= get_packet_from_connection(pconn
, &ppacket
->type
);
429 return NULL
!= ppacket
->data
;
432 /*****************************************************************************
433 Handle all incoming packets on a client connection.
434 Precondition - we have read_socket_data.
435 Postcondition - there are no more packets to handle on this connection.
436 *****************************************************************************/
437 static void incoming_client_packets(struct connection
*pconn
)
439 struct packet_to_handle packet
;
440 #if PROCESSING_TIME_STATISTICS
441 struct timer
*request_time
= NULL
;
444 while (get_packet(pconn
, &packet
)) {
447 #if PROCESSING_TIME_STATISTICS
450 request_time
= timer_renew(request_time
, TIMER_USER
, TIMER_ACTIVE
);
451 timer_start(request_time
);
452 #endif /* PROCESSING_TIME_STATISTICS */
454 pconn
->server
.last_request_id_seen
455 = get_next_request_id(pconn
->server
.last_request_id_seen
);
457 #if PROCESSING_TIME_STATISTICS
458 request_id
= pconn
->server
.last_request_id_seen
;
459 #endif /* PROCESSING_TIME_STATISTICS */
461 connection_do_buffer(pconn
);
462 start_processing_request(pconn
, pconn
->server
.last_request_id_seen
);
464 command_ok
= server_packet_input(pconn
, packet
.data
, packet
.type
);
467 finish_processing_request(pconn
);
468 connection_do_unbuffer(pconn
);
470 #if PROCESSING_TIME_STATISTICS
471 log_verbose("processed request %d in %gms", request_id
,
472 timer_read_seconds(request_time
) * 1000.0);
473 #endif /* PROCESSING_TIME_STATISTICS */
476 connection_close_server(pconn
, _("rejected"));
480 #if PROCESSING_TIME_STATISTICS
481 timer_destroy(request_time
);
482 #endif /* PROCESSING_TIME_STATISTICS */
486 /*****************************************************************************
489 - input from connections,
490 - input from server operator in stdin
492 This function also handles prompt printing, via the con_prompt_*
493 functions. That is, other functions should not need to do so. --dwp
494 *****************************************************************************/
495 enum server_events
server_sniff_all_input(void)
500 fd_set readfs
, writefs
, exceptfs
;
502 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
508 #ifdef FREECIV_HAVE_LIBREADLINE
510 if (!no_input
&& !readline_initialized
) {
511 char *storage_dir
= freeciv_storage_dir();
513 if (storage_dir
!= NULL
) {
514 int fcdl
= strlen(storage_dir
) + 1;
515 char *fc_dir
= fc_malloc(fcdl
);
517 if (fc_dir
!= NULL
) {
518 fc_snprintf(fc_dir
, fcdl
, "%s", storage_dir
);
520 if (make_dir(fc_dir
)) {
522 = fc_malloc(strlen(fc_dir
) + 1 + strlen(HISTORY_FILENAME
) + 1);
524 strcpy(history_file
, fc_dir
);
525 strcat(history_file
, "/");
526 strcat(history_file
, HISTORY_FILENAME
);
528 read_history(history_file
);
536 rl_callback_handler_install((char *) "> ",
537 handle_readline_input_callback
);
538 rl_attempted_completion_function
= freeciv_completion
;
540 readline_initialized
= TRUE
;
541 atexit(rl_callback_handler_remove
);
544 #endif /* FREECIV_HAVE_LIBREADLINE */
547 con_prompt_on(); /* accepting new input */
549 if (force_end_of_sniff
) {
550 force_end_of_sniff
= FALSE
;
552 return S_E_FORCE_END_OF_SNIFF
;
555 get_lanserver_announcement();
557 /* end server if no players for 'srvarg.quitidle' seconds,
558 * but only if at least one player has previously connected. */
559 if (srvarg
.quitidle
!= 0) {
560 static time_t last_noplayers
;
563 if (conn_list_size(game
.est_connections
) > 0) {
566 if (conns
&& conn_list_size(game
.est_connections
) == 0) {
567 if (last_noplayers
!= 0) {
568 if (time(NULL
) > last_noplayers
+ srvarg
.quitidle
) {
569 save_game_auto("Lost all connections", AS_QUITIDLE
);
571 if (srvarg
.exit_on_end
) {
572 log_normal(_("Shutting down for lack of players."));
573 set_meta_message_string("shutting down for lack of players");
575 log_normal(_("Restarting for lack of players."));
576 set_meta_message_string("restarting for lack of players");
578 (void) send_server_info_to_metaserver(META_INFO
);
580 set_server_state(S_S_OVER
);
581 force_end_of_sniff
= TRUE
;
583 if (srvarg
.exit_on_end
) {
584 /* No need for anything more; just quit. */
588 /* Do not restart before someone has connected and left again */
592 last_noplayers
= time(NULL
);
594 if (srvarg
.exit_on_end
) {
595 log_normal(_("Shutting down in %d seconds for lack of players."),
598 set_meta_message_string(N_("shutting down soon for lack of players"));
600 log_normal(_("Restarting in %d seconds for lack of players."),
603 set_meta_message_string(N_("restarting soon for lack of players"));
605 (void) send_server_info_to_metaserver(META_INFO
);
612 /* Pinging around for statistics */
613 if (time(NULL
) > (game
.server
.last_ping
+ game
.server
.pingtime
)) {
614 /* send data about the previous run */
615 send_ping_times_to_all();
617 conn_list_iterate(game
.all_connections
, pconn
) {
618 if ((!pconn
->server
.is_closing
619 && 0 < timer_list_size(pconn
->server
.ping_timers
)
620 && timer_read_seconds(timer_list_front
621 (pconn
->server
.ping_timers
))
622 > game
.server
.pingtimeout
)
623 || pconn
->ping_time
> game
.server
.pingtimeout
) {
624 /* cut mute players, except for hack-level ones */
625 if (pconn
->access_level
== ALLOW_HACK
) {
626 log_verbose("connection (%s) [hack-level] ping timeout ignored",
627 conn_description(pconn
));
629 log_verbose("connection (%s) cut due to ping timeout",
630 conn_description(pconn
));
631 connection_close_server(pconn
, _("ping timeout"));
633 } else if (pconn
->established
) {
634 /* We don't send ping to connection not established, because
635 * we wouldn't be able to handle asynchronous ping/pong with
636 * different packet header size. */
637 connection_ping(pconn
);
639 } conn_list_iterate_end
;
640 game
.server
.last_ping
= time(NULL
);
643 /* if we've waited long enough after a failure, respond to the client */
644 conn_list_iterate(game
.all_connections
, pconn
) {
645 if (srvarg
.auth_enabled
646 && !pconn
->server
.is_closing
647 && pconn
->server
.status
!= AS_ESTABLISHED
) {
648 auth_process_status(pconn
);
650 } conn_list_iterate_end
652 /* Don't wait if timeout == -1 (i.e. on auto games) */
653 if (S_S_RUNNING
== server_state() && game
.info
.timeout
== -1) {
655 script_server_signal_emit("pulse", 0);
656 (void) send_server_info_to_metaserver(META_REFRESH
);
657 return S_E_END_OF_TURN_TIMEOUT
;
664 FC_FD_ZERO(&writefs
);
665 FC_FD_ZERO(&exceptfs
);
668 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
670 #else /* FREECIV_SOCKET_ZERO_NOT_STDIN */
674 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
678 for (i
= 0; i
< listen_count
; i
++) {
679 FD_SET(listen_socks
[i
], &readfs
);
680 FD_SET(listen_socks
[i
], &exceptfs
);
681 max_desc
= MAX(max_desc
, listen_socks
[i
]);
684 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
685 struct connection
*pconn
= connections
+ i
;
687 if (pconn
->used
&& !pconn
->server
.is_closing
) {
688 FD_SET(pconn
->sock
, &readfs
);
689 if (0 < pconn
->send_buffer
->ndata
) {
690 FD_SET(pconn
->sock
, &writefs
);
692 FD_SET(pconn
->sock
, &exceptfs
);
693 max_desc
= MAX(pconn
->sock
, max_desc
);
696 con_prompt_off(); /* output doesn't generate a new prompt */
698 if (fc_select(max_desc
+ 1, &readfs
, &writefs
, &exceptfs
, &tv
) == 0) {
701 script_server_signal_emit("pulse", 0);
702 (void) send_server_info_to_metaserver(META_REFRESH
);
703 if (current_turn_timeout() > 0
704 && S_S_RUNNING
== server_state()
705 && game
.server
.phase_timer
706 && (timer_read_seconds(game
.server
.phase_timer
)
707 > game
.tinfo
.seconds_to_phasedone
)) {
709 return S_E_END_OF_TURN_TIMEOUT
;
711 if ((game
.server
.autosaves
& (1 << AS_TIMER
))
712 && S_S_RUNNING
== server_state()
713 && (timer_read_seconds(game
.server
.save_timer
)
714 >= game
.server
.save_frequency
* 60)) {
715 save_game_auto("Timer", AS_TIMER
);
716 game
.server
.save_timer
= timer_renew(game
.server
.save_timer
,
717 TIMER_USER
, TIMER_ACTIVE
);
718 timer_start(game
.server
.save_timer
);
730 unsigned long status
;
732 status
= sys$
qiow(EFN$C_ENF
, tt_chan
,
733 IO$_SENSEMODE
| IO$M_TYPEAHDCNT
, 0, 0, 0,
734 &ttchar
, sizeof(ttchar
), 0, 0, 0, 0);
735 if (!$
VMS_STATUS_SUCCESS(status
)) {
738 if (ttchar
.numchars
) {
745 #ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
746 really_close_connections();
748 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
754 for (i
= 0; i
< listen_count
; i
++) {
755 if (FD_ISSET(listen_socks
[i
], &exceptfs
)) {
760 if (excepting
) { /* handle Ctrl-Z suspend/resume */
763 for (i
= 0; i
< listen_count
; i
++) {
765 if (FD_ISSET(s
, &readfs
)) { /* new players connects */
766 log_verbose("got new connection");
767 if (-1 == server_accept_connection(s
)) {
768 /* There will be a log_error() message from
769 * server_accept_connection() if something
770 * goes wrong, so no need to make another
771 * error-level message here. */
772 log_verbose("failed accepting connection");
776 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
777 /* check for freaky players */
778 struct connection
*pconn
= &connections
[i
];
781 && !pconn
->server
.is_closing
782 && FD_ISSET(pconn
->sock
, &exceptfs
)) {
783 log_verbose("connection (%s) cut due to exception data",
784 conn_description(pconn
));
785 connection_close_server(pconn
, _("network exception"));
788 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
789 if (!no_input
&& (bufptr
= fc_read_console())) {
790 char *bufptr_internal
= local_to_internal_string_malloc(bufptr
);
792 con_prompt_enter(); /* will need a new prompt, regardless */
793 handle_stdin_input(NULL
, bufptr_internal
);
794 free(bufptr_internal
);
796 #else /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
797 if (!no_input
&& FD_ISSET(0, &readfs
)) { /* input from server operator */
798 #ifdef FREECIV_HAVE_LIBREADLINE
799 rl_callback_read_char();
800 if (readline_handled_input
) {
801 readline_handled_input
= FALSE
;
802 con_prompt_enter_clear();
805 #else /* !FREECIV_HAVE_LIBREADLINE */
807 char *buffer
= NULL
; /* Must be NULL when calling getline() */
813 didget
= getline(&buffer
, &len
, stdin
);
815 buffer
[didget
-1] = '\0'; /* overwrite newline character */
817 log_debug("Got line: \"%s\" (%ld, %ld)", buffer
,
818 (long int) didget
, (long int) len
);
820 #else /* HAVE_GETLINE */
821 buffer
= malloc(BUF_SIZE
+ 1);
823 didget
= read(0, buffer
, BUF_SIZE
);
825 buffer
[didget
] = '\0';
827 didget
= -1; /* error or end-of-file: closing stdin... */
829 #endif /* HAVE_GETLINE */
831 handle_stdin_close();
834 con_prompt_enter(); /* will need a new prompt, regardless */
837 buf_internal
= local_to_internal_string_malloc(buffer
);
838 handle_stdin_input(NULL
, buf_internal
);
842 #endif /* !FREECIV_HAVE_LIBREADLINE */
844 #endif /* !FREECIV_SOCKET_ZERO_NOT_STDIN */
846 { /* input from a player */
847 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
848 struct connection
*pconn
= connections
+ i
;
852 || pconn
->server
.is_closing
853 || !FD_ISSET(pconn
->sock
, &readfs
)) {
857 nb
= read_socket_data(pconn
->sock
, pconn
->buffer
);
859 /* We read packets; now handle them. */
860 incoming_client_packets(pconn
);
861 } else if (-2 == nb
) {
862 connection_close_server(pconn
, _("client disconnected"));
864 /* Read failure; the connection is closed. */
865 connection_close_server(pconn
, _("read error"));
869 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
870 struct connection
*pconn
= &connections
[i
];
873 && !pconn
->server
.is_closing
874 && pconn
->send_buffer
875 && pconn
->send_buffer
->ndata
> 0) {
876 if (FD_ISSET(pconn
->sock
, &writefs
)) {
877 flush_connection_send_buffer_all(pconn
);
879 cut_lagging_connection(pconn
);
883 really_close_connections();
890 script_server_signal_emit("pulse", 0);
892 if (current_turn_timeout() > 0
893 && S_S_RUNNING
== server_state()
894 && game
.server
.phase_timer
895 && (timer_read_seconds(game
.server
.phase_timer
)
896 > game
.tinfo
.seconds_to_phasedone
)) {
897 return S_E_END_OF_TURN_TIMEOUT
;
899 if ((game
.server
.autosaves
& (1 << AS_TIMER
))
900 && S_S_RUNNING
== server_state()
901 && (timer_read_seconds(game
.server
.save_timer
)
902 >= game
.server
.save_frequency
* 60)) {
903 save_game_auto("Timer", AS_TIMER
);
904 game
.server
.save_timer
= timer_renew(game
.server
.save_timer
,
905 TIMER_USER
, TIMER_ACTIVE
);
906 timer_start(game
.server
.save_timer
);
909 return S_E_OTHERWISE
;
912 /********************************************************************
913 Make up a name for the connection, before we get any data from
914 it to use as a sensible name. Name will be 'c' + integer,
915 guaranteed not to be the same as any other connection name,
916 nor player name nor user name, nor connection id (avoid possible
917 confusions). Returns pointer to static buffer, and fills in
918 (*id) with chosen value.
919 ********************************************************************/
920 static const char *makeup_connection_name(int *id
)
922 static unsigned short i
= 0;
923 static char name
[MAX_LEN_NAME
];
926 if (i
== (unsigned short) - 1) {
930 fc_snprintf(name
, sizeof(name
), "c%u", (unsigned int)++i
);
931 if (NULL
== player_by_name(name
)
932 && NULL
== player_by_user(name
)
933 && NULL
== conn_by_number(i
)
934 && NULL
== conn_by_user(name
)) {
941 /********************************************************************
942 Server accepts connection from client:
943 Low level socket stuff, and basic-initialize the connection struct.
944 Returns 0 on success, -1 on failure (bad accept(), or too many
946 ********************************************************************/
947 static int server_accept_connection(int sockfd
)
949 /* This used to have size_t for some platforms. If this is necessary
950 * it should be done with a configure check not a platform check. */
954 union fc_sockaddr fromend
;
955 bool nameinfo
= FALSE
;
956 #ifdef FREECIV_IPV6_SUPPORT
957 char host
[NI_MAXHOST
], service
[NI_MAXSERV
];
958 char dst
[INET6_ADDRSTRLEN
];
959 #else /* IPv6 support */
960 struct hostent
*from
;
961 const char *host
= NULL
;
963 #endif /* IPv6 support */
965 fromlen
= sizeof(fromend
);
967 if ((new_sock
= accept(sockfd
, &fromend
.saddr
, &fromlen
)) == -1) {
968 log_error("accept failed: %s", fc_strerror(fc_get_errno()));
972 #ifdef FREECIV_IPV6_SUPPORT
973 if (fromend
.saddr
.sa_family
== AF_INET6
) {
974 inet_ntop(AF_INET6
, &fromend
.saddr_in6
.sin6_addr
,
976 } else if (fromend
.saddr
.sa_family
== AF_INET
) {
977 inet_ntop(AF_INET
, &fromend
.saddr_in4
.sin_addr
, dst
, sizeof(dst
));
981 log_error("Unsupported address family in server_accept_connection()");
985 #else /* IPv6 support */
986 dst
= inet_ntoa(fromend
.saddr_in4
.sin_addr
);
987 #endif /* IPv6 support */
989 if (0 != game
.server
.maxconnectionsperhost
) {
992 conn_list_iterate(game
.all_connections
, pconn
) {
993 if (0 != strcmp(dst
, pconn
->server
.ipaddr
)) {
996 if (++count
>= game
.server
.maxconnectionsperhost
) {
997 log_verbose("Rejecting new connection from %s: maximum number of "
998 "connections for this address exceeded (%d).",
999 dst
, game
.server
.maxconnectionsperhost
);
1001 /* Disconnect the accepted socket. */
1002 fc_closesocket(new_sock
);
1006 } conn_list_iterate_end
;
1009 #ifdef FREECIV_IPV6_SUPPORT
1010 nameinfo
= (0 == getnameinfo(&fromend
.saddr
, fromlen
, host
, NI_MAXHOST
,
1011 service
, NI_MAXSERV
, NI_NUMERICSERV
)
1012 && '\0' != host
[0]);
1013 #else /* IPv6 support */
1014 from
= gethostbyaddr((char *) &fromend
.saddr_in4
.sin_addr
,
1015 sizeof(fromend
.saddr_in4
.sin_addr
), AF_INET
);
1016 if (NULL
!= from
&& '\0' != from
->h_name
[0]) {
1017 host
= from
->h_name
;
1020 #endif /* IPv6 support */
1022 return server_make_connection(new_sock
,
1023 (nameinfo
? host
: dst
), dst
);
1026 /********************************************************************
1027 Server accepts connection from client:
1028 Low level socket stuff, and basic-initialize the connection struct.
1029 Returns 0 on success, -1 on failure (bad accept(), or too many
1031 ********************************************************************/
1032 int server_make_connection(int new_sock
, const char *client_addr
,
1033 const char *client_ip
)
1035 struct timer
*timer
;
1038 fc_nonblock(new_sock
);
1040 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
1041 struct connection
*pconn
= &connections
[i
];
1044 connection_common_init(pconn
);
1045 pconn
->sock
= new_sock
;
1046 pconn
->observer
= FALSE
;
1047 pconn
->playing
= NULL
;
1048 pconn
->capability
[0] = '\0';
1049 pconn
->access_level
= access_level_for_next_connection();
1050 pconn
->notify_of_writable_data
= NULL
;
1051 pconn
->server
.currently_processed_request_id
= 0;
1052 pconn
->server
.last_request_id_seen
= 0;
1053 pconn
->server
.auth_tries
= 0;
1054 pconn
->server
.auth_settime
= 0;
1055 pconn
->server
.status
= AS_NOT_ESTABLISHED
;
1056 pconn
->server
.ping_timers
= timer_list_new_full(timer_destroy
);
1057 pconn
->server
.granted_access_level
= pconn
->access_level
;
1058 pconn
->server
.ignore_list
=
1059 conn_pattern_list_new_full(conn_pattern_destroy
);
1060 pconn
->server
.is_closing
= FALSE
;
1061 pconn
->ping_time
= -1.0;
1062 pconn
->incoming_packet_notify
= NULL
;
1063 pconn
->outgoing_packet_notify
= NULL
;
1065 sz_strlcpy(pconn
->username
, makeup_connection_name(&pconn
->id
));
1066 sz_strlcpy(pconn
->addr
, client_addr
);
1067 sz_strlcpy(pconn
->server
.ipaddr
, client_ip
);
1069 conn_list_append(game
.all_connections
, pconn
);
1071 log_verbose("connection (%s) from %s (%s)",
1072 pconn
->username
, pconn
->addr
, pconn
->server
.ipaddr
);
1073 /* Give a ping timeout to send the PACKET_SERVER_JOIN_REQ, or close
1074 * the mute connection. This timer will be canceled into
1075 * connecthand.c:handle_login_request(). */
1076 timer
= timer_new(TIMER_USER
, TIMER_ACTIVE
);
1078 timer_list_append(pconn
->server
.ping_timers
, timer
);
1083 log_error("maximum number of connections reached");
1084 fc_closesocket(new_sock
);
1088 /********************************************************************
1089 Open server socket to be used to accept client connections
1090 and open a server socket for server LAN announcements.
1091 ********************************************************************/
1092 int server_open_socket(void)
1094 /* setup socket address */
1095 union fc_sockaddr addr
;
1096 #ifdef HAVE_IP_MREQN
1097 struct ip_mreqn mreq4
;
1099 struct ip_mreq mreq4
;
1101 const char *cause
, *group
;
1104 struct fc_sockaddr_list
*list
;
1107 union fc_sockaddr
*problematic
= NULL
;
1109 #ifdef FREECIV_IPV6_SUPPORT
1110 struct ipv6_mreq mreq6
;
1113 log_verbose("Server attempting to listen on %s:%d",
1114 srvarg
.bind_addr
? srvarg
.bind_addr
: "(any)",
1117 /* Any supported family will do */
1118 list
= net_lookup_service(srvarg
.bind_addr
, srvarg
.port
, FC_ADDR_ANY
);
1120 name_count
= fc_sockaddr_list_size(list
);
1122 /* Lookup addresses to bind. */
1123 if (name_count
<= 0) {
1124 log_fatal(_("Server: bad address: <%s:%d>."),
1125 srvarg
.bind_addr
? srvarg
.bind_addr
: "(none)", srvarg
.port
);
1129 cause
= "internal"; /* If cause is not overwritten but gets printed... */
1132 /* Loop to create sockets, bind, listen. */
1133 listen_socks
= fc_calloc(name_count
, sizeof(listen_socks
[0]));
1136 fc_sockaddr_list_iterate(list
, paddr
) {
1137 /* Create socket for client connections. */
1138 s
= socket(paddr
->saddr
.sa_family
, SOCK_STREAM
, 0);
1140 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT.
1141 * Kernel might have disabled AF_INET6. */
1142 eno
= fc_get_errno();
1144 problematic
= paddr
;
1148 #ifndef FREECIV_HAVE_WINSOCK
1149 /* SO_REUSEADDR considered harmful on Win, necessary otherwise */
1150 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
,
1151 (char *)&on
, sizeof(on
)) == -1) {
1152 log_error("setsockopt SO_REUSEADDR failed: %s",
1153 fc_strerror(fc_get_errno()));
1154 sockaddr_debug(paddr
, LOG_NORMAL
);
1156 #endif /* FREECIV_HAVE_WINSOCK */
1158 /* AF_INET6 sockets should use IPv6 only,
1159 * without stealing IPv4 from AF_INET sockets. */
1160 #ifdef FREECIV_IPV6_SUPPORT
1161 if (paddr
->saddr
.sa_family
== AF_INET6
) {
1163 if (setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1164 (char *)&on
, sizeof(on
)) == -1) {
1165 log_error("setsockopt IPV6_V6ONLY failed: %s",
1166 fc_strerror(fc_get_errno()));
1167 sockaddr_debug(paddr
, LOG_DEBUG
);
1169 #endif /* IPV6_V6ONLY */
1171 #endif /* IPv6 support */
1173 if (bind(s
, &paddr
->saddr
, sockaddr_size(paddr
)) == -1) {
1174 eno
= fc_get_errno();
1176 problematic
= paddr
;
1178 if (eno
== EADDRNOTAVAIL
) {
1179 /* Close only this socket. This address is not available.
1180 * This can happen with the IPv6 wildcard address if this
1181 * machine has no IPv6 interfaces. */
1182 /* If you change this logic, be sure to make clientside checking
1183 * of acceptable port to match. */
1187 /* Close all sockets. Another program might have bound to
1188 * one of our addresses, and might hijack some of our
1191 for (j
= 0; j
< listen_count
; j
++) {
1192 fc_closesocket(listen_socks
[j
]);
1199 if (listen(s
, MAX_NUM_CONNECTIONS
) == -1) {
1200 eno
= fc_get_errno();
1202 problematic
= paddr
;
1207 listen_socks
[listen_count
++] = s
;
1208 } fc_sockaddr_list_iterate_end
;
1210 if (listen_count
== 0) {
1211 log_fatal("%s failure: %s (%d failed)", cause
, fc_strerror(eno
), name_count
);
1212 if (problematic
!= NULL
) {
1213 sockaddr_debug(problematic
, LOG_NORMAL
);
1215 fc_sockaddr_list_iterate(list
, paddr
) {
1216 /* Do not list already logged 'problematic' again */
1217 if (paddr
!= problematic
) {
1218 sockaddr_debug(paddr
, LOG_DEBUG
);
1220 } fc_sockaddr_list_iterate_end
;
1224 fc_sockaddr_list_destroy(list
);
1226 connections_set_close_callback(server_conn_close_callback
);
1228 if (srvarg
.announce
== ANNOUNCE_NONE
) {
1232 #ifdef FREECIV_IPV6_SUPPORT
1233 if (srvarg
.announce
== ANNOUNCE_IPV6
) {
1234 lan_family
= AF_INET6
;
1236 #endif /* IPV6 support */
1238 lan_family
= AF_INET
;
1241 /* Create socket for server LAN announcements */
1242 if ((socklan
= socket(lan_family
, SOCK_DGRAM
, 0)) < 0) {
1243 log_error("Announcement socket failed: %s", fc_strerror(fc_get_errno()));
1244 return 0; /* FIXME: Should this cause hard error as exit(EXIT_FAILURE).
1245 * It's failure to do as commandline parameters requested after all */
1248 if (setsockopt(socklan
, SOL_SOCKET
, SO_REUSEADDR
,
1249 (char *)&on
, sizeof(on
)) == -1) {
1250 log_error("SO_REUSEADDR failed: %s", fc_strerror(fc_get_errno()));
1253 fc_nonblock(socklan
);
1255 group
= get_multicast_group(srvarg
.announce
== ANNOUNCE_IPV6
);
1257 memset(&addr
, 0, sizeof(addr
));
1259 addr
.saddr
.sa_family
= lan_family
;
1261 #ifdef FREECIV_IPV6_SUPPORT
1262 if (addr
.saddr
.sa_family
== AF_INET6
) {
1263 addr
.saddr_in6
.sin6_family
= AF_INET6
;
1264 addr
.saddr_in6
.sin6_port
= htons(SERVER_LAN_PORT
);
1265 addr
.saddr_in6
.sin6_addr
= in6addr_any
;
1267 #endif /* IPv6 support */
1268 if (addr
.saddr
.sa_family
== AF_INET
) {
1269 addr
.saddr_in4
.sin_family
= AF_INET
;
1270 addr
.saddr_in4
.sin_port
= htons(SERVER_LAN_PORT
);
1271 addr
.saddr_in4
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
1275 log_error("Unsupported address family in server_open_socket()");
1278 if (bind(socklan
, &addr
.saddr
, sockaddr_size(&addr
)) < 0) {
1279 log_error("Announcement socket binding failed: %s", fc_strerror(fc_get_errno()));
1282 #ifdef FREECIV_IPV6_SUPPORT
1283 if (addr
.saddr
.sa_family
== AF_INET6
) {
1284 inet_pton(AF_INET6
, group
, &mreq6
.ipv6mr_multiaddr
.s6_addr
);
1285 mreq6
.ipv6mr_interface
= 0; /* TODO: Interface selection */
1286 if (setsockopt(socklan
, IPPROTO_IPV6
, FC_IPV6_ADD_MEMBERSHIP
,
1287 (const char*)&mreq6
, sizeof(mreq6
)) < 0) {
1288 log_error("FC_IPV6_ADD_MEMBERSHIP (%s) failed: %s",
1289 group
, fc_strerror(fc_get_errno()));
1292 #endif /* IPV6 Support */
1293 if (addr
.saddr
.sa_family
== AF_INET
) {
1294 fc_inet_aton(group
, &mreq4
.imr_multiaddr
, FALSE
);
1295 #ifdef HAVE_IP_MREQN
1296 mreq4
.imr_address
.s_addr
= htonl(INADDR_ANY
);
1297 mreq4
.imr_ifindex
= 0;
1299 mreq4
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
1302 if (setsockopt(socklan
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
1303 (const char*)&mreq4
, sizeof(mreq4
)) < 0) {
1304 log_error("IP_ADD_MEMBERSHIP (%s) failed: %s",
1305 group
, fc_strerror(fc_get_errno()));
1310 log_error("Unsupported address family for broadcasting.");
1316 /********************************************************************
1317 Initialize connection related stuff. Attention: Logging is not
1318 available within this functions!
1319 ********************************************************************/
1320 void init_connections(void)
1324 game
.all_connections
= conn_list_new();
1325 game
.est_connections
= conn_list_new();
1326 game
.glob_observers
= conn_list_new();
1328 for (i
= 0; i
< MAX_NUM_CONNECTIONS
; i
++) {
1329 struct connection
*pconn
= &connections
[i
];
1331 pconn
->used
= FALSE
;
1332 pconn
->self
= conn_list_new();
1333 conn_list_prepend(pconn
->self
, pconn
);
1337 unsigned long status
;
1339 $
DESCRIPTOR (tt_desc
, "SYS$INPUT");
1340 status
= sys$
assign(&tt_desc
, &tt_chan
, 0, 0);
1341 if (!$
VMS_STATUS_SUCCESS(status
)) {
1348 /**************************************************************************
1349 Starts processing of request packet from client.
1350 **************************************************************************/
1351 static void start_processing_request(struct connection
*pconn
,
1354 fc_assert_ret(request_id
);
1355 fc_assert_ret(pconn
->server
.currently_processed_request_id
== 0);
1356 log_debug("start processing packet %d from connection %d",
1357 request_id
, pconn
->id
);
1358 conn_compression_freeze(pconn
);
1359 send_packet_processing_started(pconn
);
1360 pconn
->server
.currently_processed_request_id
= request_id
;
1363 /**************************************************************************
1364 Finish processing of request packet from client.
1365 **************************************************************************/
1366 static void finish_processing_request(struct connection
*pconn
)
1368 if (!pconn
|| !pconn
->used
) {
1371 fc_assert_ret(pconn
->server
.currently_processed_request_id
);
1372 log_debug("finish processing packet %d from connection %d",
1373 pconn
->server
.currently_processed_request_id
, pconn
->id
);
1374 send_packet_processing_finished(pconn
);
1375 pconn
->server
.currently_processed_request_id
= 0;
1376 conn_compression_thaw(pconn
);
1379 /****************************************************************************
1381 ****************************************************************************/
1382 static void connection_ping(struct connection
*pconn
)
1384 struct timer
*timer
= timer_new(TIMER_USER
, TIMER_ACTIVE
);
1386 log_debug("sending ping to %s (open=%d)", conn_description(pconn
),
1387 timer_list_size(pconn
->server
.ping_timers
));
1389 timer_list_append(pconn
->server
.ping_timers
, timer
);
1390 send_packet_conn_ping(pconn
);
1393 /**************************************************************************
1394 Handle response to ping.
1395 **************************************************************************/
1396 void handle_conn_pong(struct connection
*pconn
)
1398 struct timer
*timer
;
1400 if (timer_list_size(pconn
->server
.ping_timers
) == 0) {
1401 log_error("got unexpected pong from %s", conn_description(pconn
));
1405 timer
= timer_list_front(pconn
->server
.ping_timers
);
1406 pconn
->ping_time
= timer_read_seconds(timer
);
1407 timer_list_pop_front(pconn
->server
.ping_timers
);
1408 log_debug("got pong from %s (open=%d); ping time = %fs",
1409 conn_description(pconn
),
1410 timer_list_size(pconn
->server
.ping_timers
), pconn
->ping_time
);
1413 /**************************************************************************
1414 Handle client's regular hearbeat
1415 **************************************************************************/
1416 void handle_client_heartbeat(struct connection
*pconn
)
1418 log_debug("Received heartbeat");
1421 /**************************************************************************
1422 Send ping time info about all connections to all connections.
1423 **************************************************************************/
1424 static void send_ping_times_to_all(void)
1426 struct packet_conn_ping_info packet
;
1430 conn_list_iterate(game
.est_connections
, pconn
) {
1434 fc_assert(i
< ARRAY_SIZE(packet
.conn_id
));
1435 packet
.conn_id
[i
] = pconn
->id
;
1436 packet
.ping_time
[i
] = pconn
->ping_time
;
1438 } conn_list_iterate_end
;
1439 packet
.connections
= i
;
1441 lsend_packet_conn_ping_info(game
.est_connections
, &packet
);
1444 /********************************************************************
1445 Listen for UDP packets multicasted from clients requesting
1446 announcement of servers on the LAN.
1447 ********************************************************************/
1448 static void get_lanserver_announcement(void)
1450 fd_set readfs
, exceptfs
;
1456 if (srvarg
.announce
== ANNOUNCE_NONE
) {
1462 FD_SET(socklan
, &exceptfs
);
1463 FD_SET(socklan
, &readfs
);
1468 while (fc_select(socklan
+ 1, &readfs
, NULL
, &exceptfs
, &tv
) == -1) {
1469 if (errno
!= EINTR
) {
1470 log_error("select failed: %s", fc_strerror(fc_get_errno()));
1473 /* EINTR can happen sometimes, especially when compiling with -pg.
1474 * Generally we just want to run select again. */
1477 /* We would need a raw network connection for broadcast messages */
1478 if (FD_ISSET(socklan
, &readfs
)) {
1479 if (0 < recvfrom(socklan
, msgbuf
, sizeof(msgbuf
), 0, NULL
, NULL
)) {
1480 dio_input_init(&din
, msgbuf
, 1);
1481 dio_get_uint8_raw(&din
, &type
);
1482 if (type
== SERVER_LAN_VERSION
) {
1483 log_debug("Received request for server LAN announcement.");
1484 send_lanserver_response();
1486 log_debug("Received invalid request for server LAN announcement.");
1492 /********************************************************************
1493 This function broadcasts an UDP packet to clients with
1494 that requests information about the server state.
1495 ********************************************************************/
1496 /* We would need a raw network connection for broadcast messages */
1497 static void send_lanserver_response(void)
1499 #ifndef FREECIV_HAVE_WINSOCK
1500 unsigned char buffer
[MAX_LEN_PACKET
];
1501 #else /* FREECIV_HAVE_WINSOCK */
1502 char buffer
[MAX_LEN_PACKET
];
1503 #endif /* FREECIV_HAVE_WINSOCK */
1511 struct raw_data_out dout
;
1512 union fc_sockaddr addr
;
1513 int socksend
, setting
= 1;
1516 #ifndef FREECIV_HAVE_WINSOCK
1520 /* Create a socket to broadcast to client. */
1521 if ((socksend
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
1522 log_error("Lan response socket failed: %s", fc_strerror(fc_get_errno()));
1526 /* Set the UDP Multicast group IP address of the packet. */
1527 group
= get_multicast_group(srvarg
.announce
== ANNOUNCE_IPV6
);
1528 memset(&addr
, 0, sizeof(addr
));
1529 addr
.saddr_in4
.sin_family
= AF_INET
;
1530 addr
.saddr_in4
.sin_addr
.s_addr
= inet_addr(group
);
1531 addr
.saddr_in4
.sin_port
= htons(SERVER_LAN_PORT
+ 1);
1533 /* this setsockopt call fails on Windows 98, so we stick with the default
1534 * value of 1 on Windows, which should be fine in most cases */
1535 #ifndef FREECIV_HAVE_WINSOCK
1536 /* Set the Time-to-Live field for the packet. */
1537 ttl
= SERVER_LAN_TTL
;
1538 if (setsockopt(socksend
, IPPROTO_IP
, IP_MULTICAST_TTL
,
1539 (const char*)&ttl
, sizeof(ttl
))) {
1540 log_error("setsockopt failed: %s", fc_strerror(fc_get_errno()));
1543 #endif /* FREECIV_HAVE_WINSOCK */
1545 if (setsockopt(socksend
, SOL_SOCKET
, SO_BROADCAST
,
1546 (const char*)&setting
, sizeof(setting
))) {
1547 log_error("Lan response setsockopt failed: %s", fc_strerror(fc_get_errno()));
1551 /* Create a description of server state to send to clients. */
1552 if (srvarg
.identity_name
[0] != '\0') {
1553 sz_strlcpy(hostname
, srvarg
.identity_name
);
1554 } else if (fc_gethostname(hostname
, sizeof(hostname
)) != 0) {
1555 sz_strlcpy(hostname
, "none");
1558 fc_snprintf(version
, sizeof(version
), "%d.%d.%d%s",
1559 MAJOR_VERSION
, MINOR_VERSION
, PATCH_VERSION
, VERSION_LABEL
);
1561 switch (server_state()) {
1563 /* TRANS: Game state for local server */
1564 fc_snprintf(status
, sizeof(status
), _("Pregame"));
1567 /* TRANS: Game state for local server */
1568 fc_snprintf(status
, sizeof(status
), _("Running"));
1571 /* TRANS: Game state for local server */
1572 fc_snprintf(status
, sizeof(status
), _("Game over"));
1576 fc_snprintf(players
, sizeof(players
), "%d",
1577 normal_player_count());
1580 players_iterate(pplayer
) {
1581 if (pplayer
->is_alive
&& is_human(pplayer
)) {
1584 } players_iterate_end
;
1585 fc_snprintf(humans
, sizeof(humans
), "%d", nhumans
);
1587 fc_snprintf(port
, sizeof(port
), "%d",
1590 dio_output_init(&dout
, buffer
, sizeof(buffer
));
1591 dio_put_uint8_raw(&dout
, SERVER_LAN_VERSION
);
1592 dio_put_string_raw(&dout
, hostname
);
1593 dio_put_string_raw(&dout
, port
);
1594 dio_put_string_raw(&dout
, version
);
1595 dio_put_string_raw(&dout
, status
);
1596 dio_put_string_raw(&dout
, players
);
1597 dio_put_string_raw(&dout
, humans
);
1598 dio_put_string_raw(&dout
, get_meta_message_string());
1599 size
= dio_output_used(&dout
);
1601 /* Sending packet to client with the information gathered above. */
1602 if (sendto(socksend
, buffer
, size
, 0, &addr
.saddr
,
1603 sockaddr_size(&addr
)) < 0) {
1604 log_error("landserver response sendto failed: %s",
1605 fc_strerror(fc_get_errno()));
1609 fc_closesocket(socksend
);