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

connection.cpp

/**********************************************************************
 ** Connection class: Opens up and maintains a connection, reading in
 **                   data and supplying functions to write data to
 **                   the socket
 **
 ** Reviewed through: version 0.14
 **
 **
 ** Copyright (C) 2001 George Noel (Slate), Ed Boraas
 **
 **   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 CONNECTION_C
#define CONNECTION_C

#include "config.h"
#include "sysdep.h"
#include "connection.h"
#include "strings.h"
#include "port.h"
#include "mud.h"
#include "global.h"
#include "timespan.h"
#include "pager.h"
#include "objtype.h"
#include "newfuncts.h"
#include "inp_funct.h"
#include "utils.h"

/* this define and table was taken from abermud code written by Eric
   from northern lights. It was just such a cool way to do it that I
   lifted it */

#define colorcode(x) ( (x>=64) ? color_table[x-64] : 0 )

char color_table[] =
{                               /* Not beautiful, but efficient :) */
        '\0',   '\0',   '4',    '6',
        '\0',   '\0',   '\0',   '2',
        '\0',   '\0',   '\0',   '\0',
        '0',    '5',    '\0',   '\0',
        '\0',   '\0',   '1',    '\0',
        '\0',   '\0',   '\0',   '7',
        '\0',   '3',    '\0',   '\0',
        '\0',   '\0',   '\0',   '\0',
        '\0',   '\0',   '4',    '6',
        '\0',   '\0',   '\0',   '2',
        '\0',   '\0',   '\0',   '\0',
        '0',    '5',    '\0',   '\0',
        '\0',   '\0',   '1',    '\0',
        '\0',   '\0',   '\0',   '7',
        '\0',   '3',    '\0',   '\0',
        '\0',   '\0',   '\0',   '\0',
};


/***********************************************************************
 ** ~_Connection (destructor) - closes the socket and cleans up
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Connection::~Connection()
{
   Player     *tmp_player;
   Builder    *tmp_builder;

   flush();

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

   valid_input = false;

#ifdef DEBUG_CONNECTION
   printf("Closing Connection.\n");
#endif

   /* need to make sure we are not snooping anyone and if so, unsnoop it */
   tmp_player = mainstruct->get_first_player();
   while (tmp_player != NULL)
   {
      (tmp_player->get_connection())->remove_snoop(this);
      tmp_player = tmp_player->get_next_player();
   }

   /* need to make sure we are not snooping anyone and if so, unsnoop it */
   tmp_builder = mainstruct->get_first_builder();
   while (tmp_builder != NULL)
   {
      (tmp_builder->get_connection())->remove_snoop(this);
      tmp_builder = tmp_builder->get_next_builder();
   }

}


/***********************************************************************
 ** _Connection (constructor) - creates a connection and opens up the socket
 **                             for IO use
 **
 ** Parameters: the_socket - the listening socket to obtain the connection
 **                          from
 **         sock_own   - the Player or Builder controlling the connection
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Connection::Connection(int the_socket, MudObject *sock_own)
{
#if defined( SLACKWARE ) || defined( __CYGWIN__ ) || defined( AIME_WIN32 )
     int sin_len = 0;
#else
     unsigned int sin_len = 0;
#endif

#if defined( AIME_WIN32 )
     unsigned long flags;
#else
     int    flags;
#endif // AIME_WIN32

     char temp_str[MAXHOSTNAMELEN+1];
     Strings holder;

     /* Clearing the class vars */
     use_color = 0;

     lost_connection = 0;
     last_input = time(0);
     hold_buffers = false;

     snoop_list = NULL;

     owner = sock_own;

     FD_ZERO(&write_fds);
     FD_ZERO(&read_fds);
     FD_ZERO(&except_fds);

     sin_len = sizeof(struct sockaddr_in);
     BZERO((char *)&sin,sin_len);

     if ((socketfd = accept(the_socket,(struct sockaddr *)&sin,&sin_len)) < 0)
     {   mainstruct->log_error("Could not accept new connection","accept");
         return;
     }
#ifdef DEBUG_CONNECTION
     else
        printf("New connection accepted.\n");
#endif

     /* save the ip address string of this person */
     BZERO(( char * )&temp_str, MAXHOSTNAMELEN+1);
     strncpy(temp_str, inet_ntoa(sin.sin_addr), MAXHOSTNAMELEN);
     ip_addr = temp_str;

#ifdef DEBUG_CONNECTION
     printf("got ip: %s\n", ip_addr.str_show());
#endif


#if defined( AIME_WIN32 )
   flags = 1;
   if( ioctlsocket( socketfd, FIONBIO, &flags ) != 0 )
   {
      mainstruct->log_error("Could not set the connection to non-blocking","fctnl");
      closesocket(socketfd);
      return;
   }

#else
     flags = fcntl(socketfd,F_GETFL);
     flags |= O_NONBLOCK;

     if (fcntl(socketfd,F_SETFL,flags) < 0)
     {   mainstruct->log_error("Could not set the connection to non-blocking","fctnl");
         close(socketfd);
         return;
     }
#endif // AIME_WIN32


#ifdef DEBUG_CONNECTION
     else
       printf("Flow control set.\n");

     printf("Connection Established.\n");
#endif

}


/***********************************************************************
 ** flush - send all in the buffer out the socket to the player
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

void Connection::flush()
{
   Timespan the_time;
   Strings  final_string;

   final_string = "\r";
   final_string.str_cat(write_buffer.str_show());

   if ((FD_ISSET(socketfd,&write_fds)) && (!hold_buffers))
   {

      write(socketfd, final_string.str_show(), final_string.str_len());
      write_buffer.truncate(0);
      FD_CLR((unsigned int)socketfd,&write_fds);
   }
}


/***********************************************************************
 ** check_socket - checks the socket for input and handles it
 **
 ** Parameters: None
 **
 ** Returns: 2 if there is write data ready
 **          1 if successful
 **          0 if it got to a point it wasnt supposed to
 **          -1 if something went wrong with select
 **          -2 if the select had an exception
 **          -3 if we lost the player's link
 **          -4 if something went wrong reading in the data
 **
 ***********************************************************************/

int Connection::check_socket()
{   int     numselected = 0;
    int     numread = 0;
    char    holder[MAX_COM_LEN];
    Strings *the_input;
    struct  timeval timeout, nulltime;
    int     holder_count = 0;
    int     x;
    Strings tmpholder;
    Strings tmp_buffer;
    char    input_buffer[MAX_COM_LEN+4];


    BZERO(input_buffer, MAX_COM_LEN);
    BZERO(holder, MAX_COM_LEN);
    FD_ZERO(&read_fds);
    FD_ZERO(&except_fds);
    FD_SET(socketfd,&read_fds);
    FD_SET(socketfd,&except_fds);

    /* Time to go to sleep */
    timeout.tv_sec  = 0;
    timeout.tv_usec = 250000;

    nulltime.tv_sec = 0;
    nulltime.tv_usec = 0;

    numselected =
               select(socketfd+1,&read_fds,&write_fds,&except_fds,&nulltime);

    if (numselected < 0)
    {   mainstruct->log_error("Player select error","select");
        perror("Player Select");
        return -1;
    }
    else if (FD_ISSET(socketfd,&except_fds))
    {   mainstruct->log_error("Exception on player socket","select");
        printf("Pending exception.\n");
        return -2;
    }
    else if (FD_ISSET(socketfd,&read_fds))
    {
       for (x=0; x<the_config.maxreadsperpoll; x++)
       {
          BZERO(input_buffer,MAX_COM_LEN+3);

          if ((numread = read(socketfd, input_buffer, MAX_COM_LEN - 1)) <= 0)
              {
            
               /* since we have non-blocking set, if we read and nothing is
                   there to read, we get this error, so return 0 */

                if (errno == EAGAIN)
                    {
                   break;
                    }
          
                if (!lost_connection)
                    {
                 if ((host_addr.str_show() == NULL) || (host_addr.str_len() <= 0))
                   tmpholder.sprintf("Connection lost for %s\n",
                                                        ip_addr.str_show());
                 else
                   tmpholder.sprintf("Connection lost for host %s",
                                                       host_addr.str_show());
                 mainstruct->log_event(tmpholder.str_show());

                 lost_connection = time(0);
                 return -3;
                    } 
              else
                 return -4;
              }
          else if (numread == 0)
              break;
          else
              {
             if (*input_buffer != '\0')
                   {
                if (fill_read_buffer(input_buffer) < 0)
                       return -4;
                   }
              } // read if

         } // main for
       valid_input = true;

       if (read_buffer.get_first() == NULL)
           return 0;

       return 1;
   }
   else if (FD_ISSET(socketfd,&write_fds))
   {
       return 2;
   }

   return 0;
}


/***********************************************************************
 ** get_input - gets input from the user, waiting for the input
 **
 ** Parameters: None
 **
 ** Returns: a pointer to a string object that is returned with input
 **
 ***********************************************************************/

Strings *Connection::get_input()
{  Strings *the_input = NULL;

   if (!lost_link())
   {
#ifdef DEBUG_INPUT
       printf("Reading input.\n");
#endif

       if ((the_input = read_buffer.get_first()) == NULL)
       return NULL;

       read_buffer.reset_current();
       read_buffer.del_cur_entry();

       the_input->handle_backspaces();

       if (read_buffer.get_first() == NULL)
       {
          valid_input = false;
          FD_CLR((unsigned int)socketfd,&read_fds);
       }

       /* now reset the idle time */
       last_input = time(0);
   }
   return the_input;
}


/***********************************************************************
 ** send_to_socket - actually it writes to the buffer for later sending
 **                  to the socket, preprocessing if necessary
 **
 ** Parameters: the_string - the string for sending to the socket
 **
 ** Returns: 1 if success
 **
 ***********************************************************************/

int Connection::send_to_socket(char *the_string, int cook_mode)
{
    char **string_ptr;              // string iterator
    char *chunk;              // piece of the raw string
    char *tmp_string;
    char *tmp_strbuff;
    Player *the_player;


    if (!lost_link()) {
       if (cook_mode == COOKED && owner->get_type() == OBJ_TYPE_PLAYER)
       {
          tmp_string = new char[MAXPROMPTLEN + 1];
          strncpy(tmp_string, the_string, MAXPROMPTLEN);

          string_ptr = &tmp_string;
          the_player = (Player *)owner;
          while ((chunk = STRSEP(string_ptr, "%")))
          {
             switch (*chunk)               // First char of chunk
             {
                case 'h':
                   tmp_strbuff = (char *)malloc(5 * sizeof(char)); // I'd be scared if health was over 99999 :)
                   SNPRINTF(tmp_strbuff, 5, "%i", the_player->get_health());
                   write_to_buffer(tmp_strbuff);
                   write_to_buffer(chunk + 1);
                   free(tmp_strbuff);
                   break;
                case 'H':
                   tmp_strbuff = (char *)malloc(5 * sizeof(char));
                   SNPRINTF(tmp_strbuff, 5, "%i", the_player->get_maxhealth());
                   write_to_buffer(tmp_strbuff);
                   write_to_buffer(chunk + 1);
                   free(tmp_strbuff);
                   break;
                case 'm':
                   tmp_strbuff = (char *)malloc(5 * sizeof(char));
                   SNPRINTF(tmp_strbuff, 5, "%i", the_player->get_magic());
                   write_to_buffer(tmp_strbuff);
                   write_to_buffer(chunk + 1);
                   free(tmp_strbuff);
                   break;
                case 'M':
                   tmp_strbuff = (char *)malloc(5 * sizeof(char));
                   SNPRINTF(tmp_strbuff, 5, "%i", the_player->get_max_magic());
                   write_to_buffer(tmp_strbuff);
                   write_to_buffer(chunk + 1);
                   free(tmp_strbuff);
                   break;
                case 'e':
                   tmp_strbuff = (char *)malloc(5 * sizeof(char));
                   SNPRINTF(tmp_strbuff, 5, "%i", the_player->get_endurance());
                   write_to_buffer(tmp_strbuff);
                   write_to_buffer(chunk + 1);
                   free(tmp_strbuff);
                   break;
                case 'E':
                   tmp_strbuff = (char *)malloc(5 * sizeof(char));
                   SNPRINTF(tmp_strbuff, 5, "%i", the_player->get_max_endurance());
                   write_to_buffer(tmp_strbuff);
                   write_to_buffer(chunk + 1);
                   free(tmp_strbuff);
                   break;
                case 'b':
                   write_to_buffer("\n");
                   break;
                case 'p':
                   write_to_buffer("%");
                   break;
                case 'n':
                   write_to_buffer(owner->get_name());
                   write_to_buffer(chunk + 1);
                   break;
                default:
                   write_to_buffer(chunk);
             }
          }
          free(tmp_string);
       }
       else
          write_to_buffer(the_string);
    }
    else
    {
      //       printf("Write to invalid stream\n");
       return -1;
    }

#ifdef NO_BUFFERING
    flush();
#endif
    return 1;
}


/***********************************************************************
 ** send_to_socket - actually it writes to the buffer for later sending
 **                  to the socket
 **
 ** NOTE: This function passes the_string to the real send_to_socket,
 **       assuming raw mode.
 **
 ** Parameters: the_string - the string for sending to the socket
 **
 ** Returns: 1 if success
 **
 ***********************************************************************/

int Connection::send_to_socket(char *the_string)
{
  return send_to_socket(the_string, RAW);
}


/***********************************************************************
 ** send_to_socket - actually it writes to the buffer for later sending
 **                  to the socket, preprocessing if necessary
 **
 ** NOTE: This function accepts a Strings object, and passes it on
 **       to the real send_to_socket as a char*.
 **
 ** Parameters: the_string - the string for sending to the socket
 **
 ** Returns: 1 if success
 **
 ***********************************************************************/

int Connection::send_to_socket(Strings *the_string, int cook_mode)
{
    return send_to_socket(the_string->str_show(), cook_mode);
}


/***********************************************************************
 ** send_to_socket - actually it writes to the buffer for later sending
 **                  to the socket
 **
 ** NOTE: This function accepts a Strings object, and passes it on
 **       to the real send_to_socket as a char*, assuming raw mode.
 **
 ** Parameters: the_string - the string for sending to the socket
 **
 ** Returns: 1 if success
 **
 ***********************************************************************/

int Connection::send_to_socket(Strings *the_string)
{
    return send_to_socket(the_string->str_show(), RAW);
}


/***********************************************************************
 ** lost_link - is the connection still valid, or did we lose it.
 **
 ** Parameters: None
 **
 ** Returns: Time we lost link at if invalid
 **          0 if valid
 **
 ***********************************************************************/

time_t Connection::lost_link()
{
   return lost_connection;
}


/***********************************************************************
 ** write_to_buffer - writes to the string buffer for later sending to
 **                   the socket
 **
 ** Parameters: new_input - the character string to write to the buffer
 **
 ** Returns: string length written if success
 **          -1 if failure
 **
 ***********************************************************************/

int Connection::write_to_buffer(char *new_input)
{  int count = 0;   /* num of ampersands in there */
   int count_nl = 0; /* number of newlines */
   char *send_str;  /* formatted string to be sent */
   char *temp_str;  /* moves along string */

   if (new_input == NULL)
      return -1;

   send_to_snoopers(new_input);

   if (hold_buffers)
   {
      pager_buffer.str_cat(new_input);
      return pager_buffer.str_len();
   }

   if (*new_input)
   {

      /* first get num of & so we know how long to make the string */
      temp_str = new_input;
      while ((*temp_str) && (*temp_str != '\0')) {
         if (*temp_str == '&')
            count++;
         if (*temp_str == '\n')
            count_nl++;
         temp_str++;
      }

      /* create the string */
      send_str =
             new char[(strlen(new_input) + (7 * count) + (2*count_nl)) + 2];
      BZERO(send_str, strlen(new_input) + (7*count) + 2);

      temp_str = send_str;

      /*      *temp_str = '\r';
            temp_str++; */


      /* convert colors */
      while ((*new_input) && (*new_input != '\0'))
      {

       /* if we hit a colorcode */
         if (*new_input == '&') {

         switch (*(new_input+1)) {

            /* if we find &&, make it just & */
            case '&':
                 new_input++;
                 *temp_str++ = *new_input++;
                 break;

            /* if we find a plus, we have a colorcode, text color */
            case '+':
                 if (colorcode(*(new_input+2)))
             {
                    if (use_color)
                {
                       strcpy ((char *) temp_str, "\033[1;30m");
                       temp_str[5] = colorcode(*(new_input+2));

                       if ((*(new_input+2)) >= 96)
                          temp_str[2] = '0';
                       temp_str += 7;
                    }
                    new_input += 3;
                    break;
                 } else {
                    *temp_str++ = *new_input++;
                 }

            /* if we find a minus, we have a colorcode, background color */
            case '-':
                 if ( colorcode(*(new_input+2)))
             {
                    if (use_color)
                {
                       strcpy ((char *) temp_str, "\033[1;40m");

                       temp_str[5] =  colorcode(*(new_input+2));

                       if ((*(new_input+2)) >= 96)
                          temp_str[2] = '0';
                       temp_str += 7;
                    }
                    new_input += 3;
                 }
                 else {
                    *temp_str++ = *new_input++;
                 }
                 break;

            /* if we have an =, we have both background and foreground */
            case '=':
                 if  (colorcode(*(new_input+2)))
             {
                    if (use_color)
                {
                       strcpy ((char *) temp_str, "\033[1;40;30m");
                          temp_str[5] =  colorcode(*(new_input+2));

                       temp_str[8] =  colorcode(*(new_input+3));
                       if ((*(new_input+2)) >= 96)
                          temp_str[2] = '0';
                       temp_str += 10;
                    }
                    new_input += 4;
                 }
                 else {
                    *temp_str++ = *new_input++;
                 }
                 break;

            /* if they say turn off colorcodes */
            case '*':
                 if (use_color)
             {
                    strcpy ((char *) temp_str, "\033[40m\033[0m");
                    temp_str += 9;
                 }
                 new_input += 2;
                 break;

            default:
                 *temp_str++ = *new_input++;
                 break;
           }
         }
         else if (*new_input == '\n')
       {
          *temp_str++ = '\r';
            *temp_str++ = '\n';
            new_input++;
         }
         else {
            *temp_str++ = *new_input++;
         }
      }
      *temp_str = '\0';

      if (!lost_link())
      {
          Timespan the_time;

          write_buffer.str_cat(send_str);

          if( !FD_ISSET(socketfd, &write_fds) )
             FD_SET(socketfd,&write_fds);
      }
      else
         printf("Write to invalid socket.\n");


      /* now free that string and return the length of string sent */
      delete send_str;

      return strlen(new_input);
   }
   else
      return -1;
}


/***********************************************************************
 ** get_ip_addr - gets the ip address string
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the ip addr string
 **
 ***********************************************************************/

char *Connection::get_ip_addr()
{
   return ip_addr.str_show();
}


/***********************************************************************
 ** find_host_addr - gets the hostname using gethostbyname
 **                  (warning) can cause lag in the thread
 **
 ** Parameters: Nothing
 **
 ** Returns:  1 if success
 **          -1 if failure
 **
 ***********************************************************************/

int Connection::find_host_addr()
{
     Strings holder;
     hostent *h;

     /* get and save the hostname if we can */
     if ((h = gethostbyaddr ((char *) &sin.sin_addr, sizeof (sin.sin_addr),
                              AF_INET)) == NULL)
     {
       /* holder.sprintf("Could not find hostname for ip address '%s'",
                                                   ip_addr.str_show());
        mainstruct->log_error(holder.str_show(), "connection constructor"); */
        return -1;
     }
     else
     {
        host_addr = (char *) h->h_name;
#ifdef DEBUG_CONNECTION
        printf("got host: %s\n", host_addr.str_show());
#endif
     }
     return 1;

}


/***********************************************************************
 ** get_host_addr - gets the host address string
 **
 ** Parameters: Nothing
 **
 ** Returns: a pointer to the host address string
 **
 ***********************************************************************/

char *Connection::get_host_addr()
{
   return host_addr.str_show();
}


/***********************************************************************
 ** echo_off - turns the echo off for the user's keystrokes
 **
 ** Parameters: Nothing
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/

int Connection::echo_off()
{
   char the_string[] =
    {
      (char) IAC,
      (char) WILL,
      (char) TELOPT_ECHO
   };
   flush();

   write(socketfd, the_string,sizeof(the_string));
   flush();

   return 1;
}


/***********************************************************************
 ** echo_on - turns the echo on for the user's keystrokes
 **
 ** Parameters: Nothing
 **
 ** Returns:  1 if successful
 **          -1 if failed
 **
 ***********************************************************************/

int Connection::echo_on()
{
   char the_string[] =
    {
      (char) IAC,
      (char) WONT,
      (char) TELOPT_ECHO,
      (char) TELOPT_NAOFFD,
      (char) TELOPT_NAOCRD
   };
   flush();

   write(socketfd, the_string, sizeof(the_string));

   flush();

   return 1;
}


/***********************************************************************
 ** get_socknum - gets the socket number for the fd
 **
 ** Parameters: Nothing
 **
 ** Returns:  the socket number
 **
 ***********************************************************************/

int Connection::get_socknum()
{
   return socketfd;
}


/***********************************************************************
 ** set_color - turns the color either on or off
 **
 ** Parameters: the_num - 1 for on, 0 for off
 **
 ** Returns:  Nothing
 **
 ***********************************************************************/

void Connection::set_color(int the_num)
{
   use_color = the_num;
}


/***********************************************************************
 ** has_input - does the connection have input ready to read?
 **
 ** Parameters: None
 **
 ** Returns:  true for yes, false for no
 **
 ***********************************************************************/

bool    Connection::has_input()
{
  if (read_buffer.get_first() != NULL)
    return true;
  return false;
}


/***********************************************************************
 ** has_output - does the connection have output ready to read?
 **
 ** Parameters: None
 **
 ** Returns:  true for yes, false for no
 **
 ***********************************************************************/

bool    Connection::has_output()
{
   return (FD_ISSET(socketfd,&write_fds) ? true : false);
}


/***********************************************************************
 ** get_idle - gets the amount of time this connection has been idle
 **
 ** Parameters: None
 **
 ** Returns:  time value (long int)
 **
 ***********************************************************************/

time_t Connection::get_idle()
{
   return (time(0) - last_input);
}


/***********************************************************************
 ** get_pager_buffer - gets a pointer to the pager buffer strings object
 **
 **
 ***********************************************************************/

Strings *Connection::get_pager_buffer()
{
   return &pager_buffer;
}


/***********************************************************************
 ** start_paging - sets up the connection to handle paged output
 **
 **
 ***********************************************************************/

void Connection::start_paging()
{
   pager_buffer.truncate(0);
   hold_buffers = true;
}


/***********************************************************************
 ** end_paging - sets up the connection to no longer handle paged output.
 **              Also starts the pager writing to the socket
 **
 ** Parameters: the_user - the user who we send the paged text to
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Connection::end_paging(MudObject *the_user)
{
   Pager       *the_pager;
   Inp_Handler *the_handler;
   int         results;

   if (the_user == NULL)
     the_user = owner;

   if (the_user->get_type() == OBJ_TYPE_PLAYER)
      the_handler = ((Player *) the_user)->get_input_handler();
   else if (the_user->get_type() == OBJ_TYPE_BUILDER)
      the_handler = ((Builder *) the_user)->get_input_handler();
   else
      return -1;

   hold_buffers = false;

   if (the_user->get_type() == OBJ_TYPE_PLAYER)
      the_pager = new_Pager(&pager_buffer,
                                    ((Player *) the_user)->get_pager_lines());
   else
      the_pager = new_Pager(&pager_buffer,
                                    ((Builder *) the_user)->get_pager_lines());

   results = the_pager->paged_read(this);

   if (results)
   {
      delete_Pager(the_pager);
   }
   else
   {
      the_handler->push_input_handler(pager_funct,
             "&+c<&+G*************&+Bpress return to continue, "
             "q to quit&+G*****************&+c>&*", HANDLER_DATA_PAGER);
      the_handler->set_data((void *) the_pager);
   }
   return 1;
}


/***********************************************************************
 ** set_owner - Sets the value of 'owner' to sock_own.
 **
 ** Parameters: sock_own - controlling MudObject*
 **
 ** Returns: 1 for success, -1 for failure
 **
 ***********************************************************************/

int Connection::set_owner(MudObject *sock_own)
{
   owner = sock_own;
   return 1;
}


/***********************************************************************
 ** send_to_snoopers - Sends the data we are outputting for the player to
 **                    folks who are snooping them
 **
 ** Parameters: the_output - the output to send to the snoopers
 **
 ** Returns: num players snooping for success, -1 for failure
 **
 ***********************************************************************/

int Connection::send_to_snoopers(char *the_output)
{
   Strings      new_output;
   Strings      old_output;
   char         *tmp_str;
   char         *start_str;
   snoop_struct *tmp_snoop;
   int          counter = 0;
   char         *terminating;


   if (snoop_list == NULL)
      return 0;

   old_output = the_output;

   tmp_str = old_output.str_show();
   while (tmp_str && (*tmp_str))
   {
      new_output.str_cat("&+Y> &*");

      start_str = tmp_str;
      while (tmp_str && (*tmp_str) && (*tmp_str != '\n'))
         tmp_str++;

      if ((*tmp_str != '\n') && (*tmp_str != '\r'))
         break;

      if (*tmp_str == '\n')
         terminating = "\n";
      else
         terminating = "\r";

      *tmp_str = '\0';
      new_output.str_cat(start_str);

      new_output.str_cat(terminating);

      tmp_str++;
      start_str = tmp_str;
   }

   tmp_snoop = snoop_list;
   while (tmp_snoop != NULL)
   {
      (tmp_snoop->user)->send_to_socket(new_output.str_show(), RAW);
      counter++;
      tmp_snoop = tmp_snoop->next_snoop;
   }
   return counter;
}


/***********************************************************************
 ** add_snoop - adds a connection that is snooping this connection
 **
 ** Parameters: the_conn - the connection that is snooping this one
 **
 ** Returns: 1 for success, -1 for failure, -2 for already snooping, -3
 **          for attempt to snoop itself
 **
 ***********************************************************************/

int Connection::add_snoop(Connection *the_conn)
{
   snoop_struct *tmp_snoop;
   snoop_struct *new_snoop;

   if (the_conn == NULL)
      return -1;

   if (the_conn == this)
      return -3;

   new_snoop = new_snoop_struct();

   new_snoop->next_snoop = NULL;
   new_snoop->user = the_conn;

   if (snoop_list == NULL)
   {
      snoop_list = new_snoop;
      return 1;
   }

   tmp_snoop = snoop_list;
   if (tmp_snoop->user == the_conn)
      return -2;

   while (tmp_snoop->next_snoop != NULL)
   {
      tmp_snoop = tmp_snoop->next_snoop;
      if (tmp_snoop->user == the_conn)
         return -2;
   }
   tmp_snoop->user = the_conn;
   return 1;
}


/***********************************************************************
 ** remove_snoop - removes a connection that is snooping this connection
 **
 ** Parameters: the_conn - the connection to remove
 **
 ** Returns: 1 for success, -1 for failure, 0 if not found
 **
 ***********************************************************************/

int Connection::remove_snoop(Connection *the_conn)
{
   snoop_struct *tmp_snoop;
   snoop_struct *prev_snoop = NULL;

   if (the_conn == NULL)
      return -1;

   tmp_snoop = snoop_list;

   while (tmp_snoop != NULL)
   {
      if (tmp_snoop->user == the_conn)
         break;
      tmp_snoop = tmp_snoop->next_snoop;
   }

   if (tmp_snoop == NULL)
      return 0;

   if (prev_snoop == NULL)
      snoop_list = snoop_list->next_snoop;
   else
      prev_snoop->next_snoop = tmp_snoop->next_snoop;

   delete_snoop_struct(tmp_snoop);
   return 1;
}


/***********************************************************************
 ** remove_all_snoop - removes all snoops from this player's list
 **
 ** Parameters: snoop_type - the type of remove we are doing
 **
 ** Returns: num removed for success, -1 for failure, 0 if not found
 **
 ***********************************************************************/

int Connection::remove_all_snoop(int snoop_type)
{
   snoop_struct *tmp_snoop;
   int          counter = 0;

   if (snoop_list == NULL)
      return 0;

   tmp_snoop = snoop_list->next_snoop;

   while (snoop_list != NULL)
   {
      if (snoop_type == SNOOP_SPECTATE)
      {
         snoop_list->user->send_to_socket("Your Spectate has been blocked.\n");
      }

      delete_snoop_struct(tmp_snoop);
      counter++;
      snoop_list = tmp_snoop;
   }

   return counter;
}


/***********************************************************************
 ** has_snoop - checks to see if a connection is being snooped by another
 **             connection
 **
 ** Parameters: the_conn - the connection to check for
 **
 ** Returns: 1 for has it, 0 if not found
 **
 ***********************************************************************/

int Connection::has_snoop(Connection *the_conn)
{
   snoop_struct *tmp_snoop;

   if (the_conn == NULL)
      return 0;

   tmp_snoop = snoop_list;

   while (tmp_snoop != NULL)
   {
      if (tmp_snoop->user == the_conn)
         return 1;
      tmp_snoop = tmp_snoop->next_snoop;
   }
   return 0;
}


/***********************************************************************
 ** set_valid - marks this socket as valid
 ***********************************************************************/

void Connection::set_valid()
{
  valid_socket = true;
}


/***********************************************************************
 ** fill_read_buffer - fills up the read buffer with any input in the socket
 **
 ** Parameters: the_conn - the connection to check for
 **
 ** Returns: 1 for has it, 0 if not found
 **
 ***********************************************************************/

int Connection::fill_read_buffer(char *input_buf)
{
  char copy_buffer[MAX_COM_LEN+4];
  char *str_ptr = input_buf;
  char *new_ptr = NULL;
  int  counter = 0;
  Strings *new_str = NULL;

  /* remove all wierd telnet function chars */
#ifdef DEBUG_INPUT
  printf("Packet: %s\n", str_ptr);
  printf("Strlen: %d\n", strlen(str_ptr));
#endif

  // Read the input buffer until we hit the end of it
  while ((str_ptr) && (*str_ptr != '\0'))
  {
    // Set up a buffer to write valid chars to
    bzero(copy_buffer, MAX_COM_LEN+4);
    new_ptr = copy_buffer;

    // Now search along the input for the length of the line
    while ((str_ptr) && (*str_ptr != '\n') && (*str_ptr != '\0'))
    {
      // Skip this char if it is not an authorized char
      if (!isalnum(*str_ptr) && !ispunct(*str_ptr) && (!isspace(*str_ptr)) &&
        (*str_ptr != '\b'))
      str_ptr++;

      // Else, it is an authorized char, copy it
      else
      {
      *new_ptr = *str_ptr;
      new_ptr++;
      str_ptr++;
      }
    }

    // Now we theoretically have the entire line, if the length is greater
    // than zero, lets copy it to a buffer
    if (strlen(copy_buffer) > 0)
    {
      // If we don't have a newline, add this to the partial buffer
      if (*str_ptr != '\n')
      {
      partial_line.str_cat(copy_buffer);
      }
      else
      {
      new_str = new Strings(partial_line.str_show());
      new_str->str_cat(copy_buffer);
      partial_line.truncate(0);
      new_str->remove_newline();
      read_buffer.add_entry(new_str);
      counter++;
      }
    }
    if ((str_ptr) && (*str_ptr != '\0'))
      str_ptr++;
  }
  return counter;
}

#endif













Generated by  Doxygen 1.6.0   Back to index