Logo Search packages:      
Sourcecode: aime version File versions  Download package

port.cpp

/**********************************************************************
 ** Port class: This class handles a listening port, creating it and
 **             providing methods to poll it. 
 **
 **   
 ** Reviewed through: version 0.14
 **    
 **
 ** Copyright (C) 2000 George Noel (Slate)
 **
 **   This program is free software; you can redistribute it and/or modify
 **   it under the terms of the GNU General Public License as
 **   published by the Free Software Foundation; either version 2 of the 
 **   License, or any later version. 
 **
 **   This program is distributed in the hope that it will be useful, but 
 **   WITHOUT ANY WARRANTY; without even the implied warranty of 
 **   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 **   General Public License for more details. 
 ** 
 **   You should have received a copy of the GNU General Public License 
 **   along with this program (in the docs dir); if not, write to the Free
 **   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 **
 **********************************************************************/

#ifndef PORT_C
#define PORT_C

#include "config.h"
#include "sysdep.h"
#include "strings.h"
#include "mudobject.h"
#include "individual.h"
#include "player.h"
#include "port.h"
#include "mud.h"
#include "global.h"
#include "timing.h"


/***********************************************************************
 ** check_socket - checks the listening socket for data, and if it finds
 **                any it handles it
 **
 ** Paramters: None
 **
 ** Returns:  1 if successful
 **          -1 if an error
 **
 ***********************************************************************/

int Port::check_socket(Timing *tmp_timer)
{
   fd_set input_set, output_set, exc_set;
   struct timeval timeout, null_time;
   long   elapsed = 0;
   int    v;            /* holds result of select */

   
   null_time.tv_usec = 0;
   null_time.tv_sec = 0;


   FD_ZERO(&input_set);
   FD_ZERO(&output_set);
   FD_ZERO(&exc_set);

   FD_SET(list_sock, &input_set);

   /* check the socket for data */
   if ((v = select (list_sock + 1, &input_set, &output_set, 
                                               &exc_set, &null_time)) < 0)
   {
      perror("select, port");
      return -1;
   }

   /* get time left in cycle for sleep */
   timeout.tv_sec = 0;
   if ((tmp_timer != NULL) && ((elapsed = tmp_timer->cycle_elapsed()) < 
                                  ((long) (1000000/the_config.pollspersec)))) 
      timeout.tv_usec = (1000000/the_config.pollspersec) - elapsed;
   else
   {
      if (tmp_timer != NULL)
      {
         mainstruct->increment_lagged_cycle();
      }
      timeout.tv_usec = 0;
   }


#if defined( AIME_WIN32 )
   Sleep( timeout.tv_usec / 1000 );
   
#else
   if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &timeout) < 0) {
      perror("Select sleep, port");
      return -1;
   }
#endif // AIME_WIN32


   if( tmp_timer )
      tmp_timer->set_cycle();

   /* if we find an exception */
   if (FD_ISSET (list_sock, &exc_set))
   {
      printf("Exception pending with listening socket\n");
      v--;
   }

   /* if we find a connection, create a new player */
   if (FD_ISSET (list_sock, &input_set))
   {
#ifdef DEBUG_CONNECTION
      printf("Received connection...");
#endif
      if (port == the_config.gameport)
      {
#ifdef DEBUG_CONNECTION
         printf("player port\n");
#endif
         mainstruct->add_player();
      }
      else if (port == the_config.buildport)
      {
#ifdef DEBUG_CONNECTION
         printf("builder port\n");
#endif
       mainstruct->add_builder();
      }
   }
   return 1;
}


/***********************************************************************
 ** get_serv_hostname - returns the server hostname string
 **
 ** Paramters: the_str - the string to put the hostname into
 **
 ** Returns: pointer to the_str with hostname loaded
 **
 ***********************************************************************/

char *Port::get_serv_hostname(void) {
   return serv_hostname.str_show();
}



/***********************************************************************
 ** connect -  Opens the listening socket and starts it listening. It
 ** (private)  places the socket in the Mud class attribute list_sock
 **            and you can poll for socket data by calling check_socket
 **
 ** Parameters: the_port - the port number to open this to
 **             quiet_mode - display output or not
 **
 ** Returns: 1  if successful
 **          -1 if gethostname error
 **          -2 if gethostbyname error
 **          -3 if socket error
 **          -4 if bind error
 **          -5 if listen error
 **          -6 if fcntl error
 **
 ***********************************************************************/

int Port::connect(unsigned short int the_port, bool quiet_mode)
{
   struct hostent *h;  /* holds the IP struct gotten from gethostbyname */
   int            size_sockaddr;  /* holds sizeof(struct sockaddr_in) */
   char           *opt;
   char           tmp_serv[MAXHOSTNAMELEN];
   Strings        holder;

   if (!quiet_mode)
      printf("Setting up listening socket.\n");

   /* get the hostname of the server */
   if (gethostname (tmp_serv, MAXHOSTNAMELEN - 1) != 0) {
      perror("gethostname");
      return -1;
   }
   serv_hostname = tmp_serv;

   /* try to get the IP address of the server from the hostname */
   if ((h = gethostbyname(serv_hostname.str_show())) == NULL) {
      holder.sprintf("gethostbyname host: %s", serv_hostname.str_show());
      perror(holder.str_show());
      return -2;
   }

   /* load the sin struct with all address data */
   size_sockaddr = sizeof(struct sockaddr_in);
   sin = (struct sockaddr_in *) malloc(size_sockaddr);
   BZERO (( char * )sin, size_sockaddr);
   sin->sin_family = h->h_addrtype;
   sin->sin_port = htons (the_port);
   port = the_port;

   
   /* opens the socket */
   if ((list_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
      perror("Init-socket");
      return -3;
   }

   if (setsockopt (list_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, 
                                                    sizeof (opt)) < 0) {
      perror ("setsockopt REUSEADDR");
      return -3;
   }

#ifdef USE_LINGER
   {
      struct linger ld;

      ld.l_onoff = 0;
      ld.l_linger = 1000;
      if (setsockopt(list_sock, SOL_SOCKET, SO_LINGER, (char *)&ld, sizeof(ld)) < 0) {
         perror("setsockopt LINGER");
         exit(1);
      }
   }
#endif


   /* bind the socket to a name */
   if (bind(list_sock, (struct sockaddr *) sin, size_sockaddr) < 0) {
      perror("bind");

#if defined( AIME_WIN32 )
      closesocket( list_sock );
#else
      close(list_sock);
#endif

      return -4;
   }

   /* start the socket listening */
   if (listen (list_sock, 3) != 0) {

#if defined( AIME_WIN32 )
      closesocket( list_sock );
#else
      close(list_sock);
#endif

      perror("listen");
      return -5;
   }

   if (!quiet_mode)
      printf("Socket configured and listening at port %d\n", port);

   return 1;
}

/***********************************************************************
 ** is_valid - tells if the listening port is still valid
 **
 ** Paramters: None
 **
 ** Returns: 1 if valid
 **          0 if not valid
 **
 ***********************************************************************/

int Port::is_valid() {
   return valid;
}


/***********************************************************************
 ** get_socket - gets the listening socket
 **
 ** Paramters: None
 **
 ** Returns: the listening socket
 **
 ***********************************************************************/

int Port::get_socket() {
   return list_sock;
}


/***********************************************************************
 ** Port (constructor) - creates and opens a listening port
 **
 ** Parameters: the_port - the port to open the listening port up to
 **             quiet_mode - display output or not
 **
 ** Returns: Nothing
 **
 ***********************************************************************/
   
Port::Port(unsigned short int the_port, bool quiet_mode)
{
   if (connect(the_port, quiet_mode) <= 0)
      valid = 0;
   else
      valid = 1;
}   


/***********************************************************************
 ** ~Port (destructor) - closes the port and cleans it up
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Port::~Port()
{
   printf("Disconnecting socket\n");

#if defined( AIME_WIN32 )
      closesocket( list_sock );
#else
      close(list_sock);
#endif

   printf("Socket disconnected\n");
   return;
}


#endif




Generated by  Doxygen 1.6.0   Back to index