[ScryMUD] SVN Commit Info r890 - trunk/mud/grrmud/server

scrymud at wanfear.com scrymud at wanfear.com
Sat Feb 24 17:21:13 PST 2007


Author: eroper
Date: 2007-02-24 17:21:12 -0800 (Sat, 24 Feb 2007)
New Revision: 890

Modified:
   trunk/mud/grrmud/server/Makefile
   trunk/mud/grrmud/server/command5.cc
   trunk/mud/grrmud/server/const.cc
   trunk/mud/grrmud/server/critter.cc
   trunk/mud/grrmud/server/critter.h
   trunk/mud/grrmud/server/grrmud.cc
   trunk/mud/grrmud/server/hegemon_handler.cc
   trunk/mud/grrmud/server/hegemon_handler.h
   trunk/mud/grrmud/server/login.cc
   trunk/mud/grrmud/server/parse.cc
   trunk/mud/grrmud/server/protocol_handler.h
   trunk/mud/grrmud/server/telnet_handler.cc
   trunk/mud/grrmud/server/telnet_handler.h
Log:
We are now using HegemonHandler's and TelnetHandler's.


Modified: trunk/mud/grrmud/server/Makefile
===================================================================
--- trunk/mud/grrmud/server/Makefile	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/Makefile	2007-02-25 01:21:12 UTC (rev 890)
@@ -21,7 +21,7 @@
 ez_skll.o social2.o cr_skll.o ar_skll.o pet_spll.o vehicle.o const.o \
 script.o SkillSpell.o zone.o rm_parse.o rm_cmds.o obj_parse.o \
 obj_cmds.o BuildInfo.o BugEntry.o MudStats.o clients.o ServerConfig.o \
-mapper.o regex.o
+mapper.o regex.o protocol_handler.o telnet_handler.o hegemon_handler.o
 grrmud_TARG = grrmud
 
 GEN_SPEC = gen_cmds.spec

Modified: trunk/mud/grrmud/server/command5.cc
===================================================================
--- trunk/mud/grrmud/server/command5.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/command5.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -48,6 +48,8 @@
 #include "clients.h"
 #include "vehicle.h"
 #include "regex.h"
+#include "telnet_handler.h"
+#include "hegemon_handler.h"
 
 int test(critter& pc) {
    String buf;
@@ -2522,6 +2524,9 @@
    Sprintf(buf, "[%i]%P10 RoomScript  %P30[%i] %P42 BugCollection\n",
            RoomScript::getInstanceCount(), BugCollection::getInstanceCount());
    pc.show(buf);
+   Sprintf(buf, "[%i]%P10 TelnetHandler %P30[%i] %P42 HegemonHandler\n",
+         TelnetHandler::getInstanceCount(), HegemonHandler::getInstanceCount());
+   pc.show(buf);
 
    Sprintf(buf, "\nSize (length) of:\n\tembattled_rooms: %i \t affected_doors: %i\n",
            embattled_rooms.size(), affected_doors.size());

Modified: trunk/mud/grrmud/server/const.cc
===================================================================
--- trunk/mud/grrmud/server/const.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/const.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -616,9 +616,9 @@
 
    //"\n\x9B\x4D\x31\x32\x68\nChoose a Password:  ", 
    //"\n\x9B\x4D\x31\x32\x68\nEnter your password again for verification:  ",
-   "\nChoose a Password (Will be Echoed):  ", 
+   "\nChoose a Password (may be echoed):  ", 
       "\nEnter your password again for verification:  ",
-      "(M)ale, (F)emale, or (N)euter:  ",
+      "\n(M)ale, (F)emale, or (N)euter:  ",
       "\n\nSelection of Classes: \n\n"
          "   Your class may affect your stats and will have an influence on\n"
          "   the skills you are able to acquire.\n"

Modified: trunk/mud/grrmud/server/critter.cc
===================================================================
--- trunk/mud/grrmud/server/critter.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/critter.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -42,6 +42,8 @@
 #include "battle.h"
 #include <stdarg.h>
 #include "clients.h"
+#include "telnet_handler.h"
+#include "hegemon_handler.h"
 
 const char* PcPositionStrings[] = {"stand", "sit", "rest", "sleep", "meditate",
                                    "stun", "dead", "prone"};
@@ -1338,6 +1340,7 @@
 
 pc_data::pc_data() {
    _cnt++;
+   p_handler = NULL;
    post_msg = NULL;
    snoop_by = NULL;
    snooping = NULL;
@@ -1348,6 +1351,7 @@
 
 pc_data::pc_data(const pc_data& source) {
    _cnt++;
+   p_handler = NULL;
    post_msg = NULL;
    snoop_by = NULL;
    snooping = NULL;
@@ -1358,6 +1362,7 @@
 
 pc_data::~pc_data() {
    _cnt--;
+
    Clear();
 }//destructor
  
@@ -1419,6 +1424,7 @@
    last_login_time = 0; //in seconds, since 1970 etc...
    total_time_online = 0; //in seconds
    lines_on_page = 20;
+   columns_on_page = 80;
    if (w_eye_obj) {
       w_eye_obj->obj_proc->w_eye_owner = NULL;
       w_eye_obj = NULL;
@@ -1461,6 +1467,7 @@
    imm_data = new immort_data(*(source.imm_data));
    mode = source.mode;
    lines_on_page = source.lines_on_page;
+   columns_on_page = source.columns_on_page;
    index = source.index;
    hunger = source.hunger;
    thirst = source.thirst;
@@ -3732,6 +3739,7 @@
          pc = new pc_data;
       }//if
       pc->Read(this, ofile);  
+
       pc->file_format_version = format_version;
    }//if
    else { //its a mob
@@ -4292,13 +4300,6 @@
       return;
    }
 
-   char go_ahead_str[] =
-   {
-      (char) IAC,
-      (char) GA,
-      (char) 0
-   };
-
    // for visible exits
    Cell<door*> cll(getCurRoom()->doors);
    door* dr_ptr;
@@ -4448,9 +4449,7 @@
       targ.Append(tmp);
    }
 
-   if (! isUsingClient()) {
-      targ.Append(go_ahead_str);
-   }
+   targ.Append(pc->p_handler->end_of_record());
 
    show(targ);
 
@@ -4591,11 +4590,31 @@
 }//whichClient   
 
 bool critter::setClient(int which) {
-   if (NUM_CLIENTS < which)
+
+   if (NUM_CLIENTS < which) {
       return false;
-   if(!pc->pc_data_flags.get(5))
+   }
+
+   if ( pc->client == which ) {
       return false;
+   }
+
    pc->client = which;
+
+   switch ( which ) {
+
+      case HEGEMON:
+         delete pc->p_handler;
+         pc->p_handler = new HegemonHandler(this);
+      break;
+
+      case NO_CLIENT:
+         delete pc->p_handler;
+         pc->p_handler = new TelnetHandler(this);
+      break;
+
+   };
+
    return true;
 }
 

Modified: trunk/mud/grrmud/server/critter.h
===================================================================
--- trunk/mud/grrmud/server/critter.h	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/critter.h	2007-02-25 01:21:12 UTC (rev 890)
@@ -40,6 +40,7 @@
 #include "const.h"
 #include "lang_strings.h"
 #include "battle.h"
+#include "protocol_handler.h"
 
 ///********************  temp crit data  *****************************///
 
@@ -552,6 +553,7 @@
    static int _cnt;
 
 public:
+   ProtocolHandler* p_handler;
    String password;
    String input;
    String output;
@@ -581,6 +583,7 @@
    short rent_year; //year of last rent
    short rent_day; //day of last rent
    short lines_on_page; //used to page output
+   short columns_on_page; //will be used to format output better
    int age;
    String host;
    short link_condition; //1 CON_PLAYING, 2 CON_LINKDEAD, 3 CON_LOGGING_IN

Modified: trunk/mud/grrmud/server/grrmud.cc
===================================================================
--- trunk/mud/grrmud/server/grrmud.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/grrmud.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -79,6 +79,7 @@
 #include <new>
 
 #include "telnet.h"
+#include "telnet_handler.h"
 
 #define MAX_HOSTNAME    256
 
@@ -1032,69 +1033,12 @@
              (pc_ptr->MODE != MODE_LOGOFF_NEWBIE_PLEASE) &&
              (pc_ptr->MODE != MODE_QUIT_ME_PLEASE)) {
 
-            /* Yes I need a better place for this, it has to happen before
-             * snooping and has to be able to put crap in the output buffer
-             */
-            {
-               String tmp;
-               int i;
-               int imax;
-               unsigned char telnet_cmd = '\0';
-
-               // Process telnet protocol commands
-
-               /* window size negotinations:
-                * (client) IAC WILL NAWS
-                * (server) IAC DO NAWS
-                * (client) IAC SB NAWS WIDTH[1] WIDTH[0] HEIGHT[1] HEIGHT[0] IAC SE
-                *                      < 16 bit value >   < 16 bit value >    
-                * For now though, I'm going to be lazy ;)
-                * (client) IAC WILL NAWS
-                * (server) IAC DON'T NAWS
-                */
-
-               imax = pc_ptr->getInput()->Strlen();
-               tmp.Clear();
-               for(i=0;i<imax;i++) {
-                  if ( pc_ptr->getInput()->charAt(i) == (char)IAC ) {
-                     if ( i+1 < imax )
-                        telnet_cmd = pc_ptr->getInput()->charAt(++i);
-
-                     switch ( telnet_cmd ) {
-                        case WILL:
-                           if ( i+1 < imax ) {
-                              telnet_cmd = pc_ptr->getInput()->charAt(++i);
-                              switch ( telnet_cmd ) {
-                                 /*
-                                    case TELOPT_NAWS:
-                                    pc_ptr->pc->output.append((char)IAC);
-                                    pc_ptr->pc->output.append((char)DO);
-                                    pc_ptr->pc->output.append((char)telnet_cmd);
-                                    break;
-                                    */
-                                 default:
-                                    pc_ptr->pc->output.append((char)IAC);
-                                    pc_ptr->pc->output.append((char)DONT);
-                                    pc_ptr->pc->output.append((char)telnet_cmd);
-                              }
-                           }
-                           break;
-                     }
-                  } //if telnet cmd
-                  else {
-                     tmp.append(pc_ptr->getInput()->charAt(i));
-                  }
-               } //for
-               pc_ptr->getInput()->Clear();
-               pc_ptr->getInput()->append(tmp);
-            } // telnet parser
-
             len = pc_ptr->getInput()->Strlen();
             if (len && ((pc_ptr->getInput()->charAt(len - 1) == '\n') ||
-                        pc_ptr->getInput()->Contains('\n')) || (len >= MAX_INPUT_LEN)) {
+                     pc_ptr->getInput()->Contains('\n')) || (len >= MAX_INPUT_LEN)) {
                if (mudlog.ofLevel(DBG)) {
                   mudlog << "processing input for: " << *(pc_ptr->getName())
-                         << ",  cmd -:" << *(pc_ptr->getInput()) << ":- " << endl;
+                     << ",  cmd -:" << *(pc_ptr->getInput()) << ":- " << endl;
                }
 
                critter* snooper;
@@ -1102,7 +1046,7 @@
                   mudlog.log(TRC, "Within snoop if\n");
                   String buf2(100);
                   Sprintf(buf2, "SNOOP_IN: %S:  %S\n",
-                          pc_ptr->getName(snooper->SEE_BIT), pc_ptr->getInput());
+                        pc_ptr->getName(snooper->SEE_BIT), pc_ptr->getInput());
                   snooper->show(buf2);
                }//if snoop
 
@@ -1123,10 +1067,10 @@
                   }//if
                   else {
                      pc_ptr->possessing->processInput(*(pc_ptr->getInput()),
-                                                      FALSE, TRUE);
+                           FALSE, TRUE);
                      if (mudlog.ofLevel(DBG)) {
                         mudlog << "input after processInput: " << *(pc_ptr->getInput())
-                               << endl;
+                           << endl;
                      }//if
                      //pc_ptr->setDoPrompt(TRUE);
                   }
@@ -1502,6 +1446,8 @@
    newd->pc = new pc_data;
    newd->CRITTER_TYPE = 0; //change default of MOB to PC
 
+   newd->pc->p_handler = new TelnetHandler(newd);
+
    mudlog.log(TRC, "In createWithDescriptor\n");
 
    if ((desc = new_connection(s)) < 0) {
@@ -1664,28 +1610,49 @@
 
 #endif
 
+// This is temporarily here for now as we need to be able to handle binary
+// data for telnet option negotiations. String::Read() assumes that we only
+// ever deal in \n terminated printable strings.
+ssize_t netread(int fd, char* input_buf, size_t max_read) {
+   ssize_t read_bytes;
+   read_bytes = recv(fd, input_buf, max_read, 0);
+   if ( read_bytes < 0 ) {
+      if ( errno != EAGAIN ) {
+         return(-1);
+      } else {
+         return(0);
+      }
+   }
+   return(read_bytes);
+}
 
+   int critter::readInput()  {
 
-int critter::readInput()  {
-   if (!pc)
-      return -1;
+      if (!pc) {
+         return -1;
+      }
 
-   errno = 0;
-   int ret;
-   ret = pc->input.Read(pc->descriptor, MAX_INPUT_LEN);
+      errno = 0;
+      int ret;
+      //ret = pc->input.Read(pc->descriptor, MAX_INPUT_LEN);
 
-   if (mudlog.ofLevel(TRC)) {
-      mudlog << "End of get_input, here it is:\n" << pc->input << ":-  ret: " << ret << endl;
-   }
-   
-   if (ret < 0) {
-      mudlog << "Critter: " << getName() << "  Read Error: " << strerror(errno) << endl;
-   }
+      char input_buf[4096];
+      ssize_t read_bytes = netread(pc->descriptor, input_buf, 4096);
 
-   return ret;  //valid input added to input buffer, can go parse it now.
-}//get_input
+      if (mudlog.ofLevel(TRC)) {
+         mudlog << "End of get_input, here it is:\n" << pc->input << ":-  ret: " << ret << endl;
+      }
 
+      if (read_bytes < 0) {
+         mudlog << "Critter: " << getName() << "  Read Error: " << strerror(errno) << endl;
+      } else if ( read_bytes > 0 ) {
+         pc->p_handler->parse(input_buf, read_bytes);
+      }
 
+      return read_bytes;  //valid input added to input buffer, can go parse it now.
+   }//get_input
+
+
 void close_sockets(int mother) {
    Cell<critter*> cell;
    pc_list.head(cell);
@@ -1713,10 +1680,10 @@
 
    if (mudlog.ofLevel(DBG)) {
       mudlog << "In doLoseLink, critter name:  " <<  *(getName())
-             << "  room:  " << getCurRoomNum() << "  addr:  " << this
-             << endl << flush;
+         << "  room:  " << getCurRoomNum() << "  addr:  " << this
+         << endl << flush;
       mudlog << " link condition:  " << pc->link_condition
-             << endl;
+         << endl;
    }
 
    if (pc->link_condition != CON_PLAYING) {
@@ -1741,7 +1708,7 @@
 
    if (mudlog.ofLevel(DBG)) {
       mudlog << "doLogOffInactive, critter:  " << *(getName())
-             << "  size of PETS:  " << PETS.size() << endl;
+         << "  size of PETS:  " << PETS.size() << endl;
    }
 
    doUngroup(1, &NULL_STRING); //take em out of their group, if in it.
@@ -1751,7 +1718,7 @@
    while ((pet_ptr = pet_cll.next())) {
       if (mudlog.ofLevel(DBG)) {
          mudlog << "PETS:  Has a pet:  " <<  *(pet_ptr->getName())
-                << "  ptr_address: " << pet_ptr << endl;
+            << "  ptr_address: " << pet_ptr << endl;
       }
    }//while
 
@@ -1762,7 +1729,7 @@
    while ((pet_ptr = pet_cll.next())) {
       if (mudlog.ofLevel(DBG)) {
          mudlog << "Tmp_List:  Has a pet:  " <<  *(pet_ptr->getName())
-                << "  ptr_address: " << pet_ptr << endl;
+            << "  ptr_address: " << pet_ptr << endl;
       }
    }//while
 
@@ -1774,7 +1741,7 @@
    while ((pet_ptr = pet_cll.next())) {
       if (mudlog.ofLevel(DBG)) {
          mudlog << "Found a pet:  " <<  *(pet_ptr->getName())
-                << endl << flush;
+            << endl << flush;
       }
       pet_ptr->show("Your master has left the game.\n");
       pet_ptr->doBecomeNonPet();
@@ -1783,7 +1750,7 @@
 
    if (PETS.size() > 0) {
       mudlog << "ERROR:  PETS.size() > 0 in doLogOffInactive:  "
-             << PETS.size() << endl << flush;
+         << PETS.size() << endl << flush;
       PETS.clear();
    }
 
@@ -1812,21 +1779,21 @@
    }
 
    doShowList(this, Selectors::instance().CC_gets_info_allow,
-              Selectors::instance().CC_none, pc_list,
-              CS_PLAYER_OFF_LD_LIST_INFO,
-              getName());
+         Selectors::instance().CC_none, pc_list,
+         CS_PLAYER_OFF_LD_LIST_INFO,
+         getName());
 
    if (MASTER) {
       doBecomeNonPet();
    }
-   
+
    emote("has left the game.");
 
    leave_room_effects(*(getCurRoom()), *this, FALSE);
    breakEarthMeld();
 
    doLeaveRoom();
-   
+
    recursive_init_unload(*this); //take eq out of circulation
 
    return 1;
@@ -1844,12 +1811,16 @@
       return -1;
    }
 
+   // no need of a protocol handler when they're D/C'ed.
+   delete pc->p_handler;
+   pc->p_handler = NULL;
+
    if (mudlog.ofLevel(DBG)) {
       mudlog << "In doGoLinkDead, critter name:  " <<  *(getName())
-             << "  room:  " << getCurRoomNum() << "  addr:  " << this
-             << endl << flush;
+         << "  room:  " << getCurRoomNum() << "  addr:  " << this
+         << endl << flush;
       mudlog << " link condition:  " << pc->link_condition
-             << endl;
+         << endl;
    }
 
    if (SNOOPED_BY) {
@@ -1864,10 +1835,10 @@
    }
 
    doShowList(this, Selectors::instance().CC_gets_info_allow,
-              Selectors::instance().CC_none, pc_list,
-              CS_PLAYER_LOST_CON_INFO,
-              getName());
-   
+         Selectors::instance().CC_none, pc_list,
+         CS_PLAYER_LOST_CON_INFO,
+         getName());
+
    if (MASTER) {
       Sprintf(buf, "%S has lost link.\n", getName());
       buf.Cap();
@@ -1880,12 +1851,12 @@
       writeOutput();
       if (close(pc->descriptor) < 0) {
          mudlog << "ERROR: close_socket, close:  " << strerror(errno) 
-                << endl;
+            << endl;
       }//if
       else {
          sockets_connected--;
       }
-      
+
       pc->descriptor = -1;
    }//if
 
@@ -1905,12 +1876,15 @@
       return -1;
    }
 
+   // remove the protocol handler
+   delete pc->p_handler;
+
    if (mudlog.ofLevel(DBG)) {
       mudlog << "In doLogOffNewLogin, critter name:  " <<  *(getName())
-             << "  room:  " << getCurRoomNum() << "  addr:  " << this
-             << endl << flush;
+         << "  room:  " << getCurRoomNum() << "  addr:  " << this
+         << endl << flush;
       mudlog << " link condition:  " << pc->link_condition
-             << endl;
+         << endl;
    }
 
    if (pc->descriptor != -1) {

Modified: trunk/mud/grrmud/server/hegemon_handler.cc
===================================================================
--- trunk/mud/grrmud/server/hegemon_handler.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/hegemon_handler.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -24,3 +24,80 @@
 #include "hegemon_handler.h"
 
 int HegemonHandler::_cnt = 0;
+
+HegemonHandler::HegemonHandler(critter* c_ptr) {
+
+   _cnt++;
+   my_critter = c_ptr;
+   current_text_state = ST_NORM;
+
+}//HegemonHandler::HegemonHandler()
+
+bool HegemonHandler::parse(const char* input_buf, size_t len) {
+   size_t i = 0;
+   const char* p;
+   bool parsed_full_command = false;
+
+   while ( i < len ) {
+
+      p = input_buf+i;
+
+      switch ( current_text_state ) {
+         case ST_NORM:
+            switch ( *p ) {
+
+               case 0x08://backspace
+                  if ( out_buf.size() > 0 ) {
+                     out_buf.resize(out_buf.size()-1);
+                  }
+               break;
+
+               case 0x0D://carriage return
+                  //do nothing, we don't like \r's around here.
+               break;
+
+               case 0x0A://newline
+                  out_buf += *p;
+                  my_critter->pc->input += out_buf.c_str();
+                  out_buf.clear();
+                  parsed_full_command = true;
+               break;
+
+               case ';':
+                  current_text_state = ST_SEMICOLON;
+               break;
+
+               default:
+                  out_buf += *p;
+               break;
+            };
+         break;
+
+         case ST_SEMICOLON:
+            switch ( *p ) {
+
+               case ';':
+                  out_buf += ';';
+               break;
+
+               case 0x08://backspace
+                  if ( out_buf.size() > 0 ) {
+                     out_buf.resize(out_buf.size()-1);
+                  }
+                  current_text_state = ST_NORM;
+               break;
+
+               default:
+                  out_buf += '\n';
+                  out_buf += *p;
+               break;
+
+            };
+         break;
+      };//switch(current_text_state)
+
+      i++;
+   }//while there's more input
+
+   return(parsed_full_command);
+}

Modified: trunk/mud/grrmud/server/hegemon_handler.h
===================================================================
--- trunk/mud/grrmud/server/hegemon_handler.h	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/hegemon_handler.h	2007-02-25 01:21:12 UTC (rev 890)
@@ -31,16 +31,22 @@
    protected:
       static int _cnt;
 
+      enum text_state { ST_NORM, ST_SEMICOLON };
+
+      text_state current_text_state;
+      std::string out_buf;
       critter* my_critter;
 
    public:
 
       static int getInstanceCount() { return _cnt; }
 
-      HegemonHandler(critter *c_ptr) : my_critter(c_ptr) { HegemonHandler::_cnt++; };
+      HegemonHandler(critter *c_ptr);
       ~HegemonHandler() { _cnt--; };
 
-      void parse(const char* input_buf) { my_critter->pc->input += input_buf; }
+      void newCritter(critter* c_ptr) { my_critter = c_ptr; };
+
+      bool parse(const char* input_buf, size_t len);
       void set_echo(bool on_off) { }
       const char* end_of_record() const { return(""); }
 };

Modified: trunk/mud/grrmud/server/login.cc
===================================================================
--- trunk/mud/grrmud/server/login.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/login.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -39,6 +39,7 @@
 #include "const.h"
 #include "Filters.h"
 #include "clients.h"
+#include "telnet_handler.h"
 
 
 extern List<critter*> new_pc_list;
@@ -64,6 +65,7 @@
    pc->input = NULL_STRING;  //null out input
    show(get_page("./opening")); //opening page
    show(login_prompts[0]); 
+   show(pc->p_handler->end_of_record());
    mudlog.log(TRC, "Done w/start_login.\n");
 }//start_login
 
@@ -189,6 +191,7 @@
             //         log("All done w/case 0.\n");
             break;
          case 1:  //password for new player
+
             string = pc->input.Get_Command(eos, term_by_period);
 
             if (string == "__HEGEMON__") {
@@ -231,6 +234,7 @@
             if (!isUsingClient())
                show(ANSI_ECHO_ON); //echo ON
             string = pc->input.Get_Command(eos, term_by_period);
+            pc->p_handler->set_echo(false);//stop echoing for the client
             if (pc->password == string) {
                pc->password = crypt((const char*)(pc->password), "bg");
                pc->index = 3; //go choose male/female/neuter
@@ -384,6 +388,8 @@
                if (!isUsingClient())
                   show(ANSI_ECHO_ON); //echo ON
 
+
+               ProtocolHandler* tmp_p_handler = pc->p_handler;
                int tmp_int = pc->descriptor;
                int tmp_index = pc->index;
                tmp_host = pc->host;
@@ -413,6 +419,7 @@
                      }//if
                      
                      fileRead(rfile, TRUE);
+
                   break;
                }
 
@@ -451,6 +458,7 @@
                   setClient(HEGEMON);
                }
                
+               pc->p_handler = tmp_p_handler;
                pc->descriptor = tmp_int;
                pc->host = tmp_host;
                pc->index = tmp_index;
@@ -497,7 +505,12 @@
                      old_ptr->pc->descriptor = pc->descriptor;
                      pc->descriptor = tmp_old_desc;
                      
-                     /*  set old player back in action */
+                     //  set old player back in action 
+                     // stick our current protocol handler into the old critter
+                     // and let our protocol handler know that it has been moved.
+                     old_ptr->pc->p_handler = pc->p_handler;
+                     old_ptr->pc->p_handler->newCritter(old_ptr);
+
                      old_ptr->cur_stats[0] &= ~32;      //make em visable again
                      old_ptr->pc->link_condition = CON_PLAYING;
                      old_ptr->pc->index = 0;
@@ -970,6 +983,10 @@
    update_skills(pc); //sync them up, does not necessarly add new ones
    pc.PC_FLAGS.turn_off(33); //make sure they aren't marked as afk
 
+   //make sure they echo for themselves
+
+   pc.pc->p_handler->set_echo(false);
+
    pc.show(get_page("./motd")); //message of the day
 
    pc.show("Welcome back!!\n\n");

Modified: trunk/mud/grrmud/server/parse.cc
===================================================================
--- trunk/mud/grrmud/server/parse.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/parse.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -271,6 +271,17 @@
          //log("Do login finished...\n");
          if (MODE != MODE_NORMAL) {
             show(login_prompts[pc->index]);
+            // turn on server side echoing for password blanking when appropriate
+            switch ( pc->index ) {
+               case 1://password for new player
+               case 2://confirm new player password
+               case 5://password for existing player
+                  pc->p_handler->set_echo(true);
+               break;
+
+               default:
+               break;
+            }
          }//if
          return 0;
       }//if logging in

Modified: trunk/mud/grrmud/server/protocol_handler.h
===================================================================
--- trunk/mud/grrmud/server/protocol_handler.h	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/protocol_handler.h	2007-02-25 01:21:12 UTC (rev 890)
@@ -47,9 +47,12 @@
 
       virtual ~ProtocolHandler() { };
 
+      // for reassociating ourself with a new critter.
+      virtual void newCritter(critter* c_ptr) = 0;
+
       // do any necessary parsing, stick the resulting data (if any) in the pc's
       // input buffer.
-      virtual void parse(const char* input_buf) = 0;
+      virtual bool parse(const char* input_buf, size_t len) = 0;
 
       // toggle server-side echoing of input
       virtual void set_echo(bool on_off) = 0;
@@ -68,10 +71,12 @@
 
       static int getInstanceCount() { return NullHandler::_cnt; }
 
-      NullHandler(critter *c_ptr) : my_critter(c_ptr) { my_critter = c_ptr; NullHandler::_cnt++; };
+      NullHandler(critter* c_ptr) { my_critter = c_ptr; NullHandler::_cnt++; };
       ~NullHandler() { NullHandler::_cnt--; };
 
-      void parse(const char* input_buf);
+      void newCritter(critter* c_ptr) { my_critter = c_ptr; };
+
+      bool parse(const char* input_buf, size_t len);
       void set_echo(bool on_off) { return; }
       const char* end_of_record() const { return(""); }
 };//class NullHandler

Modified: trunk/mud/grrmud/server/telnet_handler.cc
===================================================================
--- trunk/mud/grrmud/server/telnet_handler.cc	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/telnet_handler.cc	2007-02-25 01:21:12 UTC (rev 890)
@@ -30,6 +30,7 @@
 extern LogStream mudlog;
 
 int TelnetHandler::_cnt = 0;
+const char TelnetHandler::eor_str[2] = { IAC, EOR };
 
 TelnetHandler::TelnetHandler(critter* c_ptr) {
 
@@ -37,16 +38,17 @@
 
    my_critter = c_ptr;
    current_state = ST_TEXT;
+   current_text_state = ST_NORM;
 
    //memset is probably faster, but oh well.
    for(unsigned int i=0;i<sizeof(my_want_states);my_want_states[i++]=false);
    for(unsigned int i=0;i<sizeof(my_option_states);my_option_states[i++]=false);
 
-   //This is sort of a hack. We're assuming that we will only be instantiated
-   //immediately preceeding the login password prompt.
-   set_echo(true);
    send(DO,TELOPT_NAWS);
 
+   my_option_states[TELOPT_EOR] = true;
+   send(WILL,TELOPT_EOR);
+
 }//Constructor: TelnetHandler
 
 void TelnetHandler::send(int action, int option) {
@@ -62,11 +64,13 @@
 }//TelnetHandler::send()
 
 //handle DOs
-void TelnetHandler::rcv_do(const int opt) {
+void TelnetHandler::rcv_do(int opt) {
 
    bool need_to_respond = false;
    bool will = false;
 
+   mudlog << "TelnetHandler::rcv_do received: IAC DO " << opt << endl;
+
    //If we are already doing what they're asking for, we just ignore that they
    //asked. this is the behaviour required by the rfc.
    if ( ! my_option_states[opt] ) {
@@ -109,9 +113,11 @@
 }//TelnetHandler::rcv_do()
 
 //handle DONTs
-void TelnetHandler::rcv_dont(const int opt) {
+void TelnetHandler::rcv_dont(int opt) {
    bool need_to_respond = false;
 
+   mudlog << "TelnetHandler::rcv_dont received: IAC DONT " << opt << endl;
+
    //the rfc requires that we never refuse to turn off a feature and that we
    //be willing to drop down to basics.
 
@@ -129,26 +135,30 @@
 }//TelnetHandler::rcv_dont()
 
 //handle WILLs
-void TelnetHandler::rcv_will(const int opt) {
+void TelnetHandler::rcv_will(int opt) {
    // I don't expect to have to deal with these, but for now I'll log them to
    // find out if I'm wrong.
    mudlog << "TelnetHandler::rcv_will received: IAC WILL " << opt << endl;
 }//TelnetHandler::rcv_will()
 
 //handle WONTs
-void TelnetHandler::rcv_wont(const int opt) {
+void TelnetHandler::rcv_wont(int opt) {
    // The only thing that might come back to us here is NAWS as I don't plan
    // on asking the client to do much more than that. so for now, just log the
    // fact that they said they wouldn't do something.
    mudlog << "TelnetHandler::rcv_wont received: IAC WONT " << opt << endl;
 }//TelnetHandler::rcv_wont()
 
-void TelnetHandler::parse(const char* input_buf) {
+bool TelnetHandler::parse(const char* input_buf, size_t len) {
 
-   const char* p = input_buf;
+   size_t i=0;
+   const char* p;
+   bool parsed_full_command = false;
 
-   while ( *p ) {
+   while ( i < len ) {
 
+      p = input_buf+i;
+
       switch ( current_state ) {
 
          case ST_TEXT:
@@ -159,16 +169,75 @@
                break;
 
                default:
-                  my_critter->pc->input += *p;
+                  // we don't directly append to the pc's buf as the command
+                  // parser isn't currently smart enough to deal with
+                  // incomplete commands. We also need to handle backspace,
+                  // etc. These things were previously dealt with in
+                  // String::Read()
+                  switch ( current_text_state ) {
+                     case ST_NORM:
+                        switch ( *p ) {
+
+                           case 0x08://backspace
+                              if ( out_buf.size() > 0 ) {
+                                 out_buf.resize(out_buf.size()-1);
+                              }
+                           break;
+
+                           case 0x0D://carriage return
+                              //do nothing, we don't like \r's around here.
+                           break;
+
+                           case 0x0A://newline
+                              out_buf += *p;
+                              my_critter->pc->input += out_buf.c_str();
+                              out_buf.clear();
+                              parsed_full_command = true;
+                           break;
+
+                           case ';':
+                              current_text_state = ST_SEMICOLON;
+                           break;
+
+                           default:
+                              out_buf += *p;
+                           break;
+                        };
+                     break;
+
+                     case ST_SEMICOLON:
+                        switch ( *p ) {
+
+                           case ';':
+                              out_buf += ';';
+                           break;
+
+                           case 0x08://backspace
+                              if ( out_buf.size() > 0 ) {
+                                 out_buf.resize(out_buf.size()-1);
+                              }
+                              current_text_state = ST_NORM;
+                           break;
+
+                           default:
+                              out_buf += '\n';
+                              out_buf += *p;
+                           break;
+
+                        };
+                        current_text_state = ST_NORM;
+                     break;
+
+                  }//switch(current_text_state)
                break;
-            };
-         break;
+            };//ST_TEXT: switch(*p)
+         break;//end ST_TEXT
 
          case ST_IAC:
             switch (*p) {
 
                case IAC://escaped IAC.
-                  my_critter->pc->input += *p;
+                  out_buf += *p;
                break;
 
                case DO:
@@ -192,24 +261,30 @@
                break;
 
                default:
+                  //invalid transistion
+                  current_state = ST_TEXT;
                break;
             };
          break;
 
          case ST_DO:
             rcv_do(*p);
+            current_state = ST_TEXT;
          break;
 
          case ST_DONT:
             rcv_dont(*p);
+            current_state = ST_TEXT;
          break;
 
          case ST_WILL:
             rcv_will(*p);
+            current_state = ST_TEXT;
          break;
 
          case ST_WONT:
             rcv_wont(*p);
+            current_state = ST_TEXT;
          break;
 
          case ST_SB://processing a sub-option datastream
@@ -223,7 +298,7 @@
                   sb_buf += *p;
                   // sanity check this to prevent resource exhaustion from a
                   // rogue client
-                  if ( sb_buf.Strlen() > 256 ) {
+                  if ( sb_buf.size() > 256 ) {
                      sb_buf.clear();
                      current_state = ST_TEXT;
                   }
@@ -236,6 +311,7 @@
 
                case IAC://escaped IAC character.
                   sb_buf += *p;
+                  current_state = ST_SB;
                break;
 
                case SE://end of sub-option data
@@ -255,9 +331,11 @@
 
       };//switch ( telnet_state )
 
-      p++;
+      i++;
    }//while there's more input
 
+   return(parsed_full_command);
+
 }//TelnetHandler::parse()
 
 bool TelnetHandler::should_echo() const {
@@ -294,37 +372,35 @@
    //for now we ignore everything but NAWS, and even then just spew some log
    //information about it as we haven't established a place to store it in the
    //pcdata yet.
-   if ( sb_buf.Strlen() == 0 ) {
+   if ( sb_buf.size() == 0 ) {
       return;
    }
-   switch ( sb_buf[0] ) {
+
+   const char* p = sb_buf.data();
+
+   switch ( *p ) {
       case TELOPT_NAWS: {
          short width, height;
-         union 
-         {
-            short s;
-            char a;
-            char b;
-         } i_tmp;
 
          width = height = -1;
-         if ( sb_buf.Strlen() != 5 ) {
+         if ( sb_buf.size() != 5 ) {
             //NAWS should be: NAWS WIDTH[1] WIDTH[0] HEIGHT[1] HEIGHT[0]
             mudlog
                << "TelnetHandler::process_subopt() received malformed NAWS of len "
-               << sb_buf.Strlen()
+               << sb_buf.size()
                << endl;
             break;
          }
 
-         i_tmp.a = sb_buf[1];
-         i_tmp.b = sb_buf[2];
-         width = ntohs(i_tmp.s);
+         width = *(short *)(p+1);
+         height = *(short *)(p+3);
 
-         i_tmp.a = sb_buf[3];
-         i_tmp.b = sb_buf[4];
-         height = ntohs(i_tmp.s);
+         width = ntohs(width);
+         height = ntohs(height);
 
+         my_critter->pc->lines_on_page = height;
+         my_critter->pc->columns_on_page = width;
+
          mudlog << "TelnetHandler::process_subopt() received NAWS "
             << "width: " << width << " height: " << height << endl;
       }//TELOPT_NAWS
@@ -338,3 +414,17 @@
    sb_buf.clear();
 
 }//TelnetHandler::process_subopt()
+
+const char* TelnetHandler::end_of_record() const {
+
+   if ( my_option_states[TELOPT_EOR] ) {
+      return(TelnetHandler::eor_str);
+   } else {
+      return("");
+   }
+
+}//TelnetHandler::end_of_record()
+
+void TelnetHandler::newCritter(critter* c_ptr) {
+   my_critter = c_ptr;
+}//TelnetHandler::newCritter()

Modified: trunk/mud/grrmud/server/telnet_handler.h
===================================================================
--- trunk/mud/grrmud/server/telnet_handler.h	2007-02-24 09:41:40 UTC (rev 889)
+++ trunk/mud/grrmud/server/telnet_handler.h	2007-02-25 01:21:12 UTC (rev 890)
@@ -32,12 +32,15 @@
 
    protected:
       static int _cnt;
+      static const char eor_str[2];
 
       enum state { ST_TEXT, ST_IAC, ST_DO, ST_DONT, ST_WILL, ST_WONT, ST_SB, ST_SB_IAC };
+      enum text_state { ST_NORM, ST_SEMICOLON };
 
       state current_state;
-      String sb_buf;
-      String eor_str;
+      text_state current_text_state;
+      std::string sb_buf;
+      std::string out_buf;
       critter* my_critter;
 
       bool my_want_states[256];  //things I've requested or offered.
@@ -49,19 +52,23 @@
       void rcv_wont(int opt);
 
       void process_subopt();
+      void process_out_buf();
 
       //inserts IAC action option into my_critter's outbuf.
       void send(int action, int option);
 
+      bool should_echo() const;
+
    public:
+      static int getInstanceCount() { return _cnt; }
+
       TelnetHandler(critter* c_ptr);
       ~TelnetHandler() { _cnt--; };
 
-      void parse(const char* input_buf);
-
+      void newCritter(critter* c_ptr);
+      bool parse(const char* input_buf, size_t len);
       void set_echo(bool on_off);
-      bool should_echo() const;
-      const char* end_of_record() const { return( (const char*)eor_str ); }
+      const char* end_of_record() const;
 
 };
 




More information about the ScryMUD mailing list