26#ifdef FREECIV_HAVE_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
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>
102# define lib$stop LIB$STOP
103# define sys$qiow SYS$QIOW
104# define sys$assign SYS$ASSIGN
110# include <lib$routines.h>
112 static unsigned long int tt_chan;
118#define PROCESSING_TIME_STATISTICS 0
134#if defined(FREECIV_HAVE_LIBREADLINE) || \
135 (!defined(FREECIV_SOCKET_ZERO_NOT_STDIN) && !defined(FREECIV_HAVE_LIBREADLINE))
144#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
145 log_normal(
_(
"Server cannot read standard input. Ignoring input."));
154#ifdef FREECIV_HAVE_LIBREADLINE
157#define HISTORY_FILENAME "freeciv-server_history"
158#define HISTORY_LENGTH 100
178 if (
line[0] !=
'\0') {
206#ifdef FREECIV_HAVE_LIBREADLINE
283#ifdef FREECIV_HAVE_LIBREADLINE
315 if (
pconn->used &&
pconn->server.is_closing) {
316 closing[num++] =
pconn;
329 for (
i = 0;
i < num;
i++) {
353 if (!
pconn->server.is_closing
366 log_verbose(
"connection (%s) cut due to lagging player",
405 && !
pconn->server.is_closing
406 && 0 <
pconn->send_buffer->ndata) {
424 if (
pconn->used && !
pconn->server.is_closing) {
426 log_verbose(
"connection (%s) cut due to exception data",
430 if (
pconn->send_buffer &&
pconn->send_buffer->ndata > 0) {
467#if PROCESSING_TIME_STATISTICS
474#if PROCESSING_TIME_STATISTICS
482 pconn->server.last_request_id_seen
485#if PROCESSING_TIME_STATISTICS
498#if PROCESSING_TIME_STATISTICS
508#if PROCESSING_TIME_STATISTICS
529#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
535#ifdef FREECIV_HAVE_LIBREADLINE
602 log_normal(
_(
"Shutting down for lack of players."));
625 log_normal(
_(
"Shutting down in %d seconds for lack of players."),
630 log_normal(
_(
"Restarting in %d seconds for lack of players."),
648 if ((!
pconn->server.is_closing
651 (
pconn->server.ping_timers))
656 log_verbose(
"connection (%s) [hack-level] ping timeout ignored",
659 log_verbose(
"connection (%s) cut due to ping timeout",
663 }
else if (
pconn->established) {
676 && !
pconn->server.is_closing
698#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
717 if (
pconn->used && !
pconn->server.is_closing) {
719 if (0 <
pconn->send_buffer->ndata) {
752 ?
NULL :
"save interval");
765 unsigned long status;
780#ifndef FREECIV_SOCKET_ZERO_NOT_STDIN
818 && !
pconn->server.is_closing
820 log_verbose(
"connection (%s) cut due to exception data",
825#ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
835#ifdef FREECIV_HAVE_LIBREADLINE
888 ||
pconn->server.is_closing
897 }
else if (-2 ==
nb) {
909 && !
pconn->server.is_closing
910 &&
pconn->send_buffer
911 &&
pconn->send_buffer->ndata > 0) {
944 ?
NULL :
"save interval");
961 static unsigned short i = 0;
965 if (
i == (
unsigned short) - 1) {
995#ifdef FREECIV_IPV6_SUPPORT
1000 const char *host =
NULL;
1011#ifdef FREECIV_IPV6_SUPPORT
1020 log_error(
"Unsupported address family in server_accept_connection()");
1036 log_verbose(
"Rejecting new connection from %s: maximum number of "
1037 "connections for this address exceeded (%d).",
1048#ifdef FREECIV_IPV6_SUPPORT
1051 &&
'\0' != host[0]);
1055 if (
NULL != from &&
'\0' != from->h_name[0]) {
1056 host = from->h_name;
1087 pconn->capability[0] =
'\0';
1090 pconn->server.currently_processed_request_id = 0;
1091 pconn->server.last_request_id_seen = 0;
1092 pconn->server.auth_tries = 0;
1093 pconn->server.auth_settime = 0;
1096 pconn->server.granted_access_level =
pconn->access_level;
1097 pconn->server.ignore_list =
1100 pconn->ping_time = -1.0;
1123 log_error(
"maximum number of connections reached");
1142 const char *cause, *group;
1150#ifdef FREECIV_IPV6_SUPPORT
1154 log_verbose(
"Server attempting to listen on %s:%d",
1165 log_fatal(
_(
"Server: bad address: <%s:%d>."),
1189#ifndef FREECIV_HAVE_WINSOCK
1192 (
char *)&
on,
sizeof(
on)) == -1) {
1193 log_error(
"setsockopt SO_REUSEADDR failed: %s",
1201#ifdef FREECIV_IPV6_SUPPORT
1205 (
char *)&
on,
sizeof(
on)) == -1) {
1206 log_error(
"setsockopt IPV6_V6ONLY failed: %s",
1273#ifdef FREECIV_IPV6_SUPPORT
1291 (
char *)&
on,
sizeof(
on)) == -1) {
1299 memset(&addr, 0,
sizeof(addr));
1303#ifdef FREECIV_IPV6_SUPPORT
1305 addr.saddr_in6.sin6_family =
AF_INET6;
1317 log_error(
"Unsupported address family in server_open_socket()");
1324#ifdef FREECIV_IPV6_SUPPORT
1327 mreq6.ipv6mr_interface = 0;
1330 log_error(
"FC_IPV6_ADD_MEMBERSHIP (%s) failed: %s",
1339 mreq4.imr_ifindex = 0;
1346 log_error(
"IP_ADD_MEMBERSHIP (%s) failed: %s",
1352 log_error(
"Unsupported address family for broadcasting.");
1399 log_debug(
"start processing packet %d from connection %d",
1417 log_debug(
"finish processing packet %d from connection %d",
1418 pconn->server.currently_processed_request_id,
pconn->id);
1420 pconn->server.currently_processed_request_id = 0;
1453 log_debug(
"got pong from %s (open=%d); ping time = %fs",
1528 log_debug(
"Received request for server LAN announcement.");
1531 log_debug(
"Received invalid request for server LAN announcement.");
1544#ifndef FREECIV_HAVE_WINSOCK
1561#ifndef FREECIV_HAVE_WINSOCK
1574 memset(&addr, 0,
sizeof(addr));
1575#ifdef FREECIV_IPV6_SUPPORT
1577 addr.saddr_in6.sin6_family =
AF_INET6;
1590#ifndef FREECIV_HAVE_WINSOCK
1594#ifdef FREECIV_IPV6_SUPPORT
1606 (
const char*)&
ttl,
sizeof(
ttl))) {
1626 fc_snprintf(version,
sizeof(version),
"%d.%d.%d%s",
1649 if (pplayer->is_alive &&
is_human(pplayer)) {
1672 log_error(
"landserver response sendto failed: %s",
void call_ai_refresh(void)
void auth_process_status(struct connection *pconn)
static struct ai_type * self
static struct fc_sockaddr_list * list
void lost_connection_to_client(struct connection *pconn)
void connection_close_server(struct connection *pconn, const char *reason)
struct player * conn_get_player(const struct connection *pconn)
struct connection * conn_by_user(const char *user_name)
void connections_set_close_callback(conn_close_fn_t func)
void flush_connection_send_buffer_all(struct connection *pc)
int get_next_request_id(int old_request_id)
void connection_do_buffer(struct connection *pc)
void conn_pattern_destroy(struct conn_pattern *ppattern)
void connection_common_init(struct connection *pconn)
const char * conn_description(const struct connection *pconn)
void connection_common_close(struct connection *pconn)
void conn_compression_freeze(struct connection *pconn)
struct connection * conn_by_number(int id)
int read_socket_data(int sock, struct socket_packet_buffer *buffer)
void connection_do_unbuffer(struct connection *pc)
bool conn_compression_thaw(struct connection *pconn)
#define conn_list_iterate(connlist, pconn)
#define conn_list_iterate_end
void con_prompt_enter_clear(void)
void con_prompt_init(void)
void con_prompt_enter(void)
void con_prompt_off(void)
int dio_put_uint8_raw(struct raw_data_out *dout, int value)
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
int dio_put_string_raw(struct raw_data_out *dout, const char *value)
bool dio_get_uint8_raw(struct data_in *din, int *dest)
size_t dio_output_used(struct raw_data_out *dout)
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
#define MAX_NUM_CONNECTIONS
char * local_to_internal_string_malloc(const char *text)
int current_turn_timeout(void)
#define fc_assert_ret(condition)
#define log_verbose(message,...)
#define fc_assert(condition)
#define log_fatal(message,...)
#define log_debug(message,...)
#define log_normal(message,...)
#define log_error(message,...)
#define fc_calloc(n, esz)
void fc_shutdown_network(void)
int addr_family_for_announce_type(enum announce_type announce)
bool fc_inet_aton(const char *cp, struct in_addr *inp, bool addr_none_ok)
struct fc_sockaddr_list * net_lookup_service(const char *name, int port, enum fc_addr_family family)
void fc_closesocket(int sock)
void sockaddr_debug(union fc_sockaddr *addr, enum log_level lvl)
int sockaddr_size(union fc_sockaddr *addr)
void fc_nonblock(int sockfd)
int fc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fc_timeval *timeout)
struct timeval fc_timeval
#define fc_sockaddr_list_iterate_end
#define fc_sockaddr_list_iterate(sockaddrlist, paddr)
#define FC_IPV6_ADD_MEMBERSHIP
void packets_deinit(void)
#define get_packet_from_connection(pc, ptype)
void packet_destroy(void *packet, enum packet_type type)
int send_packet_conn_ping(struct connection *pc)
int send_packet_processing_finished(struct connection *pc)
int send_packet_processing_started(struct connection *pc)
void lsend_packet_conn_ping_info(struct conn_list *dest, const struct packet_conn_ping_info *packet)
void lsend_packet_server_shutdown(struct conn_list *dest)
struct player * player_by_name(const char *name)
struct player * player_by_user(const char *name)
#define players_iterate_end
#define players_iterate(_pplayer)
int normal_player_count(void)
void script_server_signal_emit(const char *signal_name,...)
static void cut_lagging_connection(struct connection *pconn)
static void connection_ping(struct connection *pconn)
static void server_conn_close_callback(struct connection *pconn)
static void send_lanserver_response(void)
static struct connection connections[MAX_NUM_CONNECTIONS]
int server_open_socket(void)
void init_connections(void)
static void really_close_connections(void)
int server_make_connection(int new_sock, const char *client_addr, const char *client_ip)
void handle_conn_pong(struct connection *pconn)
static int * listen_socks
static char * current_internal
static bool get_packet(struct connection *pconn, struct packet_to_handle *ppacket)
static void send_ping_times_to_all(void)
enum server_events server_sniff_all_input(void)
static void close_connection(struct connection *pconn)
void handle_client_heartbeat(struct connection *pconn)
void readline_atexit(void)
void close_connections_and_socket(void)
static void finish_processing_request(struct connection *pconn)
static void start_processing_request(struct connection *pconn, int request_id)
static void handle_stdin_close(void)
static const char * makeup_connection_name(int *id)
static int server_accept_connection(int sockfd)
static void get_lanserver_announcement(void)
static void incoming_client_packets(struct connection *pconn)
@ S_E_END_OF_TURN_TIMEOUT
#define SERVER_LAN_VERSION
bool make_dir(const char *pathname, int mode)
char * get_multicast_group(bool ipv6_preferred)
char * freeciv_storage_dir(void)
void save_game_auto(const char *save_reason, enum autosave_type type)
void set_server_state(enum server_states newstate)
struct server_arguments srvarg
bool server_packet_input(struct connection *pconn, void *packet, int type)
void fc__noreturn server_quit(void)
enum server_states server_state(void)
enum cmdlevel access_level_for_next_connection(void)
bool handle_stdin_input_free(struct connection *caller, char *str)
struct conn_list * glob_observers
struct conn_list * est_connections
struct packet_game_info info
struct timer * save_timer
int additional_phase_seconds
int maxconnectionsperhost
struct conn_list * web_client_connections
struct timer * phase_timer
struct conn_list * all_connections
struct civ_game::@32::@36 server
struct packet_timeout_info tinfo
struct socket_packet_buffer * buffer
float ping_time[MAX_NUM_CONNECTIONS]
int conn_id[MAX_NUM_CONNECTIONS]
float seconds_to_phasedone
enum announce_type announce
int fc_snprintf(char *str, size_t n, const char *format,...)
int fc_gethostname(char *buf, size_t len)
const char * fc_strerror(fc_errno err)
fc_errno fc_get_errno(void)
#define sz_strlcpy(dest, src)
void timer_destroy(struct timer *t)
void timer_start(struct timer *t)
struct timer * timer_new(enum timer_timetype type, enum timer_use use, const char *name)
double timer_read_seconds(struct timer *t)
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use, const char *name)
struct sockaddr_in saddr_in4
void send_updated_vote_totals(struct conn_list *dest)