diff options
Diffstat (limited to 'src/protocoltelnet.h')
-rw-r--r-- | src/protocoltelnet.h | 151 |
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 | ||
7 | namespace Bu | 10 | namespace 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 | ||