[Tux4kids-commits] r1124 - tuxmath/branches/lan/server

David Bruce dbruce-guest at alioth.debian.org
Wed Jul 1 00:25:05 UTC 2009


Author: dbruce-guest
Date: 2009-07-01 00:25:05 +0000 (Wed, 01 Jul 2009)
New Revision: 1124

Added:
   tuxmath/branches/lan/server/server.c
Removed:
   tuxmath/branches/lan/server/server.c
Log:
fix of some issues in check_messages() that prevent
endless loop in server if client disconnects abruptly



Deleted: tuxmath/branches/lan/server/server.c
===================================================================
--- tuxmath/branches/lan/server/server.c	2009-07-01 00:06:26 UTC (rev 1123)
+++ tuxmath/branches/lan/server/server.c	2009-07-01 00:25:05 UTC (rev 1124)
@@ -1,750 +0,0 @@
-/*
-*  C Implementation: server.c
-*
-*       Description: Server program for LAN-based play in Tux,of Math Command.
-*
-*
-* Author: Akash Gangil, David Bruce, and the TuxMath team, (C) 2009
-* Developers list: <tuxmath-devel at lists.sourceforge.net>
-*
-* Copyright: See COPYING file that comes with this distribution.  (Briefly, GNU GPL).
-*
-* NOTE: This file was initially based on example code from The Game Programming Wiki
-* (http://gpwiki.org), in a tutorial covered by the GNU Free Documentation License 1.2.
-* No invariant sections were indicated, and no separate license for the example code
-* was listed. The author was also not listed. AFAICT,this scenario allows incorporation of
-* derivative works into a GPLv2+ project like TuxMath - David Bruce 
-*/
-
-
-// NOTE: here are some pseudo-code thoughts about structuring the server program - DSB:
-// 
-// int main()
-// {
-//   //All the stuff before starting the main loop:
-//   if (!setup_server())
-//   {
-//     //print error and exit...
-//   }
-// 
-//   while (!done)
-//   {
-//     //See if any clients trying to connect:
-//     //If we aren't playing a game yet, we take their name and add them to the client set,
-//     //if we have room.
-//     //If a game is in progress, we just tell them "sorry, call back later"
-//     check_for_new_clients();
-//     
-//     //Now check all the connected clients to see if we have any messages from them:
-//     check_client_messages();
-// 
-//   }
-// 
-//   //Free resources, call MC_EndGame(), and so forth:
-//   server_cleanup();
-// }
-// 
-// 
-// //This function will use SDLNet_CheckSockets() and SDLNet_SocketReady()
-// //Some of the messages will only be meaningful between games, and others will
-// //only be meaningful during games;
-// void check_client_messages(void)
-// {
-//   for (go through client set and handle active ones)
-//   {
-//     get_buffer_from_client();
-//     get_title_out_of_buffer();
-// 
-//     //Handle all the 'non-game'messages:
-//     if (strcmp(title, NON_GAME_FOO) == 0)
-//     {
-//       //do something (e.g. disconnect)
-//     }
-//     else if (strcmp(title, NON_GAME_BAR) == 0)
-//     {
-//       //do something else (e.g. start a new game)
-//     }
-// 
-//     //Now handle gameplay-related messages:
-//     if (strcmp(title, GAME_FOO) == 0)
-//     {
-//       //do something (e.g. client answered correctly)
-//     }
-//     else if (strcmp(title, GAME_BAR) == 0)
-//     {
-//       //do something else (e.g. client quits game)
-//     }
-// 
-//   }
-// }
-
-
-
-
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
- 
-#include "server.h" 
-#include "transtruct.h"
-#include "mathcards.h"
-
-
-#define MAX_CLIENTS 16
-
-TCPsocket server_sock = NULL; /* Socket descriptor for server            */
-TCPsocket temp_sock = NULL;        /* Just used when client can't be accepted */
-IPaddress ip;
-SDLNet_SocketSet client_set = NULL;
-static client_type client[MAX_CLIENTS];
-static int num_clients = 0;
-static int sockets_used = 0;
-static int numready = 0;
-static int game_in_progress = 0;
-MC_FlashCard flash;
-
-/* Local function prototypes: */
-int setup_server(void);
-void cleanup_server(void);
-int update_clients(void);
-int check_messages(void);
-int handle_client_game_msg(int i,char *buffer);
-void handle_client_nongame_msg(int i,char *buffer);
-int find_vacant_client(void);
-void game_msg_correct_answer(int i, int id);
-void game_msg_quit(int i);
-void game_msg_exit(int i);
-void start_game(int i);
-void ping_client(int i);
-int SendQuestion(MC_FlashCard flash, TCPsocket client_sock);
-int SendMessage(int message, int z, TCPsocket client_sock);
-
-int main(int argc, char **argv)
-{ 
-  int h;
-  int quit = 0, quit2;
-  char buffer[NET_BUF_LEN];
-  char buf[NET_BUF_LEN];
-  int command_type = -1, j;
-  static int i = 0;
-  static int initialize = 0;
-  int id,x;
-
-  printf("Started tuxmathserver, waiting for client to connect:\n>\n");
-
-
-  /*     ---------------- Setup: ---------------------------   */
-  if (!setup_server())
-  {
-    fprintf(stderr, "setup_server() failed - exiting.\n");
-    exit(EXIT_FAILURE);
-  }
- 
-  /*    ------------- Main server loop:  ------------------   */
-  while (!quit)
-  {
-    /* Now we check to see if anyone is trying to connect. */
-    num_clients = update_clients();
-    /* Check for any pending messages from clients already connected: */
-    quit=check_messages();
-  }
-   
-  /*   -----  Free resources before exiting: -------    */
-  cleanup_server();
-
-  return EXIT_SUCCESS;
-}
-
-
-/*********************************************************************/
-/*  "Private" (to server.c) functions                                */
-/*********************************************************************/
-
-
-// setup_server() - all the things needed to get server running:
-int setup_server(void)
-{
-  int i = 0;
-
-  for(i = 0; i < MAX_CLIENTS; i++)
-  {
-    client[i].game_ready = 0;   /* waiting for user to OK game start */
-    client[i].name[0] = '\0';   /* no nicknames yet                  */
-    client[i].sock = NULL;      /* sockets start out unconnected     */
-  }
-
-  //this sets up mathcards with hard-coded defaults - no settings
-  //read from config file here:
-  if (!MC_Initialize())
-  {
-    fprintf(stderr, "Could not initialize MathCards\n");
-    return 0;
-  }
-
-      
-  if (SDLNet_Init() < 0)
-  {
-    fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
-    return 0;
-  }
- 
-  /* Resolving the host using NULL make network interface to listen */
-  if (SDLNet_ResolveHost(&ip, NULL, DEFAULT_PORT) < 0)
-  {
-    fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
-    return 0;
-  }
- 
-  /* Open a connection with the IP provided (listen on the host's port) */
-  if (!(server_sock = SDLNet_TCP_Open(&ip)))
-  {
-    fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
-    return 0;
-  }
-
-  client_set = SDLNet_AllocSocketSet(MAX_CLIENTS);
-  if(!client_set)
-  {
-    printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
-    return 0;
-  }
- return 1;
-}
-
-
-
-//Free resources, closing sockets, call MC_EndGame(), and so forth:
-void cleanup_server(void)
-{
-  int j;
-  /* Close the client socket(s) */
-  
-  for(j = 0; j < MAX_CLIENTS; j++)
-  {
-    if(client[j].sock != NULL)
-    {
-      SDLNet_TCP_Close(client[j].sock);    //close all the client sockets one by one
-      client[j].sock = NULL;               // So we don't segfault in case cleanup()
-    }                                      // somehow gets called more than once.
-  } 
-
-  if (client_set != NULL)
-  {
-    SDLNet_FreeSocketSet(client_set);              //releasing the memory of the client socket set
-    client_set = NULL; //this helps us remember that this set is not allocated
-  } 
-
-  if(server_sock != NULL)
-  {
-    SDLNet_TCP_Close(server_sock);
-    server_sock = NULL;
-  }
-  SDLNet_Quit();
-
- /* Clean up mathcards heap memory */
-  MC_EndGame();
-}
-
-
-
-
-
-//update_clients() sees if anyone is trying to connect, and connects if a slot
-//is open and the game is not in progress. It returns the number of connected clients.
-//FIXME we need to be able to test to see if the clients are really still connected
-int update_clients(void)
-{
-  int slot = 0;
-  int x = 0;
-  char buffer[NET_BUF_LEN];
-
-  /* See if we have a pending connection: */
-  temp_sock = SDLNet_TCP_Accept(server_sock);
-  if (!temp_sock)  /* No one waiting to join - do nothing */
-  {
-    return num_clients;
-  }
-
-  // See if any slots are available:
-  slot = find_vacant_client();
-  if (slot == -1) /* No vacancies: */
-  {
-    snprintf(buffer, NET_BUF_LEN, 
-             "%s\n",
-             "Sorry, already have maximum number of clients connected\n");
-    x = SDLNet_TCP_Send(temp_sock, buffer, NET_BUF_LEN);
-    //hang up:
-    SDLNet_TCP_Close(temp_sock);
-    temp_sock = NULL;
-#ifdef LAN_DEBUG
-    printf("buffer sent:::: %d bytes\n", x);
-    printf("buffer is: %s\n", buffer);
-#endif
-    return num_clients;
-  }     
-
-  // If game already started, send our regrets:
-  if(game_in_progress)
-  {
-    snprintf(buffer, NET_BUF_LEN, 
-             "%s\n",
-             "Sorry the game has started...... =(\n");
-    x = SDLNet_TCP_Send(temp_sock, buffer, NET_BUF_LEN);
-    //hang up:
-    SDLNet_TCP_Close(temp_sock);
-    temp_sock = NULL;
-#ifdef LAN_DEBUG
-    printf("buffer sent:::: %d bytes\n", x);
-    printf("buffer is: %s\n", buffer);
-#endif
-    return num_clients;
-  }
-
-  // If we get to here, we have room for the new connection and the
-  // game is not in progress, so we connect:
-
-#ifdef LAN_DEBUG
-  printf("creating connection for client[%d].sock:\n", slot);
-#endif
-
-  sockets_used = SDLNet_TCP_AddSocket(client_set, temp_sock);
-  if(sockets_used == -1) //No way this should happen
-  {
-    printf("SDLNet_AddSocket: %s\n", SDLNet_GetError());
-    SDLNet_TCP_Close(temp_sock);
-    temp_sock = NULL;
-    return num_clients;
-  }
-  else if( SDLNet_TCP_Recv(temp_sock, buffer, NET_BUF_LEN) > 0)
-  {
-    client[slot].sock = temp_sock;
-    strncpy(client[slot].name, buffer, NAME_SIZE);
-    num_clients = sockets_used;
-    printf(" JOINED  :::   %s\n", client[slot].name);
-    printf("slot %d  is %d\n",slot,client[slot].game_ready); 
-        //FIXME AFAICT, num_clients and i are always the same /* ya they are same , but would have to check for it*/
-  }
-  /* Now we can communicate with the client using client[i].sock socket
-  /* serv_sock will remain opened waiting other connections */
-    
-
-#ifdef LAN_DEBUG
-  /* Get the remote address */
-  {
-    IPaddress* client_ip = NULL;
-    client_ip = SDLNet_TCP_GetPeerAddress(client[slot].sock);
-    if (client_ip != NULL)
-    /* Print the address, converting in the host format */
-    {
-      printf("Client connected\n>\n");
-      printf("Client: IP = %x, Port = %d\n",
-             SDLNet_Read32(&client_ip->host),
-             SDLNet_Read16(&client_ip->port));
-    }
-    else
-      fprintf(stderr, "SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError());
-  }
-#endif
-
-  return num_clients;
-}
-
-
-// check_messages() is where we look at the client socket set to see which 
-// have sent us messages. This function is used in each server loop whether
-// or not a math game is in progress (although we expect different messages
-// during a game from those encountered outside of a game)
-
-int check_messages(void)
-{
-  int i = 0;
-  int actives = 0;
-  int msg_found = 0;
-  char buffer[NET_BUF_LEN];
-
-  /* Check the client socket set for activity: */
-  actives = SDLNet_CheckSockets(client_set, 0);
-  if(actives == -1)
-  {
-    printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
-    //most of the time this is a system error, where perror might help you.
-    perror("SDLNet_CheckSockets");
-  }
-
-  else if(actives) 
-  {
-#ifdef LAN_DEBUG
-    printf("There are %d sockets with activity\n", actives);
-#endif
-
-    // check all sockets with SDLNet_SocketReady and handle the active ones.
-    // NOTE we have to check all the slots in the set because
-    // the set will become discontinuous if someone disconnects
-    for(i = 0; i < MAX_CLIENTS; i++)
-    {
-      if((client[i].sock != NULL)
-        && (SDLNet_SocketReady(client[i].sock))) 
-      {
-#ifdef LAN_DEBUG
-        printf("client socket %d is ready\n", i);
-#endif
-        if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
-        {
-#ifdef LAN_DEBUG
-          printf("buffer received from client %d is: %s\n", i, buffer);
-#endif
-          msg_found++;
-
-          /* Here we pass the client number and the message buffer */
-          /* to a suitable function for further action:                */
-           if(game_in_progress==1)
-           {
-            if(handle_client_game_msg(i, buffer))
-            return(1);
-           }
-           if(game_in_progress==0)
-           handle_client_nongame_msg(i,buffer);
-
-        }
-      }
-    }  // end of for() loop - all client sockets checked
-    // Make sure all the active sockets reported by SDLNet_CheckSockets()
-    // are accounted for:
-    if(actives == 0)
-    {
-      printf("Warning: SDLNet_CheckSockets() reported %d active sockets,\n"
-             "but only %d messages received.\n", actives, msg_found);
-      /* We can investigate further - maybe ping all the sockets, etc. */
-      for(i = 0; i < MAX_CLIENTS; i++)
-      {
-        ping_client(i);
-      }
-    
-   
-      /* Check the client socket set for activity: */
-      actives = SDLNet_CheckSockets(client_set, 5000);
-      if(actives == 0)
-      {
-        printf("No clients , All clients have disconnected...=(\n");
-      }
-
-      else if(actives == -1)
-      {
-        printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
-        //most of the time this is a system error, where perror might help you.
-        perror("SDLNet_CheckSockets");
-      }
-
-      else if(actives) 
-      {
-#ifdef LAN_DEBUG
-       printf("There are %d sockets with activity\n", actives);
-#endif
-
-       // check all sockets with SDLNet_SocketReady and handle the active ones.
-       // NOTE we have to check all the slots in the set because
-       // the set will become discontinuous if someone disconnects
-       for(i = 0; i < MAX_CLIENTS; i++)
-       {
-         if((client[i].sock != NULL)
-            && (SDLNet_SocketReady(client[i].sock))) 
-         {
-#ifdef LAN_DEBUG
-           printf("client socket %d is ready\n", i);
-#endif
-           if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
-           {
-#ifdef LAN_DEBUG
-             printf("buffer received from client %d is: %s\n", i, buffer);
-#endif
-             if(strncmp(buffer,"PING_BACK",9))
-             printf("%s is connected =) \n",client[i].name);       
-           }
-         }
-       }
-      }
-    }
-  }
-}
-
-void handle_client_nongame_msg(int i,char *buffer)
-{
-  if(strncmp(buffer, "START_GAME", 10) == 0)
-  {
-    start_game(i);
-  }
-}
-
-int handle_client_game_msg(int i , char *buffer)
-{
-  int id;
-  char command[NET_BUF_LEN];
-
-#ifdef LAN_DEBUG  
-  printf("Buffer received from client: %s\n", buffer);
-#endif
-  sscanf (buffer,"%s %d\n",
-                  command,
-                  &id);
-
-  if(strncmp(command, "CORRECT_ANSWER", 14) == 0)
-  {
-    game_msg_correct_answer(i,id);
-  }                            
-
-  else if(strncmp(command, "exit",4) == 0) /* Terminate this connection */
-  {
-    game_msg_exit(i);
-  }
-
-  else if(strncmp(command, "quit",4) == 0) /* Quit the program */
-  {
-    game_msg_quit(i);
-    return(1);
-  }
-
-  return(0);
-}
-
-void game_msg_correct_answer(int i,int id)
-{
-  int n; 
-  printf("question id %d was answered correctly by %s",id,client[i].name);             
-  if (!MC_NextQuestion(&flash))
-  { 
-    /* no more questions available */
-    printf("MC_NextQuestion() returned NULL - no questions available\n");
-  }
-  else
-  {                                     
-#ifdef LAN_DEBUG
-    printf("WILL SEND >>\n");  
-    printf("QUESTION_ID       :      %d\n", flash.question_id);
-    printf("FORMULA_STRING    :      %s\n", flash.formula_string);
-    printf("ANSWER STRING     :      %s\n", flash.answer_string);
-    printf("ANSWER            :      %d\n",flash.answer);
-    printf("DIFFICULTY        :      %d\n",flash.difficulty);
-#endif
-  }
-                  
-  for(n = 0; n < num_clients && client[n].sock; n++)
-  {
-    if(!SendQuestion(flash,client[n].sock))
-    {
-      printf("Unable to send Question\n");
-    }
-  } 
-
-}
-
-void ping_client(int i)
-{
-  char buf[NET_BUF_LEN];
-  char msg[NET_BUF_LEN];
-  int x;
-
-  sprintf(msg,"%s", "PING\n");
-
-  snprintf(buf, NET_BUF_LEN, "%s\t%s\n", "SEND_MESSAGE", msg);
-  x = SDLNet_TCP_Send(client[i].sock, buf, NET_BUF_LEN);
-
-//#ifdef LAN_DEBUG
-  printf("buf is: %s\n", buf);
-  printf("SendMessage() - buf sent:::: %d bytes\n", x);
-//#endif
-}
-
-
-void game_msg_exit(int i)
-{
-  printf("LEFT the GAME : %s",client[i].name);
-  client[i].game_ready=0;
-  SDLNet_TCP_DelSocket(client_set,client[i].sock);
-  SDLNet_TCP_Close(client[i].sock);
-  printf("Terminating client connection\n");
-}
-
-
-void game_msg_quit(int i)
-{
-  printf("Server has been shut down by %s",client[i].name); 
-  client[i].game_ready=0;
-  SDLNet_TCP_DelSocket(client_set,client[i].sock);
-  SDLNet_TCP_Close(client[i].sock);
-  printf("Quit program....Server is shutting down...\n");
-  exit(9);                           // '9' means exit ;)  (just taken an arbitary no:)
-}
-
-
-void start_game(int i)
-{
-  char buf[NET_BUF_LEN];
-  char buffer[NET_BUF_LEN];
-  int x,j;
-  game_in_progress = 1;  //setting the game_in_progress flag to '1'
-  snprintf(buf, NET_BUF_LEN,
-                "%s\n",
-                "Success");  //FIXME what did we succeed at? This is basically a sort of handshaking signal , although it is not much needed here , but since we have a blocking recv call in the client for the case of game_in_progress , so no client join , therefore it is in accordance with that SDL_NetRecv()
-
-  x = SDLNet_TCP_Send(client[i].sock, buf, sizeof(buf));
-  client[i].game_ready = 1; // Means this player is ready to start game
-
-  /*FIXME this will only work if the clients are in a contiguous series starting */
-  /* at client[0].                                                             */
-  /* Basically , when the clients are allocated sockets , they are allocated contiguos
-     locations  starting from client[0] , so I dont think this will fail anytime.*/
-
-  /*This loop sees that the game starts only when all the players are ready */
-  for(j = 0; j < num_clients; j++)
-  {
-    if(client[j].game_ready != 1)
-    {
-      if (SDLNet_TCP_Recv(client[j].sock, buffer, NET_BUF_LEN) > 0)
-      {
-        if(strncmp(buffer, "START_GAME", 10) == 0)
-        {
-          client[j].game_ready = 1;
-          snprintf(buf, NET_BUF_LEN, 
-                "%s\n",
-                "Success");
-          x = SDLNet_TCP_Send(client[j].sock, buf, NET_BUF_LEN);
-        }
-      }
-    }
-  }
-
-  /* If no players join the game (should not happen) */
-  if(num_clients == 0)
-  {
-    printf("There were no players........=(\n");
-    cleanup_server();
-    exit(1);
-  }
-
-#ifdef LAN_DEBUG
-  printf("We have %d players.......\n",sockets_used);
-#endif
-
-
-  //Start a new math game as far as mathcards is concerned:
-  if (!MC_StartGame())
-  {
-    fprintf(stderr, "\nMC_StartGame() failed!");
-    exit(1);
-  }
-
-  game_in_progress = 1;
-
-  if (!MC_NextQuestion(&flash))
-  { 
-    /* no more questions available */
-    printf("MC_NextQuestion() returned NULL - no questions available\n");
-    exit(1);
-  }
-  else
-  {                                     
-#ifdef LAN_DEBUG
-    printf("WILL SEND >>\n");  
-    printf("QUESTION_ID       :      %d\n", flash.question_id);
-    printf("FORMULA_STRING    :      %s\n", flash.formula_string);
-    printf("ANSWER STRING     :      %s\n", flash.answer_string);
-    printf("ANSWER            :      %d\n",flash.answer);
-    printf("DIFFICULTY        :      %d\n",flash.difficulty);
-#endif
-  }
-
-  for(j = 0; j < num_clients; j++)
-  {
-    if(!SendQuestion(flash, client[j].sock))
-    {
-      printf("Unable to send Question to %s\n", client[j].name);
-    }
-  } 
-
-
-}
-//Returns the index of the first vacant client, or -1 if all clients full
-int find_vacant_client(void)
-{
-  int i = 0;
-  while (client[i].sock && i < MAX_CLIENTS)
-    i++;
-  if (i == MAX_CLIENTS)
-  {
-    fprintf(stderr, "All clients checked, none vacant\n");
-    i = -1;
-  }
-  return i;
-}
-
-
-
-
-//function to send a flashcard(question) from the server to the client
-int SendQuestion(MC_FlashCard flash,TCPsocket client_sock)
-{
-  int x;
-
-  char buf[NET_BUF_LEN];
-  snprintf(buf, NET_BUF_LEN, 
-                "%s\t%d\t%d\t%d\t%s\t%s\n",
-                "SEND_QUESTION",
-                flash.question_id,
-                flash.difficulty,
-                flash.answer,
-                flash.answer_string,
-                flash.formula_string);
-  x = SDLNet_TCP_Send(client_sock, buf, sizeof(buf));
-
-#ifdef LAN_DEBUG
-  printf("SendQuestion() - buf sent:::: %d bytes\n", x);
-  printf("buf is: %s\n", buf);
-#endif
-
-  if (x == 0)
-    return 0;
-  return 1;
-}
-
-
-/*Function to send any messages to the client be it any warnings
-  or anything the client is made to be informed*/
-int SendMessage(int message, int z,TCPsocket client_sock)         
-{
- int x, len;
- char buf[NET_BUF_LEN];
- char msg[100];  
-
- /* Create appropriate message: */
-  switch(message)
-  {
-    case NO_QUESTION_LIST:
-      sprintf(msg,"%s", "Please! first setup the question list by typing <a>\n");
-      break;
-    case ANSWER_CORRECT:
-      sprintf(msg,"%s %d %s", "Question ID:",
-              z, "was answered correctly by the client\n");
-      break;
-   case LIST_SET_UP:
-      sprintf(msg,"%s", "Question list was successfully setup\n");
-      break;
-   default :
-     fprintf(stderr, "SendMessage() - unrecognized message type\n");
-     return 0;
-  }
-  //transmit:
-  snprintf(buf, NET_BUF_LEN, "%s\t%s\n", "SEND_MESSAGE", msg);
-  x = SDLNet_TCP_Send(client_sock, buf, NET_BUF_LEN);
-
-#ifdef LAN_DEBUG
-  printf("buf is: %s\n", buf);
-  printf("SendMessage() - buf sent:::: %d bytes\n", x);
-#endif
-
-  return 1;
-}
-
-

Added: tuxmath/branches/lan/server/server.c
===================================================================
--- tuxmath/branches/lan/server/server.c	                        (rev 0)
+++ tuxmath/branches/lan/server/server.c	2009-07-01 00:25:05 UTC (rev 1124)
@@ -0,0 +1,839 @@
+/*
+*  C Implementation: server.c
+*
+*       Description: Server program for LAN-based play in Tux,of Math Command.
+*
+*
+* Author: Akash Gangil, David Bruce, and the TuxMath team, (C) 2009
+* Developers list: <tuxmath-devel at lists.sourceforge.net>
+*
+* Copyright: See COPYING file that comes with this distribution.  (Briefly, GNU GPL).
+*
+* NOTE: This file was initially based on example code from The Game Programming Wiki
+* (http://gpwiki.org), in a tutorial covered by the GNU Free Documentation License 1.2.
+* No invariant sections were indicated, and no separate license for the example code
+* was listed. The author was also not listed. AFAICT,this scenario allows incorporation of
+* derivative works into a GPLv2+ project like TuxMath - David Bruce 
+*/
+
+
+// NOTE: here are some pseudo-code thoughts about structuring the server program - DSB:
+// 
+// int main()
+// {
+//   //All the stuff before starting the main loop:
+//   if (!setup_server())
+//   {
+//     //print error and exit...
+//   }
+// 
+//   while (!done)
+//   {
+//     //See if any clients trying to connect:
+//     //If we aren't playing a game yet, we take their name and add them to the client set,
+//     //if we have room.
+//     //If a game is in progress, we just tell them "sorry, call back later"
+//     check_for_new_clients();
+//     
+//     //Now check all the connected clients to see if we have any messages from them:
+//     check_client_messages();
+// 
+//   }
+// 
+//   //Free resources, call MC_EndGame(), and so forth:
+//   server_cleanup();
+// }
+// 
+// 
+// //This function will use SDLNet_CheckSockets() and SDLNet_SocketReady()
+// //Some of the messages will only be meaningful between games, and others will
+// //only be meaningful during games;
+// void check_client_messages(void)
+// {
+//   for (go through client set and handle active ones)
+//   {
+//     get_buffer_from_client();
+//     get_title_out_of_buffer();
+// 
+//     //Handle all the 'non-game'messages:
+//     if (strcmp(title, NON_GAME_FOO) == 0)
+//     {
+//       //do something (e.g. disconnect)
+//     }
+//     else if (strcmp(title, NON_GAME_BAR) == 0)
+//     {
+//       //do something else (e.g. start a new game)
+//     }
+// 
+//     //Now handle gameplay-related messages:
+//     if (strcmp(title, GAME_FOO) == 0)
+//     {
+//       //do something (e.g. client answered correctly)
+//     }
+//     else if (strcmp(title, GAME_BAR) == 0)
+//     {
+//       //do something else (e.g. client quits game)
+//     }
+// 
+//   }
+// }
+
+
+
+
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+ 
+#include "server.h" 
+#include "transtruct.h"
+#include "mathcards.h"
+
+
+#define MAX_CLIENTS 16
+
+TCPsocket server_sock = NULL; /* Socket descriptor for server            */
+TCPsocket temp_sock = NULL;        /* Just used when client can't be accepted */
+IPaddress ip;
+SDLNet_SocketSet client_set = NULL;
+static client_type client[MAX_CLIENTS];
+static int num_clients = 0;
+static int sockets_used = 0;
+static int numready = 0;
+static int game_in_progress = 0;
+static int quit = 0; 
+MC_FlashCard flash;
+
+/* Local function prototypes: */
+int setup_server(void);
+void cleanup_server(void);
+int update_clients(void);
+int check_messages(void);
+int handle_client_game_msg(int i,char *buffer);
+void handle_client_nongame_msg(int i,char *buffer);
+int find_vacant_client(void);
+void remove_client(int i);
+void game_msg_correct_answer(int i, int id);
+void game_msg_quit(int i);
+void game_msg_exit(int i);
+void start_game(int i);
+void ping_client(int i);
+int SendQuestion(MC_FlashCard flash, TCPsocket client_sock);
+int SendMessage(int message, int z, TCPsocket client_sock);
+
+int main(int argc, char **argv)
+{ 
+  int h;
+  int quit2;
+  char buffer[NET_BUF_LEN];
+  char buf[NET_BUF_LEN];
+  int command_type = -1, j;
+  static int i = 0;
+  static int initialize = 0;
+  int id,x;
+
+  printf("Started tuxmathserver, waiting for client to connect:\n>\n");
+
+
+  /*     ---------------- Setup: ---------------------------   */
+  if (!setup_server())
+  {
+    fprintf(stderr, "setup_server() failed - exiting.\n");
+    exit(EXIT_FAILURE);
+  }
+ 
+  /*    ------------- Main server loop:  ------------------   */
+  while (!quit)
+  {
+    /* Now we check to see if anyone is trying to connect. */
+    num_clients = update_clients();
+    /* Check for any pending messages from clients already connected: */
+    check_messages();
+  }
+   
+  /*   -----  Free resources before exiting: -------    */
+  cleanup_server();
+
+  return EXIT_SUCCESS;
+}
+
+
+/*********************************************************************/
+/*  "Private" (to server.c) functions                                */
+/*********************************************************************/
+
+
+// setup_server() - all the things needed to get server running:
+int setup_server(void)
+{
+  int i = 0;
+
+  for(i = 0; i < MAX_CLIENTS; i++)
+  {
+    client[i].game_ready = 0;   /* waiting for user to OK game start */
+    client[i].name[0] = '\0';   /* no nicknames yet                  */
+    client[i].sock = NULL;      /* sockets start out unconnected     */
+  }
+
+  //this sets up mathcards with hard-coded defaults - no settings
+  //read from config file here:
+  if (!MC_Initialize())
+  {
+    fprintf(stderr, "Could not initialize MathCards\n");
+    return 0;
+  }
+
+      
+  if (SDLNet_Init() < 0)
+  {
+    fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
+    return 0;
+  }
+ 
+  /* Resolving the host using NULL make network interface to listen */
+  if (SDLNet_ResolveHost(&ip, NULL, DEFAULT_PORT) < 0)
+  {
+    fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
+    return 0;
+  }
+ 
+  /* Open a connection with the IP provided (listen on the host's port) */
+  if (!(server_sock = SDLNet_TCP_Open(&ip)))
+  {
+    fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
+    return 0;
+  }
+
+  client_set = SDLNet_AllocSocketSet(MAX_CLIENTS);
+  if(!client_set)
+  {
+    printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
+    return 0;
+  }
+ return 1;
+}
+
+
+
+//Free resources, closing sockets, call MC_EndGame(), and so forth:
+void cleanup_server(void)
+{
+  int j;
+  /* Close the client socket(s) */
+  
+  for(j = 0; j < MAX_CLIENTS; j++)
+  {
+    if(client[j].sock != NULL)
+    {
+      SDLNet_TCP_Close(client[j].sock);    //close all the client sockets one by one
+      client[j].sock = NULL;               // So we don't segfault in case cleanup()
+    }                                      // somehow gets called more than once.
+  } 
+
+  if (client_set != NULL)
+  {
+    SDLNet_FreeSocketSet(client_set);              //releasing the memory of the client socket set
+    client_set = NULL; //this helps us remember that this set is not allocated
+  } 
+
+  if(server_sock != NULL)
+  {
+    SDLNet_TCP_Close(server_sock);
+    server_sock = NULL;
+  }
+  SDLNet_Quit();
+
+ /* Clean up mathcards heap memory */
+  MC_EndGame();
+}
+
+
+
+
+
+//update_clients() sees if anyone is trying to connect, and connects if a slot
+//is open and the game is not in progress. It returns the number of connected clients.
+//FIXME we need to be able to test to see if the clients are really still connected
+int update_clients(void)
+{
+  int slot = 0;
+  int x = 0;
+  char buffer[NET_BUF_LEN];
+
+  /* See if we have a pending connection: */
+  temp_sock = SDLNet_TCP_Accept(server_sock);
+  if (!temp_sock)  /* No one waiting to join - do nothing */
+  {
+    return num_clients;
+  }
+
+  // See if any slots are available:
+  slot = find_vacant_client();
+  if (slot == -1) /* No vacancies: */
+  {
+    snprintf(buffer, NET_BUF_LEN, 
+             "%s\n",
+             "Sorry, already have maximum number of clients connected\n");
+    x = SDLNet_TCP_Send(temp_sock, buffer, NET_BUF_LEN);
+    //hang up:
+    SDLNet_TCP_Close(temp_sock);
+    temp_sock = NULL;
+#ifdef LAN_DEBUG
+    printf("buffer sent:::: %d bytes\n", x);
+    printf("buffer is: %s\n", buffer);
+#endif
+    return num_clients;
+  }     
+
+  // If game already started, send our regrets:
+  if(game_in_progress)
+  {
+    snprintf(buffer, NET_BUF_LEN, 
+             "%s\n",
+             "Sorry the game has started...... =(\n");
+    x = SDLNet_TCP_Send(temp_sock, buffer, NET_BUF_LEN);
+    //hang up:
+    SDLNet_TCP_Close(temp_sock);
+    temp_sock = NULL;
+#ifdef LAN_DEBUG
+    printf("buffer sent:::: %d bytes\n", x);
+    printf("buffer is: %s\n", buffer);
+#endif
+    return num_clients;
+  }
+
+  // If we get to here, we have room for the new connection and the
+  // game is not in progress, so we connect:
+
+#ifdef LAN_DEBUG
+  printf("creating connection for client[%d].sock:\n", slot);
+#endif
+
+  client[slot].sock = temp_sock;
+
+  /* We are receiving the client's name that was entered: */
+  if( SDLNet_TCP_Recv(client[slot].sock, buffer, NET_BUF_LEN) > 0)
+  {
+    strncpy(client[slot].name, buffer, NAME_SIZE);
+    num_clients = sockets_used;
+    printf(" JOINED  :::   %s\n", client[slot].name);
+    printf("slot %d  is %d\n",slot,client[slot].game_ready); 
+
+    /* Add client socket to set: */
+    sockets_used = SDLNet_TCP_AddSocket(client_set, client[slot].sock);
+    if(sockets_used == -1) //No way this should happen
+    {
+      printf("SDLNet_AddSocket: %s\n", SDLNet_GetError());
+      remove_client(slot);
+      return num_clients;
+    }
+  }
+  else 
+  {
+    printf("SDLNet_TCP_Recv() failed");
+    remove_client(slot);
+  }
+  /* Now we can communicate with the client using client[i].sock socket
+  /* serv_sock will remain opened waiting other connections */
+    
+
+#ifdef LAN_DEBUG
+  /* Get the remote address */
+  {
+    IPaddress* client_ip = NULL;
+    client_ip = SDLNet_TCP_GetPeerAddress(client[slot].sock);
+    if (client_ip != NULL)
+    /* Print the address, converting in the host format */
+    {
+      printf("Client connected\n>\n");
+      printf("Client: IP = %x, Port = %d\n",
+             SDLNet_Read32(&client_ip->host),
+             SDLNet_Read16(&client_ip->port));
+    }
+    else
+      fprintf(stderr, "SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError());
+  }
+#endif
+
+  return num_clients;
+}
+
+
+
+// check_messages() is where we look at the client socket set to see which 
+// have sent us messages. This function is used in each server loop whether
+// or not a math game is in progress (although we expect different messages
+// during a game from those encountered outside of a game)
+
+int check_messages(void)
+{
+  int i = 0;
+  int actives = 0;
+  int ready_found = 0;
+  char buffer[NET_BUF_LEN];
+
+  /* Check the client socket set for activity: */
+  actives = SDLNet_CheckSockets(client_set, 0);
+  if(actives == -1)
+  {
+    printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
+    //most of the time this is a system error, where perror might help you.
+    perror("SDLNet_CheckSockets");
+  }
+
+  else if(actives) 
+  {
+#ifdef LAN_DEBUG
+    printf("There are %d sockets with activity\n", actives);
+#endif
+
+    // check all sockets with SDLNet_SocketReady and handle the active ones.
+    // NOTE we have to check all the slots in the set because
+    // the set will become discontinuous if someone disconnects
+    for(i = 0; i < MAX_CLIENTS; i++)
+    {
+      if((client[i].sock != NULL)
+        && (SDLNet_SocketReady(client[i].sock))) 
+      { 
+        ready_found++;
+
+#ifdef LAN_DEBUG
+        printf("client socket %d is ready\n", i);
+#endif
+        if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
+        {
+#ifdef LAN_DEBUG
+          printf("buffer received from client %d is: %s\n", i, buffer);
+#endif
+
+          /* Here we pass the client number and the message buffer */
+          /* to a suitable function for further action:                */
+          if(game_in_progress)
+            handle_client_game_msg(i, buffer);
+          else
+            handle_client_nongame_msg(i, buffer);
+        }
+        else  // Socket activity but cannot receive - client invalid
+        {
+          printf("Client %d active but receive failed - apparently disconnected\n>\n", i);
+          remove_client(i);
+        }
+      }
+    }  // end of for() loop - all client sockets checked
+    // Make sure all the active sockets reported by SDLNet_CheckSockets()
+    // are accounted for:
+    if(actives != ready_found)
+    {
+      printf("Warning: SDLNet_CheckSockets() reported %d active sockets,\n"
+             "but only %d detected by SDLNet_SocketReady()\n", actives, ready_found);
+      /* We can investigate further - maybe ping all the sockets, etc. */
+
+    }
+  }
+}
+
+
+
+void handle_client_nongame_msg(int i,char *buffer)
+{
+  if(strncmp(buffer, "START_GAME", 10) == 0)
+  {
+    start_game(i);
+  }
+}
+
+int handle_client_game_msg(int i , char *buffer)
+{
+  int id;
+  char command[NET_BUF_LEN];
+
+#ifdef LAN_DEBUG  
+  printf("Buffer received from client: %s\n", buffer);
+#endif
+  sscanf (buffer,"%s %d\n",
+                  command,
+                  &id);
+
+  if(strncmp(command, "CORRECT_ANSWER", 14) == 0)
+  {
+    game_msg_correct_answer(i,id);
+  }                            
+
+  else if(strncmp(command, "exit",4) == 0) /* Terminate this connection */
+  {
+    game_msg_exit(i);
+  }
+
+  else if(strncmp(command, "quit",4) == 0) /* Quit the program */
+  {
+    game_msg_quit(i);
+    return(1);
+  }
+
+  return(0);
+}
+
+
+void game_msg_correct_answer(int i,int id)
+{
+  int n; 
+  printf("question id %d was answered correctly by %s",id,client[i].name);             
+  if (!MC_NextQuestion(&flash))
+  { 
+    /* no more questions available */
+    printf("MC_NextQuestion() returned NULL - no questions available\n");
+  }
+  else
+  {                                     
+#ifdef LAN_DEBUG
+    printf("WILL SEND >>\n");  
+    printf("QUESTION_ID       :      %d\n", flash.question_id);
+    printf("FORMULA_STRING    :      %s\n", flash.formula_string);
+    printf("ANSWER STRING     :      %s\n", flash.answer_string);
+    printf("ANSWER            :      %d\n",flash.answer);
+    printf("DIFFICULTY        :      %d\n",flash.difficulty);
+#endif
+  }
+                  
+  for(n = 0; n < num_clients && client[n].sock; n++)
+  {
+    if(!SendQuestion(flash,client[n].sock))
+    {
+      printf("Unable to send Question\n");
+    }
+  } 
+
+}
+
+void ping_client(int i)
+{
+  char buf[NET_BUF_LEN];
+  char msg[NET_BUF_LEN];
+  int x;
+
+  sprintf(msg,"%s", "PING\n");
+
+  snprintf(buf, NET_BUF_LEN, "%s\t%s\n", "SEND_MESSAGE", msg);
+  x = SDLNet_TCP_Send(client[i].sock, buf, NET_BUF_LEN);
+
+//#ifdef LAN_DEBUG
+  printf("buf is: %s\n", buf);
+  printf("SendMessage() - buf sent:::: %d bytes\n", x);
+//#endif
+}
+
+
+void game_msg_exit(int i)
+{
+  printf("LEFT the GAME : %s",client[i].name);
+  remove_client(i);
+}
+
+
+void game_msg_quit(int i)
+{
+  printf("Server has been shut down by %s\n",client[i].name); 
+  cleanup_server();
+  exit(9);                           // '9' means exit ;)  (just taken an arbitary no:)
+}
+
+
+void start_game(int i)
+{
+  char buf[NET_BUF_LEN];
+  char buffer[NET_BUF_LEN];
+  int x,j;
+  game_in_progress = 1;  //setting the game_in_progress flag to '1'
+  snprintf(buf, NET_BUF_LEN,
+                "%s\n",
+                "Success");  //FIXME what did we succeed at? This is basically a sort of handshaking signal , although it is not much needed here , but since we have a blocking recv call in the client for the case of game_in_progress , so no client join , therefore it is in accordance with that SDL_NetRecv()
+
+  x = SDLNet_TCP_Send(client[i].sock, buf, sizeof(buf));
+  client[i].game_ready = 1; // Means this player is ready to start game
+
+  /*FIXME this will only work if the clients are in a contiguous series starting */
+  /* at client[0].                                                             */
+  /* Basically , when the clients are allocated sockets , they are allocated contiguos
+     locations  starting from client[0] , so I dont think this will fail anytime.*/
+
+  /*This loop sees that the game starts only when all the players are ready */
+  for(j = 0; j < num_clients; j++)
+  {
+    if(client[j].game_ready != 1)
+    {
+      if (SDLNet_TCP_Recv(client[j].sock, buffer, NET_BUF_LEN) > 0)
+      {
+        if(strncmp(buffer, "START_GAME", 10) == 0)
+        {
+          client[j].game_ready = 1;
+          snprintf(buf, NET_BUF_LEN, 
+                "%s\n",
+                "Success");
+          x = SDLNet_TCP_Send(client[j].sock, buf, NET_BUF_LEN);
+        }
+      }
+    }
+  }
+
+  /* If no players join the game (should not happen) */
+  if(num_clients == 0)
+  {
+    printf("There were no players........=(\n");
+    cleanup_server();
+    exit(1);
+  }
+
+#ifdef LAN_DEBUG
+  printf("We have %d players.......\n",sockets_used);
+#endif
+
+
+  //Start a new math game as far as mathcards is concerned:
+  if (!MC_StartGame())
+  {
+    fprintf(stderr, "\nMC_StartGame() failed!");
+    exit(1);
+  }
+
+  game_in_progress = 1;
+
+  if (!MC_NextQuestion(&flash))
+  { 
+    /* no more questions available */
+    printf("MC_NextQuestion() returned NULL - no questions available\n");
+    exit(1);
+  }
+  else
+  {                                     
+#ifdef LAN_DEBUG
+    printf("WILL SEND >>\n");  
+    printf("QUESTION_ID       :      %d\n", flash.question_id);
+    printf("FORMULA_STRING    :      %s\n", flash.formula_string);
+    printf("ANSWER STRING     :      %s\n", flash.answer_string);
+    printf("ANSWER            :      %d\n",flash.answer);
+    printf("DIFFICULTY        :      %d\n",flash.difficulty);
+#endif
+  }
+
+  for(j = 0; j < num_clients; j++)
+  {
+    if(!SendQuestion(flash, client[j].sock))
+    {
+      printf("Unable to send Question to %s\n", client[j].name);
+    }
+  } 
+}
+
+
+//Returns the index of the first vacant client, or -1 if all clients full
+int find_vacant_client(void)
+{
+  int i = 0;
+  while (client[i].sock && i < MAX_CLIENTS)
+    i++;
+  if (i == MAX_CLIENTS)
+  {
+    fprintf(stderr, "All clients checked, none vacant\n");
+    i = -1;
+  }
+  return i;
+}
+
+
+void remove_client(int i)
+{
+  printf("Removing client[%d] - name: %s\n>\n", i, client[i].name);
+
+  SDLNet_TCP_DelSocket(client_set,client[i].sock);
+
+  if(client[i].sock != NULL)
+    SDLNet_TCP_Close(client[i].sock);
+
+  client[i].sock = NULL;  
+  client[i].game_ready = 0;
+  client[i].name[0] = '\0';
+}
+
+
+//function to send a flashcard(question) from the server to the client
+int SendQuestion(MC_FlashCard flash,TCPsocket client_sock)
+{
+  int x;
+
+  char buf[NET_BUF_LEN];
+  snprintf(buf, NET_BUF_LEN, 
+                "%s\t%d\t%d\t%d\t%s\t%s\n",
+                "SEND_QUESTION",
+                flash.question_id,
+                flash.difficulty,
+                flash.answer,
+                flash.answer_string,
+                flash.formula_string);
+  x = SDLNet_TCP_Send(client_sock, buf, sizeof(buf));
+
+#ifdef LAN_DEBUG
+  printf("SendQuestion() - buf sent:::: %d bytes\n", x);
+  printf("buf is: %s\n", buf);
+#endif
+
+  if (x == 0)
+    return 0;
+  return 1;
+}
+
+
+/*Function to send any messages to the client be it any warnings
+  or anything the client is made to be informed*/
+int SendMessage(int message, int z,TCPsocket client_sock)         
+{
+ int x, len;
+ char buf[NET_BUF_LEN];
+ char msg[100];  
+
+ /* Create appropriate message: */
+  switch(message)
+  {
+    case NO_QUESTION_LIST:
+      sprintf(msg,"%s", "Please! first setup the question list by typing <a>\n");
+      break;
+    case ANSWER_CORRECT:
+      sprintf(msg,"%s %d %s", "Question ID:",
+              z, "was answered correctly by the client\n");
+      break;
+   case LIST_SET_UP:
+      sprintf(msg,"%s", "Question list was successfully setup\n");
+      break;
+   default :
+     fprintf(stderr, "SendMessage() - unrecognized message type\n");
+     return 0;
+  }
+  //transmit:
+  snprintf(buf, NET_BUF_LEN, "%s\t%s\n", "SEND_MESSAGE", msg);
+  x = SDLNet_TCP_Send(client_sock, buf, NET_BUF_LEN);
+
+#ifdef LAN_DEBUG
+  printf("buf is: %s\n", buf);
+  printf("SendMessage() - buf sent:::: %d bytes\n", x);
+#endif
+
+  return 1;
+}
+
+
+//Commented-out copy of old check_messages() to keep ping work from 
+//being lost
+
+// int check_messages(void)
+// {
+//   int i = 0;
+//   int actives = 0;
+//   int msg_found = 0;
+//   char buffer[NET_BUF_LEN];
+// 
+//   /* Check the client socket set for activity: */
+//   actives = SDLNet_CheckSockets(client_set, 0);
+//   if(actives == -1)
+//   {
+//     printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
+//     //most of the time this is a system error, where perror might help you.
+//     perror("SDLNet_CheckSockets");
+//   }
+// 
+//   else if(actives) 
+//   {
+// #ifdef LAN_DEBUG
+//     printf("There are %d sockets with activity\n", actives);
+// #endif
+// 
+//     // check all sockets with SDLNet_SocketReady and handle the active ones.
+//     // NOTE we have to check all the slots in the set because
+//     // the set will become discontinuous if someone disconnects
+//     for(i = 0; i < MAX_CLIENTS; i++)
+//     {
+//       if((client[i].sock != NULL)
+//         && (SDLNet_SocketReady(client[i].sock))) 
+//       {
+// #ifdef LAN_DEBUG
+//         printf("client socket %d is ready\n", i);
+// #endif
+//         if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
+//         {
+// #ifdef LAN_DEBUG
+//           printf("buffer received from client %d is: %s\n", i, buffer);
+// #endif
+//           msg_found++;
+// 
+//           /* Here we pass the client number and the message buffer */
+//           /* to a suitable function for further action:                */
+//            if(game_in_progress==1)
+//            {
+//             if(handle_client_game_msg(i, buffer))
+//             return(1);
+//            }
+//            if(game_in_progress==0)
+//            handle_client_nongame_msg(i,buffer);
+// 
+//         }
+//       }
+//     }  // end of for() loop - all client sockets checked
+//     // Make sure all the active sockets reported by SDLNet_CheckSockets()
+//     // are accounted for:
+//     if(actives == 0)
+//     {
+//       printf("Warning: SDLNet_CheckSockets() reported %d active sockets,\n"
+//              "but only %d messages received.\n", actives, msg_found);
+//       /* We can investigate further - maybe ping all the sockets, etc. */
+//       for(i = 0; i < MAX_CLIENTS; i++)
+//       {
+//         ping_client(i);
+//       }
+//     
+//    
+//       /* Check the client socket set for activity: */
+//       actives = SDLNet_CheckSockets(client_set, 5000);
+//       if(actives == 0)
+//       {
+//         printf("No clients , All clients have disconnected...=(\n");
+//       }
+// 
+//       else if(actives == -1)
+//       {
+//         printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
+//         //most of the time this is a system error, where perror might help you.
+//         perror("SDLNet_CheckSockets");
+//       }
+// 
+//       else if(actives) 
+//       {
+// #ifdef LAN_DEBUG
+//        printf("There are %d sockets with activity\n", actives);
+// #endif
+// 
+//        // check all sockets with SDLNet_SocketReady and handle the active ones.
+//        // NOTE we have to check all the slots in the set because
+//        // the set will become discontinuous if someone disconnects
+//        for(i = 0; i < MAX_CLIENTS; i++)
+//        {
+//          if((client[i].sock != NULL)
+//             && (SDLNet_SocketReady(client[i].sock))) 
+//          {
+// #ifdef LAN_DEBUG
+//            printf("client socket %d is ready\n", i);
+// #endif
+//            if (SDLNet_TCP_Recv(client[i].sock, buffer, NET_BUF_LEN) > 0)
+//            {
+// #ifdef LAN_DEBUG
+//              printf("buffer received from client %d is: %s\n", i, buffer);
+// #endif
+//              if(strncmp(buffer,"PING_BACK",9))
+//              printf("%s is connected =) \n",client[i].name);       
+//            }
+//          }
+//        }
+//       }
+//     }
+//   }
+// }




More information about the Tux4kids-commits mailing list