From a2d696dea797faaa3157046c8ae89cd70e965bff Mon Sep 17 00:00:00 2001 From: scratko Date: Sat, 10 Aug 2024 02:46:56 +0300 Subject: Prefinal version Added client. Moved files to directories. --- server.c | 733 --------------------------------------------------------------- 1 file changed, 733 deletions(-) delete mode 100644 server.c (limited to 'server.c') diff --git a/server.c b/server.c deleted file mode 100644 index 5153107..0000000 --- a/server.c +++ /dev/null @@ -1,733 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "server.h" -#include "server_data_processing.h" -#include "server_game_process.h" -#include "card_stack.h" -#include "card_queue.h" - - -static void init_session(struct session *new_session, struct sockaddr_in *from, - int fd, int player_position) -{ - new_session->fd = fd; - new_session->record = 1; - new_session->state = display_only_table; - new_session->player_position = player_position; - new_session->tm = none; - new_session->defense_lost = 0; - init_stack(&new_session->deck); -} - -static int accept_client(struct server *serv) -{ - int fd, i; - struct sockaddr_in addr; - struct session *new_session; - socklen_t len = sizeof(addr); - fd = accept(serv->listen_socket, (struct sockaddr*) &addr, &len); - if(fd == -1) - return -1; - - if(fd >= serv->max_sess_arr_size) { - int newlen = serv->max_sess_arr_size; - while(fd >= newlen) - newlen += init_sess_arr_size; - serv->sess_arr = - realloc(serv->sess_arr, newlen * sizeof(struct session*)); - for(i = serv->max_sess_arr_size; i < newlen; i++) - serv->sess_arr[i] = NULL; - serv->max_sess_arr_size = newlen; - } - new_session = malloc(sizeof(struct session)); - serv->sess_arr[fd] = new_session; - ++serv->connected_players_counter; - init_session(new_session, &addr, fd, serv->connected_players_counter); - return 1; -} - -static int check_playable_player_number(struct server *serv) -{ - return serv->connected_players_counter >= 2 && - serv->connected_players_counter < 8; -} - -static int is_max_playable_player_number(struct server *serv) -{ - return serv->connected_players_counter == 8; -} - -static void init_new_game(struct server *serv) -{ - int i,j, lowest_trump, current_trump, who_attack; - /* idx in serv->turn_queue */ - who_attack = -1; - lowest_trump = 0; - - serv->shuffled_deck = get_shuffled_deck(); - serv->trump_suit = find_trump_suit(serv->shuffled_deck, - &serv->shuffled_deck_size); - serv->turn_queue = malloc(sizeof(struct session*) * - serv->connected_players_counter); - serv->card_quantity_arr = malloc(sizeof(int) * - serv->connected_players_counter); - serv->position_whose_turn = 0; - serv->cq = malloc(sizeof(struct card_queue)); - serv->cot = malloc(sizeof(struct cards_on_table)); - /* - * dealing cards to all and - * determining who moves first - */ - for(i = 0, j = 0; i < serv->max_sess_arr_size; ++i) { - if(serv->sess_arr[i]) { - serv->turn_queue[j] = serv->sess_arr[i]; - deal_first_cards(serv->shuffled_deck, &serv->shuffled_deck_size, - &serv->sess_arr[i]->deck); - current_trump = find_lowest_trump(serv->sess_arr[i]->deck, - serv->trump_suit); - if(current_trump) - if(!lowest_trump || current_trump < lowest_trump) { - lowest_trump = current_trump; - who_attack = j; - } - ++j; - } - } - /* random selection of the first player */ - if(who_attack == -1) { - who_attack = - 0 + (int)((double)serv->connected_players_counter*rand()/ - (RAND_MAX + 1.0)); - } - for(i = 0; i < who_attack; ++i) - shift_turn_queue_by_one(serv->turn_queue, - serv->connected_players_counter); - update_card_quantity_arr(serv); - init_queue(serv->cq); - serv->cot->card_arr_idx = -1; - serv->gi = get_new_game_info(serv->connected_players_counter, - serv->card_quantity_arr, - serv->shuffled_deck_size, - serv->trump_suit, serv->position_whose_turn, - serv->cq, serv->cot); -} - -static void set_whose_turn(struct server *serv, enum client_game_states state) -{ - switch(state) { - case attack: - serv->position_whose_turn = serv->turn_queue[0]->player_position; - break; - case defense: - serv->position_whose_turn = serv->turn_queue[1]->player_position; - break; - case tossing: - default: - serv->position_whose_turn = 0; - } -} - -static void set_state_for_client(struct server *serv, - enum client_game_states state) -{ - int i; - - switch(state) { - case attack: - serv->turn_queue[0]->state = attack; - break; - case defense: - serv->turn_queue[1]->state = defense; - break; - case tossing: - serv->turn_queue[1]->state = tossing_expectation; - default: - {} - } - - for(i = 0; i < serv->connected_players_counter; ++i) { - switch(state) { - case attack: - if(serv->turn_queue[i] && serv->turn_queue[i] != - serv->turn_queue[0]) - serv->turn_queue[i]->state = attack_expectation; - break; - case defense: - if(serv->turn_queue[i] && serv->turn_queue[i] != - serv->turn_queue[1]) - serv->turn_queue[i]->state = defense_expectation; - break; - case tossing: - if(serv->turn_queue[i] && serv->turn_queue[i] != - serv->turn_queue[1]) { - if(check_player_can_toss_card(serv->turn_queue[i]->deck, - serv->cot)) - { - serv->turn_queue[i]->tm = answer_wait; - serv->turn_queue[i]->state = tossing; - } else { - serv->turn_queue[i]->tm = none; - serv->turn_queue[i]->state = tossing_expectation; - } - } - break; - case display_only_table: - if(serv->turn_queue[i]) - serv->turn_queue[i]->state = display_only_table; - break; - default: - {} - } - } -} - -static void set_record_status_for_all(struct server *serv) -{ - int i; - for(i = 0; i < serv->max_sess_arr_size; ++i) - if(serv->sess_arr[i]) - serv->sess_arr[i]->record = 1; -} - -static int print_table_condition(struct server *serv) -{ - return !check_defender_can_defend(serv->cq, serv->turn_queue[1]->deck, - serv->trump_suit) && - !check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, - serv->cq, serv->cot); -} - -static int defense_condition(struct server *serv) -{ - return check_defender_can_defend(serv->cq, serv->turn_queue[1]->deck, - serv->trump_suit); -} - -static void define_phase_after_attack(struct server *serv) -{ - if(print_table_condition(serv)) { - set_state_for_client(serv, display_only_table); - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - serv->turn_queue[1]->defense_lost = 1; - serv->state = table; - } else if(defense_condition(serv)) { - set_state_for_client(serv, defense); - set_whose_turn(serv, defense); - put_one_card_from_queue_to_table(serv->cot, serv->cq); - serv->state = defense_phase_out; - } else { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - serv->turn_queue[1]->defense_lost = 1; - serv->state = tossing_phase_out; - } -} - -static void define_phase_after_defense(struct server *serv) -{ - /* card wasn't beated */ - if(serv->cot->card_arr[serv->cot->card_arr_idx][0] == '-') { - serv->turn_queue[1]->defense_lost = 1; - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, - serv->cq, serv->cot)) - { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - serv->state = tossing_phase_out; - /* then begin new attack */ - } else { - set_state_for_client(serv, display_only_table); - serv->state = table; - } - /* can defender continue defense? */ - } else { - if(is_empty_queue(serv->cq)) { - if(check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, - serv->cq, serv->cot)) - { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - serv->state = tossing_phase_out; - } else { - set_state_for_client(serv, display_only_table); - serv->state = table; - } - /* card queue contains some cards for defender */ - } else { - /* defender can defense */ - if(defense_condition(serv)) { - put_one_card_from_queue_to_table(serv->cot, serv->cq); - set_state_for_client(serv, defense); - set_whose_turn(serv, defense); - serv->state = defense_phase_out; - } - /* defender can't defense */ -#if 0 - } else { - serv->turn_queue[1]->defense_lost = 1; - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, - serv->cq, serv->cot)) - { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - serv->state = tossing_phase_out; - } else { - move_all_cards_to_defender(serv->cot, - &serv->turn_queue[1]->deck); - /* add shifting of turn arr*/ - set_state_for_client(serv, attack); - set_whose_turn(serv, attack); - serv->state = attack_phase_out; - } - } -#endif - } - } -} - -static void define_phase_after_tossing(struct server *serv) -{ - if(serv->turn_queue[1]->defense_lost) { - if(is_empty_queue(serv->cq)) { - /* nobody's put any cards on the table */ - set_state_for_client(serv, display_only_table); - serv->state = table; - } - else { - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, - serv->cq, serv->cot)) - { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - serv->state = tossing_phase_out; - } else { - set_state_for_client(serv, display_only_table); - serv->state = table; - } - } - /* defense continue? */ - } else { - if(is_empty_queue(serv->cq)) { - set_state_for_client(serv, display_only_table); - serv->state = table; - } else { - if(check_defender_can_defend(serv->cq, serv->turn_queue[1]->deck, - serv->trump_suit)) { - put_one_card_from_queue_to_table(serv->cot, serv->cq); - set_state_for_client(serv, defense); - set_whose_turn(serv, defense); - serv->state = defense_phase_out; - } else { - serv->turn_queue[1]->defense_lost = 1; - put_all_cards_from_queue_to_table(serv->cot, serv->cq); - if(check_someone_can_toss_card(serv->turn_queue, - serv->connected_players_counter, - serv->cq, serv->cot)) - { - set_state_for_client(serv, tossing); - set_whose_turn(serv, tossing); - serv->state = tossing_phase_out; - } else { - set_state_for_client(serv, display_only_table); - serv->state = table; - } - } - } - } -} - -static void determine_server_state(struct server *serv) -{ - switch(serv->state) { - case no_players: - serv->state = first_player; - break; - case first_player: - if(check_playable_player_number(serv)) - serv->state = confirmation_waiting; - break; - case confirmation_waiting: - set_record_status_for_all(serv); - init_new_game(serv); - serv->state = start_game; - break; - case start_game: - set_state_for_client(serv, attack); - set_whose_turn(serv, attack); - set_record_status_for_all(serv); - serv->state = attack_phase_out; - break; - case attack_phase_out: - serv->state = attack_phase_in; - break; - case attack_phase_in: - case defense_phase_in: - case tossing_phase_in: - if(serv->state == attack_phase_in) - define_phase_after_attack(serv); - else if(serv->state == defense_phase_in) - define_phase_after_defense(serv); - else - /* all answers received or the limit on card tossing was reached */ - define_phase_after_tossing(serv); - set_record_status_for_all(serv); - update_card_quantity_arr(serv); - update_game_info(serv->gi, serv->connected_players_counter, - serv->shuffled_deck_size, serv->position_whose_turn); - break; - case table: - if(serv->turn_queue[1]->defense_lost) { - move_all_cards_to_defender(serv->cot, &serv->turn_queue[1]->deck); - move_turn_queue_two_players_ahead(serv->turn_queue, - serv->connected_players_counter); - } - else { - remove_cards_from_table(serv->cot); - shift_turn_queue_by_one(serv->turn_queue, - serv->connected_players_counter); - } - set_record_status_for_all(serv); - set_state_for_client(serv, attack); - set_whose_turn(serv, attack); - update_card_quantity_arr(serv); - deal_cards(serv->shuffled_deck, &serv->shuffled_deck_size, - serv->turn_queue, serv->connected_players_counter, - serv->card_quantity_arr); - serv->state = attack_phase_out; - break; - case defense_phase_out: - serv->state = defense_phase_in; - break; - case tossing_phase_out: - serv->state = tossing_phase_in; - break; - } - serv->change_server_state = 0; -} - -static int new_player_tracking_condition(enum server_states state) -{ - return state == no_players || state == first_player || - state == confirmation_waiting; -} -/* - * when accepting new players - */ -static int server_state_change_condition(struct server *serv) -{ - return - serv->state == no_players || - (serv->state == first_player && check_playable_player_number(serv)) || - (serv->state == confirmation_waiting && - is_max_playable_player_number(serv)); - -} - -static int accept_new_player(struct server *serv) -{ - int accept_result; - accept_result = accept_client(serv); - if(accept_result == -1) { - syslog(LOG_ERR, "accept error"); - return -1; - } - /* update info about connected players */ - set_record_status_for_all(serv); - if(server_state_change_condition(serv)) - serv->change_server_state = 1; - return 1; -} - -static void set_up_player_tracking(struct server *serv, fd_set *readfds, - fd_set *writefds) -{ - int i; - for(i = 0; i < serv->max_sess_arr_size; ++i) { - if(!serv->sess_arr[i]) - continue; - - switch(serv->state) { - case first_player: - if(serv->sess_arr[i]->record) - FD_SET(i, writefds); - break; - case confirmation_waiting: - FD_SET(i, readfds); - if(serv->sess_arr[i]->record) - FD_SET(i, writefds); - break; - case start_game: - case attack_phase_out: - case table: - case defense_phase_out: - case tossing_phase_out: - if(serv->sess_arr[i]->record) - FD_SET(i, writefds); - break; - case attack_phase_in: - if(serv->sess_arr[i]->state == attack) - FD_SET(i, readfds); - break; - case defense_phase_in: - if(serv->sess_arr[i]->state == defense) - FD_SET(i, readfds); - break; - case tossing_phase_in: - if(serv->sess_arr[i]->state == tossing && - serv->sess_arr[i]->tm == answer_wait) - FD_SET(i, readfds); - break; - case no_players: - {} - } - } -} - -static int check_server_state_change_conditions(int is_tossing_limit, - struct server *serv) -{ - switch(serv->state) { - case start_game: - case attack_phase_out: - case attack_phase_in: - case defense_phase_out: - case defense_phase_in: - case tossing_phase_out: - case table: - return 1; - case tossing_phase_in: - if(is_tossing_limit || - check_all_answers_were_received((const struct session**) - serv->turn_queue, - serv->connected_players_counter)) - return 1; - default: - return 0; - } - return 0; -} - -static void close_connection() -{ -} - -static void make_data_transfer(struct server *serv, fd_set *readfds, - fd_set *writefds) -{ - int i, result, tossing_limit = 0; - for(i = 0; i < serv->max_sess_arr_size; ++i) { - if(!serv->sess_arr[i]) - continue; - - switch(serv->state) { - case first_player: - if(FD_ISSET(i, writefds)) { - result = print_message_for_first_player(i); - serv->sess_arr[i]->record = 0; - } - break; - case confirmation_waiting: - if(FD_ISSET(i, writefds) && serv->sess_arr[i]->record) { - result = - print_connected_players(i, serv->connected_players_counter); - serv->sess_arr[i]->record = 0; - } - if(FD_ISSET(i, readfds)) { - result = check_readiness(serv->sess_arr[i]); - if(result == 1) - serv->change_server_state = 1; - } - break; - case start_game: - case attack_phase_out: - case defense_phase_out: - case tossing_phase_out: - case table: - if(FD_ISSET(i, writefds) && serv->sess_arr[i]->record) - result = print_game_part(serv->sess_arr[i], serv->gi); - serv->sess_arr[i]->record = 0; - break; - case attack_phase_in: - if(FD_ISSET(i, readfds)) - result = get_cards_from_attacker(serv->sess_arr[i], serv->cq); - break; - case defense_phase_in: - if(FD_ISSET(i, readfds)) - result = get_card_from_defender(serv->sess_arr[i], serv->cot, - serv->trump_suit); - break; - case tossing_phase_in: - if(FD_ISSET(i, readfds)) { - /* to determine that the player can no longer tossing */ - if(tossing_limit) - serv->sess_arr[i]->tm = cancel; - result = - get_cards_from_tossing_player(serv->sess_arr[i], - serv->turn_queue[1]->deck, - serv->cot, serv->cq); - if(result == 1 || result == 2) - serv->sess_arr[i]->tm = answer_got; - - if(result == 2) - tossing_limit = 1; - else if(result == 3) - serv->sess_arr[i]->tm = cancel; - } - break; - case no_players: - {} - } - } - if(serv->state == start_game || serv->state == table) - sleep(2); - if(check_server_state_change_conditions(tossing_limit, serv)) - serv->change_server_state = 1; - /* connection is closed */ - if(!result) - close_connection(); -} - -int main_loop(struct server *serv) -{ - int maxfd, accept_result; - fd_set readfds, writefds; - - for(;;) { - if(serv->change_server_state) - determine_server_state(serv); - FD_ZERO(&readfds); - FD_ZERO(&writefds); - - if(new_player_tracking_condition(serv->state)) { - FD_SET(serv->listen_socket, &readfds); - maxfd = serv->listen_socket; - } - - set_up_player_tracking(serv, &readfds, &writefds); - - select(maxfd + 1, &readfds, &writefds, NULL, NULL); - - if(FD_ISSET(serv->listen_socket, &readfds)) { - accept_result = accept_new_player(serv); - if(accept_result == -1) - return 4; - } - make_data_transfer(serv, &readfds, &writefds); - } -} - -/* - * 0 - error - * 1 - success - */ -static int init_server(struct server *serv, int port) -{ - int opt, i; - struct sockaddr_in addr; - - serv->listen_socket = socket(AF_INET, SOCK_STREAM, 0); - if(serv->listen_socket == -1) - return 0; - - opt = 1; - setsockopt(serv->listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, - sizeof(opt)); - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port); - - if(bind(serv->listen_socket, (struct sockaddr*) &addr, sizeof(addr)) == -1) - return 0; - - serv->sess_arr = malloc(sizeof(*serv->sess_arr) * - init_sess_arr_size); - serv->max_sess_arr_size = init_sess_arr_size; - for(i = 0; i < init_sess_arr_size; i++) - serv->sess_arr[i] = NULL; - - serv->state = no_players; - serv->change_server_state = 0; - serv->connected_players_counter = 0; - serv->shuffled_deck = NULL; - serv->shuffled_deck_size = max_shuffled_deck_size; - serv->gi = NULL; - serv->card_quantity_arr = NULL; - serv->cq = NULL; - serv->cot = NULL; - - listen(serv->listen_socket, listen_qlen); - return 1; -} - -#if 0 -static void demonization() -{ - int pid; - - close(0); - close(1); - close(2); - open("/dev/null", O_RDONLY); - open("/dev/null", O_WRONLY); - open("/dev/null", O_WRONLY); - chdir("/"); - pid = fork(); - if(pid) - exit(0); - setsid(); - pid = fork(); - if(pid) - exit(0); -} -#endif - -int main(int argc, char **argv) -{ - unsigned short port; - struct server serv; - - if(argc != 2) { - fprintf(stderr, - "Usage: \n"); - return 1; - } -#if 0 - demonization(); -#endif - srand(time(NULL)); -#if 0 - openlog("durak server", 0, LOG_USER); - syslog(LOG_INFO, "daemon started"); -#endif - port = strtol(argv[1], NULL, 10); - - if(!init_server(&serv, port)) { -#if 0 - syslog(LOG_ERR, "server initialization error"); -#endif - return 2; - } - return main_loop(&serv); -#if 0 - syslog(LOG_INFO, "server terminated"); - closelog(); -#endif -} -- cgit v1.2.3