diff options
author | scratko <m@scratko.xyz> | 2024-12-09 23:06:34 +0300 |
---|---|---|
committer | scratko <m@scratko.xyz> | 2024-12-10 00:34:47 +0300 |
commit | e44cb50ab5964747d2d1369da378ceae804b85ef (patch) | |
tree | bde2a1b2cadf8c28d471855f0dc4a08d06f1cf3a /server/server.c | |
parent | bedb024261f6539d0517430e88cfaa1e78e6e955 (diff) | |
download | durak-e44cb50ab5964747d2d1369da378ceae804b85ef.tar.gz durak-e44cb50ab5964747d2d1369da378ceae804b85ef.tar.bz2 durak-e44cb50ab5964747d2d1369da378ceae804b85ef.zip |
After 30 seconds a signal is sent after the first player is connected. During
this period the second player must connect, otherwise the first player will be
disconnected.
Diffstat (limited to 'server/server.c')
-rw-r--r-- | server/server.c | 71 |
1 files changed, 59 insertions, 12 deletions
diff --git a/server/server.c b/server/server.c index 0017888..bfc71ef 100644 --- a/server/server.c +++ b/server/server.c @@ -15,10 +15,17 @@ #include "card_stack.h" #include "card_queue.h" +static volatile sig_atomic_t timeout_is_over = 0; + void handler(int s) { - if(s == SIGPIPE) - signal(SIGPIPE, handler); + switch(s) { + case SIGPIPE: + signal(SIGPIPE, handler); + break; + case SIGALRM: + timeout_is_over = 1; + } } static void init_session(struct session *new_session, struct sockaddr_in *from, @@ -98,8 +105,7 @@ static void close_connection(struct server *serv) static int check_playable_player_number(struct server *serv) { - return serv->connected_players_counter >= 2 && - serv->connected_players_counter < 8; + return serv->connected_players_counter >= 2; } static int is_max_playable_player_number(struct server *serv) @@ -593,10 +599,21 @@ static void determine_server_state(struct server *serv) switch(serv->state) { case no_players: serv->state = first_player; + /* + * The second player must connect no later than TIMEOUT. + * This is done to protect against bots. + */ + signal(SIGALRM, handler); + alarm(timeout); break; case first_player: - if(check_playable_player_number(serv)) + if(check_playable_player_number(serv)) { serv->state = confirmation_waiting; + /* cancel alarm */ + alarm(0); + /* default disposition */ + signal(SIGALRM, SIG_DFL); + } break; case confirmation_waiting: set_record_status_for_all(serv); @@ -658,7 +675,7 @@ static int new_player_tracking_condition(enum server_states state) /* * when accepting new players */ -static int server_state_change_condition(struct server *serv) +static int check_server_state_change_conditions_before_game(struct server *serv) { return serv->state == no_players || @@ -678,7 +695,7 @@ static int accept_new_player(struct server *serv) } /* update info about connected players */ set_record_status_for_all(serv); - if(server_state_change_condition(serv)) + if(check_server_state_change_conditions_before_game(serv)) serv->change_server_state = 1; return 1; } @@ -736,7 +753,10 @@ static void set_up_player_tracking(struct server *serv, fd_set *readfds, } } -static int check_server_state_change_conditions(struct server *serv) +/* + * is checked after a write or read operation in make_data_transfer + */ +static int check_server_state_change_conditions_in_game(struct server *serv) { switch(serv->state) { case start_game: @@ -763,7 +783,7 @@ static int check_server_state_change_conditions(struct server *serv) static void make_data_transfer(struct server *serv, fd_set *readfds, fd_set *writefds) { - int i, result, close_connection_status = 0; + int i, result = 1, close_connection_status = 0; for(i = 0; i < serv->max_sess_arr_size; ++i) { if(!serv->sess_arr[i]) continue; @@ -840,13 +860,18 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, close(i); serv->sess_arr[i]->fd = -1; close_connection_status = 1; - result = 1; /* next can be reading that's not ready */ + /* + * Flag reset + * The following clients may not have requested read or + * write operations + */ + result = 1; } } if(serv->state == start_game || serv->state == end_round || serv->state == end_game) sleep(2); - if(check_server_state_change_conditions(serv)) + if(check_server_state_change_conditions_in_game(serv)) serv->change_server_state = 1; /* connection is closed */ if(close_connection_status) { @@ -856,6 +881,23 @@ static void make_data_transfer(struct server *serv, fd_set *readfds, } } +static void close_bot_connection(struct server *serv) +{ + int i; + + for(i = 0; i < serv->max_sess_arr_size; ++i) { + if(!serv->sess_arr[i]) + continue; + close(serv->sess_arr[i]->fd); + serv->sess_arr[i]->fd = -1; + free(serv->sess_arr[i]); + serv->sess_arr[i] = NULL; + } + serv->change_server_state = 0; + serv->connected_players_counter = 0; + serv->state = no_players; +} + int main_loop(struct server *serv) { int maxfd, accept_result, select_result; @@ -875,8 +917,13 @@ int main_loop(struct server *serv) set_up_player_tracking(serv, &readfds, &writefds, &maxfd); select_result = select(maxfd + 1, &readfds, &writefds, NULL, NULL); - if(select_result == -1) + if(select_result == -1 && !timeout_is_over) return 3; + if(timeout_is_over && serv->connected_players_counter == 1) { + close_bot_connection(serv); + timeout_is_over = 0; + continue; + } if(FD_ISSET(serv->listen_socket, &readfds)) { accept_result = accept_new_player(serv); |