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

scrymud at wanfear.com scrymud at wanfear.com
Sat Feb 24 01:41:40 PST 2007


Author: eroper
Date: 2007-02-24 01:41:40 -0800 (Sat, 24 Feb 2007)
New Revision: 889

Added:
   trunk/mud/grrmud/server/hegemon_handler.cc
Modified:
   trunk/mud/grrmud/server/hegemon_handler.h
   trunk/mud/grrmud/server/protocol_handler.h
   trunk/mud/grrmud/server/telnet_handler.cc
   trunk/mud/grrmud/server/telnet_handler.h
Log:
More work on the protocol stuff.


Added: trunk/mud/grrmud/server/hegemon_handler.cc
===================================================================
--- trunk/mud/grrmud/server/hegemon_handler.cc	                        (rev 0)
+++ trunk/mud/grrmud/server/hegemon_handler.cc	2007-02-24 09:41:40 UTC (rev 889)
@@ -0,0 +1,26 @@
+// $Id$
+
+//
+//ScryMUD Server Code
+//Copyright (C) 2007  Edward Roper
+//
+//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 (at your option) 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; if not, write to the Free Software
+//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//
+// To contact the Author, Edward Roper: edro <- at -> wanfear.net
+//
+
+#include "hegemon_handler.h"
+
+int HegemonHandler::_cnt = 0;


Property changes on: trunk/mud/grrmud/server/hegemon_handler.cc
___________________________________________________________________
Name: svn:keywords
   + Id Author Date Revision

Modified: trunk/mud/grrmud/server/hegemon_handler.h
===================================================================
--- trunk/mud/grrmud/server/hegemon_handler.h	2007-02-23 09:27:57 UTC (rev 888)
+++ trunk/mud/grrmud/server/hegemon_handler.h	2007-02-24 09:41:40 UTC (rev 889)
@@ -35,13 +35,13 @@
 
    public:
 
-      static int getInstanceCount() { return HegemonHandler::_cnt; }
+      static int getInstanceCount() { return _cnt; }
 
       HegemonHandler(critter *c_ptr) : my_critter(c_ptr) { HegemonHandler::_cnt++; };
-      ~HegemonHandler() { HegemonHandler::_cnt--; };
+      ~HegemonHandler() { _cnt--; };
 
       void parse(const char* input_buf) { my_critter->pc->input += input_buf; }
-      void toggle_echo() { }
+      void set_echo(bool on_off) { }
       const char* end_of_record() const { return(""); }
 };
 

Modified: trunk/mud/grrmud/server/protocol_handler.h
===================================================================
--- trunk/mud/grrmud/server/protocol_handler.h	2007-02-23 09:27:57 UTC (rev 888)
+++ trunk/mud/grrmud/server/protocol_handler.h	2007-02-24 09:41:40 UTC (rev 889)
@@ -38,6 +38,10 @@
 #ifndef GRRMUD_PROTOCOL_HANDLER
 #define GRRMUD_PROTOCOL_HANDLER
 
+class ProtocolHandler;
+
+#include "critter.h"
+
 class ProtocolHandler {
    public:
 
@@ -45,13 +49,13 @@
 
       // do any necessary parsing, stick the resulting data (if any) in the pc's
       // input buffer.
-      virtual void parse(const char* input_buf);
+      virtual void parse(const char* input_buf) = 0;
 
       // toggle server-side echoing of input
-      virtual void toggle_echo();
+      virtual void set_echo(bool on_off) = 0;
 
       // return a string used to mark end-of-record (player prompt)
-      virtual const char* end_of_record();
+      virtual const char* end_of_record() const = 0;
 };//class ProtocolHandler
 
 class NullHandler : public ProtocolHandler {
@@ -64,11 +68,11 @@
 
       static int getInstanceCount() { return NullHandler::_cnt; }
 
-      NullHandler(critter *c_ptr) : my_critter(c_ptr) { NullHandler::_cnt++; };
+      NullHandler(critter *c_ptr) : my_critter(c_ptr) { my_critter = c_ptr; NullHandler::_cnt++; };
       ~NullHandler() { NullHandler::_cnt--; };
 
-      void parse(const char* input_buf) { my_critter->pc->input += input_buf; }
-      void toggle_echo() { return; }
+      void parse(const char* input_buf);
+      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-23 09:27:57 UTC (rev 888)
+++ trunk/mud/grrmud/server/telnet_handler.cc	2007-02-24 09:41:40 UTC (rev 889)
@@ -22,59 +22,128 @@
 //
 
 #include "telnet_handler.h"
+#include "telnet.h"
+#include "LogStream.h"
 
+#include <arpa/inet.h>
+
+extern LogStream mudlog;
+
+int TelnetHandler::_cnt = 0;
+
 TelnetHandler::TelnetHandler(critter* c_ptr) {
 
-   TelnetHandler::_cnt++;
+   _cnt++;
 
    my_critter = c_ptr;
    current_state = ST_TEXT;
 
    //memset is probably faster, but oh well.
-   for(int i=0;i<sizeof(my_want_states);my_want_states[i++]=false);
-   for(int i=0;i<sizeof(my_option_states);my_option_states[i++]=false);
+   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);
+
 }//Constructor: TelnetHandler
 
+void TelnetHandler::send(int action, int option) {
+
+   char msg[4];
+   msg[0] = IAC;
+   msg[1] = action;
+   msg[2] = option;
+   msg[3] = '\0';
+
+   my_critter->pc->output += msg;
+
+}//TelnetHandler::send()
+
 //handle DOs
 void TelnetHandler::rcv_do(const int opt) {
 
-   if ( my_want_states[opt] ) {
+   bool need_to_respond = false;
+   bool will = false;
 
-   }
+   //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] ) {
 
-   switch ( opt ) {
+      //If we did not start the conversation with a WILL offer, we need to
+      //respond with a WILL.
+      if ( my_want_states[opt] ) {
+         need_to_respond = false;
+         my_want_states[opt] = false;
+      }  else {
+         need_to_respond = true;
+      }
 
-      case TELOPT_ECHO:
-      break;
+      switch ( opt ) {
 
-      case TELOPT_EOR:
-      break;
+         case TELOPT_ECHO:
+         case TELOPT_EOR:
+            my_option_states[opt] = will = true;
+         break;
 
-      default:
-      break;
+         default:
+            need_to_respond = true;
+            will = false;
+         break;
 
-   };
+      };
 
+   }//if not already doing
+
+   if ( need_to_respond ) {
+
+      if ( will ) {
+         send(WILL,opt);
+      } else {
+         send(WONT,opt);
+      }
+
+   }
+
 }//TelnetHandler::rcv_do()
 
 //handle DONTs
 void TelnetHandler::rcv_dont(const int opt) {
+   bool need_to_respond = false;
+
+   //the rfc requires that we never refuse to turn off a feature and that we
+   //be willing to drop down to basics.
+
+   if ( my_option_states[opt] ) {
+      my_option_states[opt] = false;
+      need_to_respond = true;
+   } else {
+      need_to_respond = false;
+   }
+
+   if ( need_to_respond ) {
+      send(WONT,opt);
+   }
+
 }//TelnetHandler::rcv_dont()
 
 //handle WILLs
 void TelnetHandler::rcv_will(const 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) {
-   // 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.
+   // 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) {
-   using namespace telnet;
 
    const char* p = input_buf;
 
@@ -98,7 +167,7 @@
          case ST_IAC:
             switch (*p) {
 
-               case IAC://escaped IAC
+               case IAC://escaped IAC.
                   my_critter->pc->input += *p;
                break;
 
@@ -151,12 +220,12 @@
                break;
 
                default://default here is to append to sb_buf
+                  sb_buf += *p;
                   // sanity check this to prevent resource exhaustion from a
                   // rogue client
-                  sb_buf += *p;
                   if ( sb_buf.Strlen() > 256 ) {
+                     sb_buf.clear();
                      current_state = ST_TEXT;
-                     sb_buf.clear();
                   }
                break;
             };
@@ -165,16 +234,20 @@
          case ST_SB_IAC:
             switch (*p) {
 
-               case IAC:
+               case IAC://escaped IAC character.
                   sb_buf += *p;
                break;
 
                case SE://end of sub-option data
+                  process_subopt();
                   sb_buf.clear();
+                  current_state = ST_TEXT;
                break;
 
                default:
                   //this state transistion is not valid
+                  current_state = ST_TEXT;
+                  sb_buf.clear();
                break;
 
             };
@@ -186,3 +259,82 @@
    }//while there's more input
 
 }//TelnetHandler::parse()
+
+bool TelnetHandler::should_echo() const {
+   return my_option_states[TELOPT_ECHO];
+}//TelnetHandler::should_echo()
+
+void TelnetHandler::set_echo(bool on_off) {
+
+   //do nothing if we're already at the requested state.
+   if ( on_off == my_option_states[TELOPT_ECHO] ) {
+      return;
+   }
+
+   switch ( on_off ) {
+
+      case true:
+         my_want_states[TELOPT_ECHO] = true;
+         send(WILL,TELOPT_ECHO);
+      break;
+
+      case false:
+         //not sure if we're supposed to wait for a DONT, but since a WONT is
+         //a "refusal" to do, or continue doing, I don't assume we technically
+         //need to wait.
+         my_option_states[TELOPT_ECHO] = false;
+         send(WONT,TELOPT_ECHO);
+      break;
+
+   };
+
+}//TelnetHandler::set_echo()
+
+void TelnetHandler::process_subopt() {
+   //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 ) {
+      return;
+   }
+   switch ( sb_buf[0] ) {
+      case TELOPT_NAWS: {
+         short width, height;
+         union 
+         {
+            short s;
+            char a;
+            char b;
+         } i_tmp;
+
+         width = height = -1;
+         if ( sb_buf.Strlen() != 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()
+               << endl;
+            break;
+         }
+
+         i_tmp.a = sb_buf[1];
+         i_tmp.b = sb_buf[2];
+         width = ntohs(i_tmp.s);
+
+         i_tmp.a = sb_buf[3];
+         i_tmp.b = sb_buf[4];
+         height = ntohs(i_tmp.s);
+
+         mudlog << "TelnetHandler::process_subopt() received NAWS "
+            << "width: " << width << " height: " << height << endl;
+      }//TELOPT_NAWS
+      break;
+
+      default:
+      break;
+
+   }//switch(sb_buf[0])
+
+   sb_buf.clear();
+
+}//TelnetHandler::process_subopt()

Modified: trunk/mud/grrmud/server/telnet_handler.h
===================================================================
--- trunk/mud/grrmud/server/telnet_handler.h	2007-02-23 09:27:57 UTC (rev 888)
+++ trunk/mud/grrmud/server/telnet_handler.h	2007-02-24 09:41:40 UTC (rev 889)
@@ -28,12 +28,6 @@
 #include "critter.h"
 #include "protocol_handler.h"
 
-namespace telnet {
-
-#include "telnet.h"
-
-};
-
 class TelnetHandler : public ProtocolHandler {
 
    protected:
@@ -49,20 +43,26 @@
       bool my_want_states[256];  //things I've requested or offered.
       bool my_option_states[256];//the current state of things.
 
+      void rcv_do(int opt);
+      void rcv_dont(int opt);
+      void rcv_will(int opt);
+      void rcv_wont(int opt);
+
+      void process_subopt();
+
+      //inserts IAC action option into my_critter's outbuf.
+      void send(int action, int option);
+
    public:
       TelnetHandler(critter* c_ptr);
-      ~TelnetHandler() { TelnetHandler::_cnt--; };
+      ~TelnetHandler() { _cnt--; };
 
       void parse(const char* input_buf);
 
-      void toggle_echo() { }
+      void set_echo(bool on_off);
+      bool should_echo() const;
       const char* end_of_record() const { return( (const char*)eor_str ); }
 
-      void rcv_do(int opt);
-      void rcv_dont(int opt);
-      void rcv_will(int opt);
-      void rcv_wont(int opt);
-
 };
 
 #endif




More information about the ScryMUD mailing list