/*! * Main loop of the internet protocol service */ void serve_clients_internet_protocol (global_status_type * global_status, global_option_type * global_option) { int player_index; for (player_index = 0; player_index < MAX_NUMBER_PLAYER; player_index++) { global_status->next_frame_to_send[player_index] = 1; global_status->input_value[player_index] = 0; } /* Allocate memory for the history */ init_internet_history (); /* Prepare memory releasing at the end of the program */ atexit (release_internet_history); init_frame_status (global_status, global_option); global_status->start_time = (double) SDL_GetTicks () / (double) SDL_TICKS_PER_SECOND; for (;;) { #if defined(DEBUG) fprintf (stderr, "Waiting for status packets while preparing frame %u\ntime = %u\n", global_status->frame_number, SDL_GetTicks ()); #endif /* Let packets accumulate for a short amount of time */ SDL_Delay (get_remaining_time (global_status)); #if defined(DEBUG) fprintf (stderr, "Finished sleeping, time = %u\n", SDL_GetTicks ()); #endif while (read_incoming_server_packet (global_status) != 0) { #if defined(DEBUG) fprintf (stderr, "Got a packet\n"); #endif /* Stores the incoming status */ store_remote_status_internet (global_status, global_option); } send_internet_digest (global_status, global_option); } /* While the above loop is infinite, this won't be called */ release_internet_history (); }
/*! * Main loop of the lan protocol service */ void serve_clients_lan_protocol (global_status_type * global_status, global_option_type * global_option) { init_frame_status (global_status, global_option); for (;;) { int number_ready_socket; #if defined(DEBUG) fprintf (stderr, "Waiting for status packets for frame %u\n", global_status->frame_number); #endif number_ready_socket = SDLNet_CheckSockets (global_status->server_socket_set, SERVER_SOCKET_TIMEOUT); if (number_ready_socket == -1) { fprintf (stderr, "Error in socket waiting (disconnection ?).\n"); break; } if (number_ready_socket == 1) { #if defined(DEBUG) fprintf (stderr, "Got a packet\n"); #endif /* We're awaiting a packet in the server socket */ if (read_incoming_server_packet (global_status)) { /* Stores the incoming status and updates clients status accordingly */ store_remote_status_lan (global_status, global_option); /* Sends packet (if needed) to client accordingly to their status */ send_digest_lan_packets (global_status, global_option); } } } }
/*! * main loop. Accept contribution from clients and dispatch digest of * the frame to all clients */ void serve_dispatch (global_option_type * global_option) { global_status_type global_status; int client_index; /* * Initialize global_status fields */ global_status.frame_number = 1; global_status.number_identified_players = 0; global_status.number_allocation_request = 0; #if defined(GTK) gtk_stop_asked = 0; #endif for (client_index = 0; client_index < MAX_NUMBER_PLAYER; client_index++) { global_status.player_status[client_index] = UNIDENTIFIED; } global_status.server_socket = SDLNet_UDP_Open (global_option->server_port); if (global_status.server_socket == NULL) { printf_screen ("Couldn't open UDP socket on port %d.\nCheck privileges and availability.\n", global_option->server_port); return; } /* global_status.server_socket is ready to serve our needs :) */ global_status.current_packet = SDLNet_AllocPacket (CLIENT_PACKET_SIZE); if (global_status.current_packet == NULL) { SDLNet_UDP_Close (global_status.server_socket); printf_screen ("Failed to allocate a buffer for receiving client packets (size: %d bytes) (Not enough memory ?)", CLIENT_PACKET_SIZE); return; } global_status.digest_packet = SDLNet_AllocPacket (SERVER_PACKET_SIZE); if (global_status.digest_packet == NULL) { SDLNet_UDP_Close (global_status.server_socket); SDLNet_FreePacket (global_status.digest_packet); printf_screen ("Failed to allocate a buffer for sending packets (size: %d bytes) (Not enough memory ?)", SERVER_PACKET_SIZE); return; } /* Allocate enough space for a single socket */ global_status.server_socket_set = SDLNet_AllocSocketSet (1); if (global_status.server_socket_set == NULL) { SDLNet_UDP_Close (global_status.server_socket); SDLNet_FreePacket (global_status.current_packet); SDLNet_FreePacket (global_status.digest_packet); printf_screen ("Couldn't allocate a socket set (not enough memory ?).\n"); return; } if (SDLNet_UDP_AddSocket (global_status.server_socket_set, global_status.server_socket) != 1) { SDLNet_UDP_Close (global_status.server_socket); SDLNet_FreePacket (global_status.current_packet); SDLNet_FreePacket (global_status.digest_packet); SDLNet_FreeSocketSet (global_status.server_socket_set); printf_screen ("Error when adding socket to socket set.\n"); return; } /* Identification loop */ /* * We're expecting identification packets until we've filled all slots, then * we can proceed to the real meat */ for (;;) { int number_ready_socket; #if defined(DEBUG) printf_screen ("Waiting for identification\n"); #endif if (read_incoming_server_packet (&global_status)) { identify_client (&global_status, global_option); if (count_remaining_slot (&global_status, global_option) == 0) { /* Perfect, we've finished the identification of all slots */ break; } printf_screen("%d slots open.\n", count_remaining_slot (&global_status, global_option)); /* Going back to the identification loop */ continue; } #if defined(GTK) gtk_iteration = GTK_SERVER_SOCKET_RATIO; do { number_ready_socket = SDLNet_CheckSockets (global_status.server_socket_set, SERVER_SOCKET_TIMEOUT / GTK_SERVER_SOCKET_RATIO); while (gtk_events_pending()) { if (gtk_main_iteration()) { gtk_stop_asked = 1; } } } while ( (number_ready_socket == 0) && (--gtk_iteration != 0) && !gtk_stop_asked); #else number_ready_socket = SDLNet_CheckSockets (global_status.server_socket_set, SERVER_SOCKET_TIMEOUT); #endif if (gtk_stop_asked) { break; } if (number_ready_socket == -1) { printf_screen ("Error in socket waiting (disconnection ?).\n"); break; } if (number_ready_socket == 1) { #if defined(DEBUG) printf_screen ("Got a packet\n"); #endif /* We're awaiting a packet in the server socket */ if (read_incoming_server_packet (&global_status)) { /* * If we haven't identified all clients yet, we're trying to use the current packet * to improve our knowledge of the typography */ identify_client (&global_status, global_option); if (count_remaining_slot (&global_status, global_option) == 0) { /* Perfect, we've finished the identification of all slots */ break; } printf_screen("%d slots open.\n", count_remaining_slot (&global_status, global_option)); } } } if (!gtk_stop_asked) { printf_screen ("Identification finished\n"); #if defined(DEBUG) for (client_index = 0; client_index < MAX_NUMBER_PLAYER; client_index++) { printf_screen ("Mapping[%d] = { { 0x%08X, %d }, %d }\n", client_index, global_status.input_mapping[client_index].address.host, global_status.input_mapping[client_index].address.port, global_status.input_mapping[client_index].remote_input_device); } #endif switch (global_option->type_server) { case LAN_PROTOCOL_TYPE: serve_clients_lan_protocol(&global_status, global_option); break; case INTERNET_PROTOCOL_TYPE: serve_clients_internet_protocol(&global_status, global_option); break; default: printf_screen("Internal error, unknown internal server type : %d\n", global_option->type_server); break; } } // gtk_stop_asked /* * Free resources */ SDLNet_FreePacket (global_status.current_packet); SDLNet_FreePacket (global_status.digest_packet); SDLNet_FreeSocketSet (global_status.server_socket_set); SDLNet_UDP_Close (global_status.server_socket); global_status.server_socket = NULL; }