[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