summaryrefslogtreecommitdiff
path: root/src/protocoltelnet.h
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2007-10-14 22:27:51 +0000
committerMike Buland <eichlan@xagasoft.com>2007-10-14 22:27:51 +0000
commite72d6077b475bc6142afc3b5967db113922c76f5 (patch)
tree45bdb7b69ec4c1dbcfadc1fa568b1d6b341a6f0f /src/protocoltelnet.h
parent44eac9521632f8da42f73085db945bdba45f8311 (diff)
downloadlibbu++-e72d6077b475bc6142afc3b5967db113922c76f5.tar.gz
libbu++-e72d6077b475bc6142afc3b5967db113922c76f5.tar.bz2
libbu++-e72d6077b475bc6142afc3b5967db113922c76f5.tar.xz
libbu++-e72d6077b475bc6142afc3b5967db113922c76f5.zip
Fixed an interesting ideosyncacy in Bu::Hash in a safe way, I should try to do
this with the Bu::Archive next. Basically, there's one generic template function that will convert anything that can safely cast to a uint32_t and that supports direct comparisson, and doesn't have it's own override already to be a Hash key, such as char, uint8_t, uint64_t, etc. The Telnet protocol handler does everything I need it too for now, next up for it is escape sequence handling, it would be nice to make this general too, by using the termcap database or something, but there is an ANSI/ISO standard now, I may just go ahead and use that. Also, it looks like it'd be pretty easy to make the canonical mode editing functions be pluggable to facilitate different types of editing, but that can be done down the road as well.
Diffstat (limited to 'src/protocoltelnet.h')
-rw-r--r--src/protocoltelnet.h151
1 files changed, 135 insertions, 16 deletions
diff --git a/src/protocoltelnet.h b/src/protocoltelnet.h
index 3a606b5..f773f1e 100644
--- a/src/protocoltelnet.h
+++ b/src/protocoltelnet.h
@@ -3,35 +3,131 @@
3 3
4#include "bu/protocol.h" 4#include "bu/protocol.h"
5#include "bu/hash.h" 5#include "bu/hash.h"
6#include "bu/fstring.h"
7
8// #define __TELNET_DEBUG
6 9
7namespace Bu 10namespace Bu
8{ 11{
12 /**
13 * Telnet Protocol handler. This attempts to provide useful and general
14 * support for most of the most commonly used Telnet extensions in a simple
15 * and easy to use way. The Option variables control the settings that can
16 * be used on the line, and control which virtual "callbacks" will be called
17 * when different events happen.
18 *
19 * To setup initial values and to disable any options you wish override the
20 * onNewConnection function in your own class, like this:
21 *@code
22 class MyTelnet : public Bu::ProtocolTelnet
23 {
24 public:
25 ...
26
27 virtual void onNewConnection( class Bu::Client *pClient )
28 {
29 // Call the parent class' onNewConnection to get everything all
30 // set up.
31 Bu::ProtocolTelnet::onNewConnection( pClient );
32
33 // These functions disable the option to send files via telnet,
34 // disabling the remote option means that we won't accept this
35 // option (binary data being sent to us) from the client.
36 //
37 // Disabling the local option means that the client cannot ask us
38 // to send them binary data.
39 oBinary.enableRemote( false );
40 oBinary.enableLocal( false );
41
42 // This requests that the client send us window size updates
43 // whenever the size of their window changes, and an initial set to
44 // boot.
45 //
46 // To see if this option is set later, try oNAWS.isRemoteSet(), but
47 // wait a little while, asking immediatly will always return false,
48 // since the remote side has yet to receive our request.
49 oNAWS.remoteSet();
50 }
51 }
52 @endcode
53 *
54 */
9 class ProtocolTelnet : public Protocol 55 class ProtocolTelnet : public Protocol
10 { 56 {
11 public: 57 public:
12 ProtocolTelnet(); 58 ProtocolTelnet();
13 virtual ~ProtocolTelnet(); 59 virtual ~ProtocolTelnet();
14 60
61 /**
62 * If you override this function in a child class, make sure to call
63 * this version of it as the very first thing that you do, before you
64 * set any options. See the example in the class docs.
65 */
15 virtual void onNewConnection( class Bu::Client *pClient ); 66 virtual void onNewConnection( class Bu::Client *pClient );
67
68 /**
69 * You should never override this function unless you really, really
70 * know what you're doing. If you want to get data after each line
71 * entered (in canonical mode) or after any data arrives (non canonical
72 * mode) then override the gotLine and gotData functions, respectively.
73 */
16 virtual void onNewData( class Bu::Client *pClient ); 74 virtual void onNewData( class Bu::Client *pClient );
17 75
18 enum OptMode 76 /**
19 { 77 * Override this function to be notified of lines being submitted by
20 optOff, 78 * the client. This function is only called in canonical mode, after
21 optOn, 79 * all edits are performed on the data. In this mode weather you use
22 optDesire, 80 * the line or not, the data will be cleared from the buffer when this
23 optRefuse 81 * function returns, any changes made to the buffer will be destroyed.
24 }; 82 */
83 virtual void gotLine( Bu::FString &sLine ){};
25 84
26 OptMode getLocalOptBinary(); 85 /**
27 void setLocalOptBinary( OptMode eMode ); 86 * Override this function to be notified of any new data that comes in
28 OptMode getRemoteOptBinary(); 87 * from the client. This function is only called in non-canonical mode,
29 void setRemoteOptBinary( OptMode eMode ); 88 * and includes all raw data minus telnet control codes and ansi
89 * escape sequences. In this mode control of the buffer is up to the
90 * child class in this function, the buffer will never be cleared unless
91 * it happens in this function's override.
92 */
93 virtual void gotData( Bu::FString &sData ){};
30 94
31 OptMode getLocalOptEcho(); 95 /**
32 void setLocalOptEcho( OptMode eMode ); 96 * Using this function to enable or disable canonical mode only affects
33 OptMode getRemoteOptEcho(); 97 * the way the data is processed and which virtual functions are called
34 void setRemoteOptEcho( OptMode eMode ); 98 * during processing. It does not affect options set locally or
99 * remotely. Setting this to false will enable char-at-a-time mode,
100 * effectively disabling internal line-editing code. Characters
101 * such as backspace that are detected will not be handled and will be
102 * sent to the user override. The subclass will also be notified every
103 * time new data is available, not just whole lines.
104 *
105 * When set to true (the default), line editing control codes will be
106 * interpreted and used, and the subclass will only be notified when
107 * complete lines are available in the buffer.
108 */
109 void setCanonical( bool bCon=true );
110 bool isCanonical();
111
112 void write( const Bu::FString &sData );
113 void write( char *pData, int iSize );
114 void write( char cData );
115
116 public:
117 /**
118 * If you wish to know the current dimensions of the client window,
119 * override this function, it will be called whenever the size changes.
120 */
121 virtual void onSubNAWS( uint16_t iWidth, uint16_t iHeight ){};
122
123 /**
124 * This function is called whenever an unknown sub negotiation option is
125 * sent over the line. This doesn't mean that it's malformatted, it
126 * just means that this class doesn't support that option yet, but you
127 * can handle it yourself if you'd like. Feel free to change the
128 * sSubBuf, it will be cleared as soon as this function returns anyway.
129 */
130 virtual void onSubUnknown( char cSubOpt, Bu::FString &sSubBuf ){};
35 131
36 private: 132 private:
37 /** 133 /**
@@ -75,15 +171,38 @@ namespace Bu
75 char fOpts; 171 char fOpts;
76 char cCode; 172 char cCode;
77 }; 173 };
174 friend class Bu::ProtocolTelnet::Option;
78 175
79 Hash<char, Option *> hOpts; 176 Hash<char, Option *> hOpts;
80 177
178 public:
81 Option oBinary; 179 Option oBinary;
82 Option oEcho; 180 Option oEcho;
181 Option oNAWS;
182 Option oSuppressGA;
83 183
184 private:
185 void onWill( char cCode );
186 void onWont( char cCode );
187 void onDo( char cCode );
188 void onDont( char cCode );
189 void onSubOpt();
190 void onCtlChar( char cChr );
191
192#ifdef __TELNET_DEBUG
193 void printCode( char cCode );
194 void printOpt( char cOpt );
195#endif
196
197 private:
84 Client *pClient; 198 Client *pClient;
85 199
86 friend class Bu::ProtocolTelnet::Option; 200 Bu::FString sDataBuf; /**< Buffer for regular line data. */
201 Bu::FString sSubBuf; /**< Buffer for subnegotiation data. */
202 char cSubOpt; /**< Which suboption are we processing. */
203
204 bool bCanonical; /**< Are we canonicalizing incoming data? */
205 bool bSubOpt; /**< Are we processing a suboption right now? */
87 }; 206 };
88} 207}
89 208