back to scratko.xyz
aboutsummaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'server.c')
-rw-r--r--server.c733
1 files changed, 0 insertions, 733 deletions
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 <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <time.h>
-
-#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: <port>\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
-}