Exemplo n.º 1
0
/*!
 * 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;

}
Exemplo n.º 2
0
/*!
 * Process an identification request from a client, filling the interesting
 * fields in the global_status structure to find later the client
 */
void
identify_client (global_status_type * global_status,
		 global_option_type * global_option)
{

  int requested_slots;
  int allocated_slots;
  int slot_index;
  int already_allocated_slot_by_client;

  if (global_status->current_packet->len != PACKET_IDENTIFICATION_LENGTH)
    {
      /* Discarding invalid packet */
#if defined(DEBUG)
      fprintf (stderr,
	       "Invalid packet received when in identification phase (received length: %d, expected length: %d)\n",
	       global_status->current_packet->len,
	       PACKET_IDENTIFICATION_LENGTH);
#endif
      return;
    }

  if (global_status->current_packet->data[PACKET_IDENTIFIER] !=
      PACKET_IDENTIFICATION_ID)
    {
      /* Discarding invalid packet */
#if defined(DEBUG)
      fprintf (stderr,
	       "Invalid packet received when in identification phase (received ID: 0x%02x, expected ID: 0x%02x)\n",
	       global_status->current_packet->data[PACKET_IDENTIFIER],
	       PACKET_IDENTIFICATION_ID);
#endif
      return;
    }

  if (global_status->current_packet->data[PACKET_IDENTIFICATION_CHECKSUM] !=
      compute_checksum (global_status->current_packet->data,
			PACKET_IDENTIFIER, PACKET_IDENTIFICATION_CHECKSUM))
    {
      /* Discarding invalid packet */
#if defined(DEBUG)
      fprintf (stderr,
	       "Packet checksum received when in identification phase (received checksum: 0x%02x, expected checksum: 0x%02x)\n",
	       global_status->current_packet->
	       data[PACKET_IDENTIFICATION_CHECKSUM],
	       compute_checksum (global_status->current_packet->data,
				 PACKET_IDENTIFIER,
				 PACKET_IDENTIFICATION_CHECKSUM));
#endif
      return;
    }

  requested_slots =
    global_status->current_packet->
    data[PACKET_IDENTIFICATION_NUMBER_REQUESTED_SLOTS];

  allocated_slots =
    min (requested_slots,
	 count_remaining_slot (global_status, global_option));

  /* Check if it's a new request or a re-request (happens when the client didn't get the acknowledgement) */
  already_allocated_slot_by_client =
    compare_request_to_previous (global_status,
				 global_status->current_packet->address);

  if (already_allocated_slot_by_client != -1)
    {
      /* We already answered this client, we'll reacknowledge */
      send_identification_acknowledge_packet (global_status,
					      already_allocated_slot_by_client);

      return;
    }

  for (slot_index = global_status->number_identified_players;
       slot_index <
       global_status->number_identified_players + allocated_slots;
       slot_index++)
    {
      /* Set the address for identified player */
      global_status->input_mapping[slot_index].address.port =
	global_status->current_packet->address.port;

      global_status->input_mapping[slot_index].address.host =
	global_status->current_packet->address.host;


      /* Set the remote input device number */
      global_status->input_mapping[slot_index].remote_input_device =
	global_status->current_packet->
	data[PACKET_IDENTIFICATION_INPUT_DEVICE_INDEX + slot_index -
	     global_status->number_identified_players];

      /* Change status from UNIDENTIFIED */
      global_status->player_status[slot_index] = WAITING;
    }

  global_status->allocation_request[global_status->number_allocation_request].
    address.port = global_status->current_packet->address.port;

  global_status->allocation_request[global_status->number_allocation_request].
    address.host = global_status->current_packet->address.host;

  global_status->allocation_request[global_status->number_allocation_request].
    allocated_slots = allocated_slots;

  global_status->number_allocation_request++;

  global_status->number_identified_players += allocated_slots;

  send_identification_acknowledge_packet (global_status, allocated_slots);

}