summaryrefslogtreecommitdiff
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
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.
-rw-r--r--Doxyfile4
-rw-r--r--misc/iana-telnet-options.txt486
-rw-r--r--misc/rfc854-telnet.txt854
-rw-r--r--src/hash.cpp20
-rw-r--r--src/hash.h14
-rw-r--r--src/protocolhttp.h9
-rw-r--r--src/protocoltelnet.cpp532
-rw-r--r--src/protocoltelnet.h151
-rw-r--r--src/tests/telnetsrv.cpp85
9 files changed, 2075 insertions, 80 deletions
diff --git a/Doxyfile b/Doxyfile
index 4e64a4c..220119a 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -65,7 +65,7 @@ GENERATE_DEPRECATEDLIST= YES
65ENABLED_SECTIONS = 65ENABLED_SECTIONS =
66MAX_INITIALIZER_LINES = 30 66MAX_INITIALIZER_LINES = 30
67SHOW_USED_FILES = YES 67SHOW_USED_FILES = YES
68SHOW_DIRECTORIES = YES 68SHOW_DIRECTORIES = NO
69FILE_VERSION_FILTER = 69FILE_VERSION_FILTER =
70#--------------------------------------------------------------------------- 70#---------------------------------------------------------------------------
71# configuration options related to warning and progress messages 71# configuration options related to warning and progress messages
@@ -258,7 +258,7 @@ INCLUDE_GRAPH = YES
258INCLUDED_BY_GRAPH = YES 258INCLUDED_BY_GRAPH = YES
259CALL_GRAPH = NO 259CALL_GRAPH = NO
260GRAPHICAL_HIERARCHY = YES 260GRAPHICAL_HIERARCHY = YES
261DIRECTORY_GRAPH = YES 261DIRECTORY_GRAPH = NO
262DOT_IMAGE_FORMAT = png 262DOT_IMAGE_FORMAT = png
263DOT_PATH = 263DOT_PATH =
264DOTFILE_DIRS = 264DOTFILE_DIRS =
diff --git a/misc/iana-telnet-options.txt b/misc/iana-telnet-options.txt
new file mode 100644
index 0000000..d1338a3
--- /dev/null
+++ b/misc/iana-telnet-options.txt
@@ -0,0 +1,486 @@
1
2TELNET OPTIONS
3
4(last updated 2003-11-06)
5
6The Telnet Protocol has a number of options that may be negotiated.
7These options are listed here. "Internet Official Protocol Standards"
8(STD 1) provides more detailed information.
9
10Options Name References
11------- ----------------------- ----------
12 0 Binary Transmission [RFC856]
13 1 Echo [RFC857]
14 2 Reconnection [NIC50005]
15 3 Suppress Go Ahead [RFC858]
16 4 Approx Message Size Negotiation [ETHERNET]
17 5 Status [RFC859]
18 6 Timing Mark [RFC860]
19 7 Remote Controlled Trans and Echo [RFC726]
20 8 Output Line Width [NIC50005]
21 9 Output Page Size [NIC50005]
22 10 Output Carriage-Return Disposition [RFC652]
23 11 Output Horizontal Tab Stops [RFC653]
24 12 Output Horizontal Tab Disposition [RFC654]
25 13 Output Formfeed Disposition [RFC655]
26 14 Output Vertical Tabstops [RFC656]
27 15 Output Vertical Tab Disposition [RFC657]
28 16 Output Linefeed Disposition [RFC658]
29 17 Extended ASCII [RFC698]
30 18 Logout [RFC727]
31 19 Byte Macro [RFC735]
32 20 Data Entry Terminal [RFC1043,RFC732]
33 21 SUPDUP [RFC736,RFC734]
34 22 SUPDUP Output [RFC749]
35 23 Send Location [RFC779]
36 24 Terminal Type [RFC1091]
37 25 End of Record [RFC885]
38 26 TACACS User Identification [RFC927]
39 27 Output Marking [RFC933]
40 28 Terminal Location Number [RFC946]
41 29 Telnet 3270 Regime [RFC1041]
42 30 X.3 PAD [RFC1053]
43 31 Negotiate About Window Size [RFC1073]
44 32 Terminal Speed [RFC1079]
45 33 Remote Flow Control [RFC1372]
46 34 Linemode [RFC1184]
47 35 X Display Location [RFC1096]
48 36 Environment Option [RFC1408]
49 37 Authentication Option [RFC2941]
50 38 Encryption Option [RFC2946]
51 39 New Environment Option [RFC1572]
52 40 TN3270E [RFC1647]
53 41 XAUTH [Earhart]
54 42 CHARSET [RFC2066]
55 43 Telnet Remote Serial Port (RSP) [Barnes]
56 44 Com Port Control Option [RFC2217]
57 45 Telnet Suppress Local Echo [Atmar]
58 46 Telnet Start TLS [Boe]
59 47 KERMIT [RFC2840]
60 48 SEND-URL [Croft]
61 49 FORWARD_X [Altman]
62 50-137 Unassigned [IANA]
63 138 TELOPT PRAGMA LOGON [McGregory]
64 139 TELOPT SSPI LOGON [McGregory]
65 140 TELOPT PRAGMA HEARTBEAT [McGregory]
66 255 Extended-Options-List [RFC861]
67
68Telnet Authentication Types (Option 37)
69
70In [RFC2941], a list of authentication commands and types is
71documented. Additions to the list are registerd by the IANA and
72documented here. Note: Authentication types followed by (*) were
73never submitted to the IETF for consideration as an Internet standard.
74
75Command Description Reference
76 0 IS [RFC2941]
77 1 SEND [RFC2941]
78 2 REPLY [RFC2941]
79 3 NAME [RFC2941]
80
81Type Description Reference
82 0 NULL [RFC2941]
83 1 KERBEROS_V4 [RFC2941]
84 2 KERBEROS_V5 [RFC2942]
85 3 SPX [RFC2941] *
86 4 MINK [RFC2941] *
87 5 SRP [RFC2944]
88 6 RSA (also used by SRA) [RFC2941]
89 7 SSL [RFC2941]
90 8-9 Unassigned [IANA]
91 10 LOKI [RFC2941] *
92 11 SSA [Schoch]
93 12 KEA_SJ [RFC2951]
94 13 KEA_SJ_INTEG [RFC2951]
95 14 DSS [RFC2943]
96 15 NTLM [Kahn] *
97
98In [RFC 1411], on the KERBEROS_V4 Telnet Authentication type there are
99a set of Suboption Commands. Additions to the list are registerd by
100the IANA and documented here.
101
102Suboption Command Reference
103 0 AUTH [RFC1411]
104 1 REJECT [RFC1411]
105 2 ACCEPT [RFC1411]
106 3 CHALLENGE [RFC1411]
107 4 RESPONSE [RFC1411]
108 5 FORWARD [Brashear]
109 6 FORWARD-ACCEPT [Brashear]
110 7 FORWARD-REJECT [Brashear]
111 8 EXP [Wu]
112 9 PARAMS [Wu]
113
114
115In the KERBEROS_V5 Telnet Authentication type there are a set of
116Suboption Commands. Additions to the list are registerd by the IANA
117and documented here.
118
119Suboption Command Reference
120 0 AUTH [RFC2942]
121 1 REJECT [RFC2942]
122 2 ACCEPT [RFC2942]
123 3 RESPONSE [RFC2942]
124 4 FORWARD [RFC2942]
125 5 FORWARD_ACCEPT [RFC2942]
126 6 FORWARD-REJECT [RFC2942]
127
128
129In the DSS Telnet Authentication type there are a set of
130Suboption Commands. Additions to the list are registerd by the IANA
131and documented here.
132
133Suboption Command Reference
134 1 DSS_INITIALIZE [RFC2943]
135 2 DSS_TOKENBA [RFC2943]
136 3 DSS_CERTA_TOKENAB [RFC2943]
137 4 DSS_CERTB_TOKENBA2 [RFC2943]
138
139
140In the SRP Telnet Authentication type there are a set of Suboption
141Commands. Additions to the list are registerd by the IANA and
142documented here.
143
144Suboption Command Reference
145 0 AUTH [RFC2944]
146 1 REJECT [RFC2944]
147 2 ACCEPT [RFC2944]
148 3 CHALLENGE [RFC2944]
149 4 RESPONSE [RFC2944]
150 5-7 Unassigned [RFC2944]
151 8 EXP [RFC2944]
152 9 PARAMS [RFC2944]
153
154
155In the KEA_SJ and KEA_SJ_INTEG Telnet Authentication types, there are
156a set of Suboption Commands. Additions to the list are registerd by
157the IANA and documented here.
158
159Suboption Command Reference
160 1 KEA_CERTA_RA [RFC2951]
161 2 KEA_CERTB_RB_IVB_NONCEB [RFC2951]
162 3 KEA_IVA_RESPONSEB_NONCEA [RFC2951]
163 4 KEA_RESPONSEA [RFC2951]
164
165
166Telnet Encryption Types (Option 38)
167
168In the Telnet Encryption commands and types [RFC2946] there have been
169various implementations in several widely distributed versions of
170Telnet (e.g., at MIT, Stanford, and Columbia). Originally, only two
171encryption types were specified. Additional encryption types have
172been defined and are listed below. Additions to the list are
173registerd by the IANA and documented here.
174
175Command
176
177 0 IS [RFC2946]
178 1 SUPPORT [RFC2946]
179 2 REPLY [RFC2946]
180 3 START [RFC2946]
181 4 END [RFC2946]
182 5 REQUEST-START [RFC2946]
183 6 REQUEST-END [RFC2946]
184 7 ENC_KEYID [RFC2946]
185 8 DEC_KEYID [RFC2946]
186
187Type
188
189 0 NULL [RFC2946]
190 1 DES_CFB64 [RFC2946]
191 2 DES_OFB64 [RFC2946]
192 3 DES3_CFB64 [RFC2946]
193 4 DES3_OFB64 [RFC2946]
194 5-7 Unassigned [IANA]
195 8 CAST5_40_CFB64 [RFC2946]
196 9 CAST5_40_OFB64 [RFC2946]
197 10 CAST128_CFB64 [RFC2946]
198 11 CAST128_OFB64 [RFC2946]
199 12 AES_CCM [Josefsson]
200
201In the DES3_CFB64 Telnet Encryption type there are a set of Suboption
202Commands. Additions to the list are registerd by the IANA and
203documented here.
204
205Suboption Command Reference
206 1 CFB64_IV [RFC2947]
207 2 CFB64_IV_OK [RFC2947]
208 3 CFB64_IV_BAD [RFC2947]
209
210
211In the DES3_OFB64 Telnet Encryption type there are a set of Suboption
212Commands. Additions to the list are registerd by the IANA and
213documented here.
214
215Suboption Command Reference
216 1 OFB64_IV [RFC2948]
217 2 OFB64_IV_OK [RFC2948]
218 3 OFB64_IV_BAD [RFC2948]
219
220
221In the CAST5_40_OFB64 and CAST128_OFB64 Telnet Encryption types, there
222are a set of Suboption Commands. Additions to the list are registerd
223by the IANA and documented here.
224
225Suboption Command Reference
226 1 OFB64_IV [RFC2949]
227 2 OFB64_IV_OK [RFC2949]
228 3 OFB64_IV_BAD [RFC2949]
229
230
231In the CAST5_40_CFB64 and CAST128_CFB64 Telnet Encryption types, there
232are a set of Suboption Commands. Additions to the list are registerd
233by the IANA and documented here.
234
235Suboption Command Reference
236 1 CFB64_IV [RFC2950]
237 2 CFB64_IV_OK [RFC2950]
238 3 CFB64_IV_BAD [RFC2950]
239
240
241In the DES_CFB64 Telnet Encryption type there are a set of Suboption
242Commands. Additions to the list are registerd by the IANA and
243documented here.
244
245Suboption Command Reference
246 1 CFB64_IV [RFC2952]
247 2 CFB64_IV_OK [RFC2952]
248 3 CFB64_IV_BAD [RFC2952]
249
250
251In the DES_OFB64 Telnet Encryption type there are a set of Suboption
252Commands. Additions to the list are registerd by the IANA and
253documented here.
254
255Suboption Command Reference
256 1 OFB64_IV [RFC2953]
257 2 OFB64_IV_OK [RFC2953]
258 3 OFB64_IV_BAD [RFC2953]
259
260
261REFERENCES
262
263[ETHERNET] "The Ethernet, A Local Area Network: Data Link Layer and
264 Physical Layer Specification", AA-K759B-TK, Digital
265 Equipment Corporation, Maynard, MA. Also as: "The
266 Ethernet - A Local Area Network", Version 1.0, Digital
267 Equipment Corporation, Intel Corporation, Xerox
268 Corporation, September 1980. And: "The Ethernet, A Local
269 Area Network: Data Link Layer and Physical Layer
270 Specifications", Digital, Intel and Xerox, November 1982.
271 And: XEROX, "The Ethernet, A Local Area Network: Data Link
272 Layer and Physical Layer Specification", X3T51/80-50, Xerox
273 Corporation, Stamford, CT., October 1980.
274
275[NIC50005] DDN Protocol Handbook, "Telnet Reconnection Option",
276 "Telnet Output Line Width Option", "Telnet Output Page Size
277 Option", NIC 50005, December 1985.
278
279[RFC652] Crocker, D., "Telnet Output Carriage-Return Disposition
280 Option", RFC 652, UCLA-NMC, October 1974.
281
282[RFC653] Crocker, D., "Telnet Output Horizontal Tabstops Option",
283 RFC 653, UCLA-NMC, October 1974.
284
285[RFC654] Crocker, D., "Telnet Output Horizontal Tab Disposition
286 Option", RFC 654, UCLA-NMC, October 1974.
287
288[RFC655] Crocker, D., "Telnet Output Formfeed Disposition Option",
289 RFC 655, UCLA-NMC, October 1974.
290
291[RFC656] Crocker, D., "Telnet Output Vertical Tabstops Option",
292 RFC 656, UCLA-NMC, October 1974.
293
294[RFC657] Crocker, D., "Telnet Output Vertical Tab Disposition Option",
295 RFC 657, UCLA-NMC, October 1974.
296
297[RFC658] Crocker, D., "Telnet Output Linefeed Disposition", RFC 658,
298 UCLA-NMC, October 1974.
299
300[RFC698] Tovar, "Telnet Extended ASCII Option", RFC 698, Stanford
301 University-AI, July 1975.
302
303[RFC726] Postel, J. and D. Crocker, "Remote Controlled Transmission
304 and Echoing Telnet Option", RFC 726, SRI-ARC, UC Irvine,
305 March 1977.
306
307[RFC727] Crispin, M., "Telnet Logout Option", RFC 727, Stanford
308 University-AI, April 1977.
309
310[RFC734] Crispin, M., "SUPDUP Protocol", RFC 734, Stanford,
311 October 1977.
312
313[RFC735] Crocker, D. and R. Gumpertz, "Revised Telnet Byte Marco
314 Option", RFC 735, Rand, CMU, November 1977.
315
316[RFC736] Crispin, M., "Telnet SUPDUP Option", Stanford University-AI,
317 RFC 736, Stanford, October 1977.
318
319[RFC749] Greenberg, B., "Telnet SUPDUP-OUTPUT Option", RFC 749,
320 MIT-Multics, September 1978.
321
322[RFC779] Killian, E., "Telnet Send-Location Option", RFC 779,
323 LLL, April 1981.
324
325[RFC856] Postel, J. and J. Reynolds, "Telnet Binary Transmission",
326 STD 27, RFC 856, USC/Information Sciences Institute, May
327 1983.
328
329[RFC857] Postel, J. and J. Reynolds, "Telnet Echo Option", STD 28, RFC
330 857, USC/Information Sciences Institute, May 1983.
331
332[RFC858] Postel, J. and J. Reynolds, "Telnet Suppress Go Ahead
333 Option", STD 29, RFC 858, USC/Information Sciences Institute,
334 May 1983.
335
336[RFC859] Postel, J. and J. Reynolds, "Telnet Status Option", STD 30,
337 RFC 859, USC/Information Sciences Institute, May 1983.
338
339[RFC860] Postel, J. and J. Reynolds, "Telnet Timing Mark Option",
340 STD 31, RFC 860, USC/Information Sciences Institute, May
341 1983.
342
343[RFC861] Postel, J. and J. Reynolds, "Telnet Extended Options - List
344 Option", STD 32, RFC 861, USC/Information Sciences Institute,
345 May 1983.
346
347[RFC885] Postel, J., "Telnet End of Record Option", RFC 885,
348 USC/Information Sciences Institute, December 1983.
349
350[RFC927] Anderson, B., "TACACS User Identification Telnet Option",
351 RFC 927, BBN, December 1984.
352
353[RFC933] Silverman, S., "Output Marking Telnet Option", RFC 933,
354 MITRE, January 1985.
355
356[RFC946] Nedved, R., "Telnet Terminal Location Number Option",
357 RFC 946, Carnegie-Mellon University, May 1985.
358
359[RDC1041] Rekhter, J., "Telnet 3270 Regime Option", RFC 1041,
360 IBM, January 1988.
361
362[RFC1043] Yasuda, A., and T. Thompson, "TELNET Data Entry Terminal
363 Option DODIIS Implementation", RFC 1043, DIA, February 1988.
364
365[RFC1053] Levy, S., and T. Jacobson, "Telnet X.3 PAD Option",
366 RFC 1053, Minnesota Supercomputer Center, April 1988.
367
368[RFC1073] Waitzman, D., "Telnet Window Size Option", RFC 1073,
369 BBN STC, October, 1988.
370
371[RFC1079] Hedrick, C., "Telnet Terminal Speed Option", RFC 1079,
372 Rutgers University, December 1988.
373
374[RFC1091] VanBokkelen, J., "Telnet Terminal Type Option",
375 RFC 1091, FTP Software, Inc., February 1989.
376
377[RFC1096] Marcy, G., "Telnet X Display Location Option", RFC 1096,
378 Carnegie Mellon University, March 1989.
379
380[RFC1184] Borman, D., Editor, "Telnet Linemode Option",
381 RFC 1184, Cray Research, Inc., October 1990.
382
383[RFC1372] Hedrick, C., and D. Borman, "Telnet Remote Flow Control
384 Option", RFC 1372, Rutgers University, Cray Research, Inc.,
385 October 1992.
386
387[RFC1408] Borman, D., Editor, "Telnet Environment Option", RFC 1408,
388 Cray Research, Inc., January 1993.
389
390[RFC1411] Borman, D., Editor, "Telnet Authentication: Kerberos
391 Version 4", RFC 1411, Cray Research, Inc., January 1993.
392
393[RFC1416] Borman, D., Editor, "Telnet Authentication Option", RFC
394 1416, Cray Research, Inc., February 1993.
395
396[RFC1572] Alexander, S., Editor, "Telnet Environment Option", RFC1572,
397 Lachman Technology, Inc., January 1994.
398
399[RFC1647] Kelly, B., "TN3270 Enhancements", RFC1647, Auburn
400 University, July 1994.
401
402[RFC2066] Gellens, R., "Telnet CharSet Option", RFC 2066, Unisys,
403 January 1997.
404
405[RFC2217] Clark, G., "Telnet Com Port Control Option", RFC 2217,
406 Cisco Systems, Inc., October 1997.
407
408[RFC2840] Altman, J., "Telnet Kermit Option", RFC 2840, May 2000.
409
410[RFC2941] Ts'o, T. and J. Altman, "Telnet Authentication Option",
411 RFC 2941, September 2000.
412
413[RFC2942] Ts'o, T., "Telnet Authentication: Kerberos Version 5",
414 RFC 2942, September 2000.
415
416[RFC2943] Housley, R., Horting, T. and P. Yee, "TELNET Authentication
417 Using DSA", RFC 2943, September 2000.
418
419[RFC2944] Wu, T., "Telnet Authentication: SRP", RFC 2944, September
420 2000.
421
422[RFC2946] Ts'o, T., "Telnet Data Encryption Option", RFC 2946,
423 September 2000.
424
425[RFC2947] Altman, J., "Telnet Encryption: DES3 64 bit Cipher
426 Feedback", RFC 2947, September 2000.
427
428[RFC2948] Altman, J., "Telnet Encryption: DES3 64 bit Output
429 Feedback", RFC 2948, September 2000.
430
431[RFC2949] Altman, J., "Telnet Encryption: CAST-128 64 bit Output
432 Feedback", RFC 2949, September 2000.
433
434[RFC2950] Altman, J., "Telnet Encryption: CAST-128 64 bit Cipher
435 Feedback", September 2000.
436
437[RFC2951] Housley, R., Horting, T. and P. Yee, "TELNET Authentication
438 Using KEA and SKIPJACK", September 2000.
439
440[RFC2952] Ts'o, T., "Telnet Encryption: DES 64 bit Cipher Feedback",
441 RFC 2952, September 2000.
442
443[RFC2953] Ts'o, T., "Telnet Encryption: DES 64 bit Output Feedback",
444 RFC 2953, September 2000.
445
446PEOPLE
447------
448
449[Altman] Jeffrey Altman, <jaltman@watsun.cc.columbia.edu>, August
450 1998, January 2000.
451
452[Atmar] Wirt Atmar, <atmar@aics-research.com>, June 1998.
453
454[Barnes] Robert Barnes, <rab@stallion.oz.au>, July 1997.
455
456[Boe] Michael Boe, <mboe@cisco.com>, June 1998.
457
458[Brashear] Derrick Brashear, <shadow@dementia.org>, January 1995.
459
460[Borman] Dave Borman, <dab@CRAY.COM>, January 1995.
461
462[Croft] David Croft, <david@infotrek.co.uk>, September 1998.
463
464[Earhart] Rob Earhart, <earhart+@CMU.EDU>, April 1995.
465
466[Horting] Todd Horting <thorting@spyrus.com>, April 1998.
467
468[Hudson] Tim Hudson <tjh@cryptsoft.com>, December 1998.
469
470[IANA] Internet Assigned Numbers Authority, <iana@isi.edu>, January 1995.
471
472[Josefsson] S. Josefsson <jas@extundo.com>, November 2003.
473 http://josefsson.org/shishi/shishi.html#Telnet%20encryption%20with%20AES-CCM
474
475[Kahn] Louis Kahn, <louisk@microsoft.com>, October 1998.
476
477[McGregory] Steve McGregory <stevemc@pragmasys.com>, December 1998.
478
479[Schoch] Steven Schoch, <schoch@sheba.arc.nasa.gov>, January 1995.
480
481[Ts'o] Theodore Ts'o, <tytso@mit.edu>, September 1998.
482
483[Wu] Thomas Wu, <tjw@stanford.edu>, July 1997, September 1998.
484
485[]
486
diff --git a/misc/rfc854-telnet.txt b/misc/rfc854-telnet.txt
new file mode 100644
index 0000000..e794bf7
--- /dev/null
+++ b/misc/rfc854-telnet.txt
@@ -0,0 +1,854 @@
1
2Network Working Group J. Postel
3Request for Comments: 854 J. Reynolds
4 ISI
5Obsoletes: NIC 18639 May 1983
6
7 TELNET PROTOCOL SPECIFICATION
8
9
10This RFC specifies a standard for the ARPA Internet community. Hosts on
11the ARPA Internet are expected to adopt and implement this standard.
12
13INTRODUCTION
14
15 The purpose of the TELNET Protocol is to provide a fairly general,
16 bi-directional, eight-bit byte oriented communications facility. Its
17 primary goal is to allow a standard method of interfacing terminal
18 devices and terminal-oriented processes to each other. It is
19 envisioned that the protocol may also be used for terminal-terminal
20 communication ("linking") and process-process communication
21 (distributed computation).
22
23GENERAL CONSIDERATIONS
24
25 A TELNET connection is a Transmission Control Protocol (TCP)
26 connection used to transmit data with interspersed TELNET control
27 information.
28
29 The TELNET Protocol is built upon three main ideas: first, the
30 concept of a "Network Virtual Terminal"; second, the principle of
31 negotiated options; and third, a symmetric view of terminals and
32 processes.
33
34 1. When a TELNET connection is first established, each end is
35 assumed to originate and terminate at a "Network Virtual Terminal",
36 or NVT. An NVT is an imaginary device which provides a standard,
37 network-wide, intermediate representation of a canonical terminal.
38 This eliminates the need for "server" and "user" hosts to keep
39 information about the characteristics of each other's terminals and
40 terminal handling conventions. All hosts, both user and server, map
41 their local device characteristics and conventions so as to appear to
42 be dealing with an NVT over the network, and each can assume a
43 similar mapping by the other party. The NVT is intended to strike a
44 balance between being overly restricted (not providing hosts a rich
45 enough vocabulary for mapping into their local character sets), and
46 being overly inclusive (penalizing users with modest terminals).
47
48 NOTE: The "user" host is the host to which the physical terminal
49 is normally attached, and the "server" host is the host which is
50 normally providing some service. As an alternate point of view,
51
52
53
54
55Postel & Reynolds [Page 1]
56
57
58
59RFC 854 May 1983
60
61
62 applicable even in terminal-to-terminal or process-to-process
63 communications, the "user" host is the host which initiated the
64 communication.
65
66 2. The principle of negotiated options takes cognizance of the fact
67 that many hosts will wish to provide additional services over and
68 above those available within an NVT, and many users will have
69 sophisticated terminals and would like to have elegant, rather than
70 minimal, services. Independent of, but structured within the TELNET
71 Protocol are various "options" that will be sanctioned and may be
72 used with the "DO, DON'T, WILL, WON'T" structure (discussed below) to
73 allow a user and server to agree to use a more elaborate (or perhaps
74 just different) set of conventions for their TELNET connection. Such
75 options could include changing the character set, the echo mode, etc.
76
77 The basic strategy for setting up the use of options is to have
78 either party (or both) initiate a request that some option take
79 effect. The other party may then either accept or reject the
80 request. If the request is accepted the option immediately takes
81 effect; if it is rejected the associated aspect of the connection
82 remains as specified for an NVT. Clearly, a party may always refuse
83 a request to enable, and must never refuse a request to disable some
84 option since all parties must be prepared to support the NVT.
85
86 The syntax of option negotiation has been set up so that if both
87 parties request an option simultaneously, each will see the other's
88 request as the positive acknowledgment of its own.
89
90 3. The symmetry of the negotiation syntax can potentially lead to
91 nonterminating acknowledgment loops -- each party seeing the incoming
92 commands not as acknowledgments but as new requests which must be
93 acknowledged. To prevent such loops, the following rules prevail:
94
95 a. Parties may only request a change in option status; i.e., a
96 party may not send out a "request" merely to announce what mode it
97 is in.
98
99 b. If a party receives what appears to be a request to enter some
100 mode it is already in, the request should not be acknowledged.
101 This non-response is essential to prevent endless loops in the
102 negotiation. It is required that a response be sent to requests
103 for a change of mode -- even if the mode is not changed.
104
105 c. Whenever one party sends an option command to a second party,
106 whether as a request or an acknowledgment, and use of the option
107 will have any effect on the processing of the data being sent from
108 the first party to the second, then the command must be inserted
109 in the data stream at the point where it is desired that it take
110
111
112Postel & Reynolds [Page 2]
113
114
115
116RFC 854 May 1983
117
118
119 effect. (It should be noted that some time will elapse between
120 the transmission of a request and the receipt of an
121 acknowledgment, which may be negative. Thus, a host may wish to
122 buffer data, after requesting an option, until it learns whether
123 the request is accepted or rejected, in order to hide the
124 "uncertainty period" from the user.)
125
126 Option requests are likely to flurry back and forth when a TELNET
127 connection is first established, as each party attempts to get the
128 best possible service from the other party. Beyond that, however,
129 options can be used to dynamically modify the characteristics of the
130 connection to suit changing local conditions. For example, the NVT,
131 as will be explained later, uses a transmission discipline well
132 suited to the many "line at a time" applications such as BASIC, but
133 poorly suited to the many "character at a time" applications such as
134 NLS. A server might elect to devote the extra processor overhead
135 required for a "character at a time" discipline when it was suitable
136 for the local process and would negotiate an appropriate option.
137 However, rather than then being permanently burdened with the extra
138 processing overhead, it could switch (i.e., negotiate) back to NVT
139 when the detailed control was no longer necessary.
140
141 It is possible for requests initiated by processes to stimulate a
142 nonterminating request loop if the process responds to a rejection by
143 merely re-requesting the option. To prevent such loops from
144 occurring, rejected requests should not be repeated until something
145 changes. Operationally, this can mean the process is running a
146 different program, or the user has given another command, or whatever
147 makes sense in the context of the given process and the given option.
148 A good rule of thumb is that a re-request should only occur as a
149 result of subsequent information from the other end of the connection
150 or when demanded by local human intervention.
151
152 Option designers should not feel constrained by the somewhat limited
153 syntax available for option negotiation. The intent of the simple
154 syntax is to make it easy to have options -- since it is
155 correspondingly easy to profess ignorance about them. If some
156 particular option requires a richer negotiation structure than
157 possible within "DO, DON'T, WILL, WON'T", the proper tack is to use
158 "DO, DON'T, WILL, WON'T" to establish that both parties understand
159 the option, and once this is accomplished a more exotic syntax can be
160 used freely. For example, a party might send a request to alter
161 (establish) line length. If it is accepted, then a different syntax
162 can be used for actually negotiating the line length -- such a
163 "sub-negotiation" might include fields for minimum allowable, maximum
164 allowable and desired line lengths. The important concept is that
165
166
167
168
169Postel & Reynolds [Page 3]
170
171
172
173RFC 854 May 1983
174
175
176 such expanded negotiations should never begin until some prior
177 (standard) negotiation has established that both parties are capable
178 of parsing the expanded syntax.
179
180 In summary, WILL XXX is sent, by either party, to indicate that
181 party's desire (offer) to begin performing option XXX, DO XXX and
182 DON'T XXX being its positive and negative acknowledgments; similarly,
183 DO XXX is sent to indicate a desire (request) that the other party
184 (i.e., the recipient of the DO) begin performing option XXX, WILL XXX
185 and WON'T XXX being the positive and negative acknowledgments. Since
186 the NVT is what is left when no options are enabled, the DON'T and
187 WON'T responses are guaranteed to leave the connection in a state
188 which both ends can handle. Thus, all hosts may implement their
189 TELNET processes to be totally unaware of options that are not
190 supported, simply returning a rejection to (i.e., refusing) any
191 option request that cannot be understood.
192
193 As much as possible, the TELNET protocol has been made server-user
194 symmetrical so that it easily and naturally covers the user-user
195 (linking) and server-server (cooperating processes) cases. It is
196 hoped, but not absolutely required, that options will further this
197 intent. In any case, it is explicitly acknowledged that symmetry is
198 an operating principle rather than an ironclad rule.
199
200 A companion document, "TELNET Option Specifications," should be
201 consulted for information about the procedure for establishing new
202 options.
203
204THE NETWORK VIRTUAL TERMINAL
205
206 The Network Virtual Terminal (NVT) is a bi-directional character
207 device. The NVT has a printer and a keyboard. The printer responds
208 to incoming data and the keyboard produces outgoing data which is
209 sent over the TELNET connection and, if "echoes" are desired, to the
210 NVT's printer as well. "Echoes" will not be expected to traverse the
211 network (although options exist to enable a "remote" echoing mode of
212 operation, no host is required to implement this option). The code
213 set is seven-bit USASCII in an eight-bit field, except as modified
214 herein. Any code conversion and timing considerations are local
215 problems and do not affect the NVT.
216
217 TRANSMISSION OF DATA
218
219 Although a TELNET connection through the network is intrinsically
220 full duplex, the NVT is to be viewed as a half-duplex device
221 operating in a line-buffered mode. That is, unless and until
222
223
224
225
226Postel & Reynolds [Page 4]
227
228
229
230RFC 854 May 1983
231
232
233 options are negotiated to the contrary, the following default
234 conditions pertain to the transmission of data over the TELNET
235 connection:
236
237 1) Insofar as the availability of local buffer space permits,
238 data should be accumulated in the host where it is generated
239 until a complete line of data is ready for transmission, or
240 until some locally-defined explicit signal to transmit occurs.
241 This signal could be generated either by a process or by a
242 human user.
243
244 The motivation for this rule is the high cost, to some hosts,
245 of processing network input interrupts, coupled with the
246 default NVT specification that "echoes" do not traverse the
247 network. Thus, it is reasonable to buffer some amount of data
248 at its source. Many systems take some processing action at the
249 end of each input line (even line printers or card punches
250 frequently tend to work this way), so the transmission should
251 be triggered at the end of a line. On the other hand, a user
252 or process may sometimes find it necessary or desirable to
253 provide data which does not terminate at the end of a line;
254 therefore implementers are cautioned to provide methods of
255 locally signaling that all buffered data should be transmitted
256 immediately.
257
258 2) When a process has completed sending data to an NVT printer
259 and has no queued input from the NVT keyboard for further
260 processing (i.e., when a process at one end of a TELNET
261 connection cannot proceed without input from the other end),
262 the process must transmit the TELNET Go Ahead (GA) command.
263
264 This rule is not intended to require that the TELNET GA command
265 be sent from a terminal at the end of each line, since server
266 hosts do not normally require a special signal (in addition to
267 end-of-line or other locally-defined characters) in order to
268 commence processing. Rather, the TELNET GA is designed to help
269 a user's local host operate a physically half duplex terminal
270 which has a "lockable" keyboard such as the IBM 2741. A
271 description of this type of terminal may help to explain the
272 proper use of the GA command.
273
274 The terminal-computer connection is always under control of
275 either the user or the computer. Neither can unilaterally
276 seize control from the other; rather the controlling end must
277 relinguish its control explicitly. At the terminal end, the
278 hardware is constructed so as to relinquish control each time
279 that a "line" is terminated (i.e., when the "New Line" key is
280 typed by the user). When this occurs, the attached (local)
281
282
283Postel & Reynolds [Page 5]
284
285
286
287RFC 854 May 1983
288
289
290 computer processes the input data, decides if output should be
291 generated, and if not returns control to the terminal. If
292 output should be generated, control is retained by the computer
293 until all output has been transmitted.
294
295 The difficulties of using this type of terminal through the
296 network should be obvious. The "local" computer is no longer
297 able to decide whether to retain control after seeing an
298 end-of-line signal or not; this decision can only be made by
299 the "remote" computer which is processing the data. Therefore,
300 the TELNET GA command provides a mechanism whereby the "remote"
301 (server) computer can signal the "local" (user) computer that
302 it is time to pass control to the user of the terminal. It
303 should be transmitted at those times, and only at those times,
304 when the user should be given control of the terminal. Note
305 that premature transmission of the GA command may result in the
306 blocking of output, since the user is likely to assume that the
307 transmitting system has paused, and therefore he will fail to
308 turn the line around manually.
309
310 The foregoing, of course, does not apply to the user-to-server
311 direction of communication. In this direction, GAs may be sent at
312 any time, but need not ever be sent. Also, if the TELNET
313 connection is being used for process-to-process communication, GAs
314 need not be sent in either direction. Finally, for
315 terminal-to-terminal communication, GAs may be required in
316 neither, one, or both directions. If a host plans to support
317 terminal-to-terminal communication it is suggested that the host
318 provide the user with a means of manually signaling that it is
319 time for a GA to be sent over the TELNET connection; this,
320 however, is not a requirement on the implementer of a TELNET
321 process.
322
323 Note that the symmetry of the TELNET model requires that there is
324 an NVT at each end of the TELNET connection, at least
325 conceptually.
326
327 STANDARD REPRESENTATION OF CONTROL FUNCTIONS
328
329 As stated in the Introduction to this document, the primary goal
330 of the TELNET protocol is the provision of a standard interfacing
331 of terminal devices and terminal-oriented processes through the
332 network. Early experiences with this type of interconnection have
333 shown that certain functions are implemented by most servers, but
334 that the methods of invoking these functions differ widely. For a
335 human user who interacts with several server systems, these
336 differences are highly frustrating. TELNET, therefore, defines a
337 standard representation for five of these functions, as described
338
339
340Postel & Reynolds [Page 6]
341
342
343
344RFC 854 May 1983
345
346
347 below. These standard representations have standard, but not
348 required, meanings (with the exception that the Interrupt Process
349 (IP) function may be required by other protocols which use
350 TELNET); that is, a system which does not provide the function to
351 local users need not provide it to network users and may treat the
352 standard representation for the function as a No-operation. On
353 the other hand, a system which does provide the function to a
354 local user is obliged to provide the same function to a network
355 user who transmits the standard representation for the function.
356
357 Interrupt Process (IP)
358
359 Many systems provide a function which suspends, interrupts,
360 aborts, or terminates the operation of a user process. This
361 function is frequently used when a user believes his process is
362 in an unending loop, or when an unwanted process has been
363 inadvertently activated. IP is the standard representation for
364 invoking this function. It should be noted by implementers
365 that IP may be required by other protocols which use TELNET,
366 and therefore should be implemented if these other protocols
367 are to be supported.
368
369 Abort Output (AO)
370
371 Many systems provide a function which allows a process, which
372 is generating output, to run to completion (or to reach the
373 same stopping point it would reach if running to completion)
374 but without sending the output to the user's terminal.
375 Further, this function typically clears any output already
376 produced but not yet actually printed (or displayed) on the
377 user's terminal. AO is the standard representation for
378 invoking this function. For example, some subsystem might
379 normally accept a user's command, send a long text string to
380 the user's terminal in response, and finally signal readiness
381 to accept the next command by sending a "prompt" character
382 (preceded by <CR><LF>) to the user's terminal. If the AO were
383 received during the transmission of the text string, a
384 reasonable implementation would be to suppress the remainder of
385 the text string, but transmit the prompt character and the
386 preceding <CR><LF>. (This is possibly in distinction to the
387 action which might be taken if an IP were received; the IP
388 might cause suppression of the text string and an exit from the
389 subsystem.)
390
391 It should be noted, by server systems which provide this
392 function, that there may be buffers external to the system (in
393
394
395
396
397Postel & Reynolds [Page 7]
398
399
400
401RFC 854 May 1983
402
403
404 the network and the user's local host) which should be cleared;
405 the appropriate way to do this is to transmit the "Synch"
406 signal (described below) to the user system.
407
408 Are You There (AYT)
409
410 Many systems provide a function which provides the user with
411 some visible (e.g., printable) evidence that the system is
412 still up and running. This function may be invoked by the user
413 when the system is unexpectedly "silent" for a long time,
414 because of the unanticipated (by the user) length of a
415 computation, an unusually heavy system load, etc. AYT is the
416 standard representation for invoking this function.
417
418 Erase Character (EC)
419
420 Many systems provide a function which deletes the last
421 preceding undeleted character or "print position"* from the
422 stream of data being supplied by the user. This function is
423 typically used to edit keyboard input when typing mistakes are
424 made. EC is the standard representation for invoking this
425 function.
426
427 *NOTE: A "print position" may contain several characters
428 which are the result of overstrikes, or of sequences such as
429 <char1> BS <char2>...
430
431 Erase Line (EL)
432
433 Many systems provide a function which deletes all the data in
434 the current "line" of input. This function is typically used
435 to edit keyboard input. EL is the standard representation for
436 invoking this function.
437
438 THE TELNET "SYNCH" SIGNAL
439
440 Most time-sharing systems provide mechanisms which allow a
441 terminal user to regain control of a "runaway" process; the IP and
442 AO functions described above are examples of these mechanisms.
443 Such systems, when used locally, have access to all of the signals
444 supplied by the user, whether these are normal characters or
445 special "out of band" signals such as those supplied by the
446 teletype "BREAK" key or the IBM 2741 "ATTN" key. This is not
447 necessarily true when terminals are connected to the system
448 through the network; the network's flow control mechanisms may
449 cause such a signal to be buffered elsewhere, for example in the
450 user's host.
451
452
453
454Postel & Reynolds [Page 8]
455
456
457
458RFC 854 May 1983
459
460
461 To counter this problem, the TELNET "Synch" mechanism is
462 introduced. A Synch signal consists of a TCP Urgent notification,
463 coupled with the TELNET command DATA MARK. The Urgent
464 notification, which is not subject to the flow control pertaining
465 to the TELNET connection, is used to invoke special handling of
466 the data stream by the process which receives it. In this mode,
467 the data stream is immediately scanned for "interesting" signals
468 as defined below, discarding intervening data. The TELNET command
469 DATA MARK (DM) is the synchronizing mark in the data stream which
470 indicates that any special signal has already occurred and the
471 recipient can return to normal processing of the data stream.
472
473 The Synch is sent via the TCP send operation with the Urgent
474 flag set and the DM as the last (or only) data octet.
475
476 When several Synchs are sent in rapid succession, the Urgent
477 notifications may be merged. It is not possible to count Urgents
478 since the number received will be less than or equal the number
479 sent. When in normal mode, a DM is a no operation; when in urgent
480 mode, it signals the end of the urgent processing.
481
482 If TCP indicates the end of Urgent data before the DM is found,
483 TELNET should continue the special handling of the data stream
484 until the DM is found.
485
486 If TCP indicates more Urgent data after the DM is found, it can
487 only be because of a subsequent Synch. TELNET should continue
488 the special handling of the data stream until another DM is
489 found.
490
491 "Interesting" signals are defined to be: the TELNET standard
492 representations of IP, AO, and AYT (but not EC or EL); the local
493 analogs of these standard representations (if any); all other
494 TELNET commands; other site-defined signals which can be acted on
495 without delaying the scan of the data stream.
496
497 Since one effect of the SYNCH mechanism is the discarding of
498 essentially all characters (except TELNET commands) between the
499 sender of the Synch and its recipient, this mechanism is specified
500 as the standard way to clear the data path when that is desired.
501 For example, if a user at a terminal causes an AO to be
502 transmitted, the server which receives the AO (if it provides that
503 function at all) should return a Synch to the user.
504
505 Finally, just as the TCP Urgent notification is needed at the
506 TELNET level as an out-of-band signal, so other protocols which
507 make use of TELNET may require a TELNET command which can be
508 viewed as an out-of-band signal at a different level.
509
510
511Postel & Reynolds [Page 9]
512
513
514
515RFC 854 May 1983
516
517
518 By convention the sequence [IP, Synch] is to be used as such a
519 signal. For example, suppose that some other protocol, which uses
520 TELNET, defines the character string STOP analogously to the
521 TELNET command AO. Imagine that a user of this protocol wishes a
522 server to process the STOP string, but the connection is blocked
523 because the server is processing other commands. The user should
524 instruct his system to:
525
526 1. Send the TELNET IP character;
527
528 2. Send the TELNET SYNC sequence, that is:
529
530 Send the Data Mark (DM) as the only character
531 in a TCP urgent mode send operation.
532
533 3. Send the character string STOP; and
534
535 4. Send the other protocol's analog of the TELNET DM, if any.
536
537 The user (or process acting on his behalf) must transmit the
538 TELNET SYNCH sequence of step 2 above to ensure that the TELNET IP
539 gets through to the server's TELNET interpreter.
540
541 The Urgent should wake up the TELNET process; the IP should
542 wake up the next higher level process.
543
544 THE NVT PRINTER AND KEYBOARD
545
546 The NVT printer has an unspecified carriage width and page length
547 and can produce representations of all 95 USASCII graphics (codes
548 32 through 126). Of the 33 USASCII control codes (0 through 31
549 and 127), and the 128 uncovered codes (128 through 255), the
550 following have specified meaning to the NVT printer:
551
552 NAME CODE MEANING
553
554 NULL (NUL) 0 No Operation
555 Line Feed (LF) 10 Moves the printer to the
556 next print line, keeping the
557 same horizontal position.
558 Carriage Return (CR) 13 Moves the printer to the left
559 margin of the current line.
560
561
562
563
564
565
566
567
568Postel & Reynolds [Page 10]
569
570
571
572RFC 854 May 1983
573
574
575 In addition, the following codes shall have defined, but not
576 required, effects on the NVT printer. Neither end of a TELNET
577 connection may assume that the other party will take, or will
578 have taken, any particular action upon receipt or transmission
579 of these:
580
581 BELL (BEL) 7 Produces an audible or
582 visible signal (which does
583 NOT move the print head).
584 Back Space (BS) 8 Moves the print head one
585 character position towards
586 the left margin.
587 Horizontal Tab (HT) 9 Moves the printer to the
588 next horizontal tab stop.
589 It remains unspecified how
590 either party determines or
591 establishes where such tab
592 stops are located.
593 Vertical Tab (VT) 11 Moves the printer to the
594 next vertical tab stop. It
595 remains unspecified how
596 either party determines or
597 establishes where such tab
598 stops are located.
599 Form Feed (FF) 12 Moves the printer to the top
600 of the next page, keeping
601 the same horizontal position.
602
603 All remaining codes do not cause the NVT printer to take any
604 action.
605
606 The sequence "CR LF", as defined, will cause the NVT to be
607 positioned at the left margin of the next print line (as would,
608 for example, the sequence "LF CR"). However, many systems and
609 terminals do not treat CR and LF independently, and will have to
610 go to some effort to simulate their effect. (For example, some
611 terminals do not have a CR independent of the LF, but on such
612 terminals it may be possible to simulate a CR by backspacing.)
613 Therefore, the sequence "CR LF" must be treated as a single "new
614 line" character and used whenever their combined action is
615 intended; the sequence "CR NUL" must be used where a carriage
616 return alone is actually desired; and the CR character must be
617 avoided in other contexts. This rule gives assurance to systems
618 which must decide whether to perform a "new line" function or a
619 multiple-backspace that the TELNET stream contains a character
620 following a CR that will allow a rational decision.
621
622 Note that "CR LF" or "CR NUL" is required in both directions
623
624
625Postel & Reynolds [Page 11]
626
627
628
629RFC 854 May 1983
630
631
632 (in the default ASCII mode), to preserve the symmetry of the
633 NVT model. Even though it may be known in some situations
634 (e.g., with remote echo and suppress go ahead options in
635 effect) that characters are not being sent to an actual
636 printer, nonetheless, for the sake of consistency, the protocol
637 requires that a NUL be inserted following a CR not followed by
638 a LF in the data stream. The converse of this is that a NUL
639 received in the data stream after a CR (in the absence of
640 options negotiations which explicitly specify otherwise) should
641 be stripped out prior to applying the NVT to local character
642 set mapping.
643
644 The NVT keyboard has keys, or key combinations, or key sequences,
645 for generating all 128 USASCII codes. Note that although many
646 have no effect on the NVT printer, the NVT keyboard is capable of
647 generating them.
648
649 In addition to these codes, the NVT keyboard shall be capable of
650 generating the following additional codes which, except as noted,
651 have defined, but not reguired, meanings. The actual code
652 assignments for these "characters" are in the TELNET Command
653 section, because they are viewed as being, in some sense, generic
654 and should be available even when the data stream is interpreted
655 as being some other character set.
656
657 Synch
658
659 This key allows the user to clear his data path to the other
660 party. The activation of this key causes a DM (see command
661 section) to be sent in the data stream and a TCP Urgent
662 notification is associated with it. The pair DM-Urgent is to
663 have required meaning as defined previously.
664
665 Break (BRK)
666
667 This code is provided because it is a signal outside the
668 USASCII set which is currently given local meaning within many
669 systems. It is intended to indicate that the Break Key or the
670 Attention Key was hit. Note, however, that this is intended to
671 provide a 129th code for systems which require it, not as a
672 synonym for the IP standard representation.
673
674 Interrupt Process (IP)
675
676 Suspend, interrupt, abort or terminate the process to which the
677 NVT is connected. Also, part of the out-of-band signal for
678 other protocols which use TELNET.
679
680
681
682Postel & Reynolds [Page 12]
683
684
685
686RFC 854 May 1983
687
688
689 Abort Output (AO)
690
691 Allow the current process to (appear to) run to completion, but
692 do not send its output to the user. Also, send a Synch to the
693 user.
694
695 Are You There (AYT)
696
697 Send back to the NVT some visible (i.e., printable) evidence
698 that the AYT was received.
699
700 Erase Character (EC)
701
702 The recipient should delete the last preceding undeleted
703 character or "print position" from the data stream.
704
705 Erase Line (EL)
706
707 The recipient should delete characters from the data stream
708 back to, but not including, the last "CR LF" sequence sent over
709 the TELNET connection.
710
711 The spirit of these "extra" keys, and also the printer format
712 effectors, is that they should represent a natural extension of
713 the mapping that already must be done from "NVT" into "local".
714 Just as the NVT data byte 68 (104 octal) should be mapped into
715 whatever the local code for "uppercase D" is, so the EC character
716 should be mapped into whatever the local "Erase Character"
717 function is. Further, just as the mapping for 124 (174 octal) is
718 somewhat arbitrary in an environment that has no "vertical bar"
719 character, the EL character may have a somewhat arbitrary mapping
720 (or none at all) if there is no local "Erase Line" facility.
721 Similarly for format effectors: if the terminal actually does
722 have a "Vertical Tab", then the mapping for VT is obvious, and
723 only when the terminal does not have a vertical tab should the
724 effect of VT be unpredictable.
725
726TELNET COMMAND STRUCTURE
727
728 All TELNET commands consist of at least a two byte sequence: the
729 "Interpret as Command" (IAC) escape character followed by the code
730 for the command. The commands dealing with option negotiation are
731 three byte sequences, the third byte being the code for the option
732 referenced. This format was chosen so that as more comprehensive use
733 of the "data space" is made -- by negotiations from the basic NVT, of
734 course -- collisions of data bytes with reserved command values will
735 be minimized, all such collisions requiring the inconvenience, and
736
737
738
739Postel & Reynolds [Page 13]
740
741
742
743RFC 854 May 1983
744
745
746 inefficiency, of "escaping" the data bytes into the stream. With the
747 current set-up, only the IAC need be doubled to be sent as data, and
748 the other 255 codes may be passed transparently.
749
750 The following are the defined TELNET commands. Note that these codes
751 and code sequences have the indicated meaning only when immediately
752 preceded by an IAC.
753
754 NAME CODE MEANING
755
756 SE 240 End of subnegotiation parameters.
757 NOP 241 No operation.
758 Data Mark 242 The data stream portion of a Synch.
759 This should always be accompanied
760 by a TCP Urgent notification.
761 Break 243 NVT character BRK.
762 Interrupt Process 244 The function IP.
763 Abort output 245 The function AO.
764 Are You There 246 The function AYT.
765 Erase character 247 The function EC.
766 Erase Line 248 The function EL.
767 Go ahead 249 The GA signal.
768 SB 250 Indicates that what follows is
769 subnegotiation of the indicated
770 option.
771 WILL (option code) 251 Indicates the desire to begin
772 performing, or confirmation that
773 you are now performing, the
774 indicated option.
775 WON'T (option code) 252 Indicates the refusal to perform,
776 or continue performing, the
777 indicated option.
778 DO (option code) 253 Indicates the request that the
779 other party perform, or
780 confirmation that you are expecting
781 the other party to perform, the
782 indicated option.
783 DON'T (option code) 254 Indicates the demand that the
784 other party stop performing,
785 or confirmation that you are no
786 longer expecting the other party
787 to perform, the indicated option.
788 IAC 255 Data Byte 255.
789
790
791
792
793
794
795
796Postel & Reynolds [Page 14]
797
798
799
800RFC 854 May 1983
801
802
803CONNECTION ESTABLISHMENT
804
805 The TELNET TCP connection is established between the user's port U
806 and the server's port L. The server listens on its well known port L
807 for such connections. Since a TCP connection is full duplex and
808 identified by the pair of ports, the server can engage in many
809 simultaneous connections involving its port L and different user
810 ports U.
811
812 Port Assignment
813
814 When used for remote user access to service hosts (i.e., remote
815 terminal access) this protocol is assigned server port 23
816 (27 octal). That is L=23.
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853Postel & Reynolds [Page 15]
854
diff --git a/src/hash.cpp b/src/hash.cpp
index a207c29..9b8a1c1 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -2,26 +2,6 @@
2 2
3namespace Bu { subExceptionDef( HashException ) } 3namespace Bu { subExceptionDef( HashException ) }
4 4
5template<> uint32_t Bu::__calcHashCode<int>( const int &k )
6{
7 return k;
8}
9
10template<> bool Bu::__cmpHashKeys<int>( const int &a, const int &b )
11{
12 return a == b;
13}
14
15template<> uint32_t Bu::__calcHashCode<unsigned int>( const unsigned int &k )
16{
17 return k;
18}
19
20template<> bool Bu::__cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b )
21{
22 return a == b;
23}
24
25template<> 5template<>
26uint32_t Bu::__calcHashCode<const char *>( const char * const &k ) 6uint32_t Bu::__calcHashCode<const char *>( const char * const &k )
27{ 7{
diff --git a/src/hash.h b/src/hash.h
index 62b19c9..be57786 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -1008,12 +1008,16 @@ namespace Bu
1008 challoc ca; 1008 challoc ca;
1009 sizecalc szCalc; 1009 sizecalc szCalc;
1010 }; 1010 };
1011
1012 template<typename T> uint32_t __calcHashCode( const T &k )
1013 {
1014 return static_cast<uint32_t>( k );
1015 }
1011 1016
1012 template<> uint32_t __calcHashCode<int>( const int &k ); 1017 template<typename T> bool __cmpHashKeys( const T &a, const T &b )
1013 template<> bool __cmpHashKeys<int>( const int &a, const int &b ); 1018 {
1014 1019 return (a == b);
1015 template<> uint32_t __calcHashCode<unsigned int>( const unsigned int &k ); 1020 }
1016 template<> bool __cmpHashKeys<unsigned int>( const unsigned int &a, const unsigned int &b );
1017 1021
1018 template<> uint32_t __calcHashCode<const char *>( const char * const &k ); 1022 template<> uint32_t __calcHashCode<const char *>( const char * const &k );
1019 template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b ); 1023 template<> bool __cmpHashKeys<const char *>( const char * const &a, const char * const &b );
diff --git a/src/protocolhttp.h b/src/protocolhttp.h
index e2612f5..85510e3 100644
--- a/src/protocolhttp.h
+++ b/src/protocolhttp.h
@@ -11,7 +11,14 @@
11namespace Bu 11namespace Bu
12{ 12{
13 /** 13 /**
14 * 14 * An HTTP Protocol handler. Yes, I know that HTTP stands for Hyper Text
15 * Transfer Protocol, and that the Protocol part is redundant, but in this
16 * case the word Protocol is refering to the Libbu++ construct Bu::Protocol,
17 * and not a means of encoding conversations. Anyway, this class represents
18 * a general HTTP server processor. Every time a request comes in it calls
19 * the onRequest function in a subclass with the method and URI that were
20 * requested. The sub-class can then do whatever it needs to to send back
21 * a response.
15 */ 22 */
16 class ProtocolHttp : public Protocol 23 class ProtocolHttp : public Protocol
17 { 24 {
diff --git a/src/protocoltelnet.cpp b/src/protocoltelnet.cpp
index b0209db..e4fc926 100644
--- a/src/protocoltelnet.cpp
+++ b/src/protocoltelnet.cpp
@@ -1,30 +1,69 @@
1#include "bu/protocoltelnet.h" 1#include "bu/protocoltelnet.h"
2#include "bu/client.h" 2#include "bu/client.h"
3 3
4#define CODE_SE '\xf0' /**< End of subnegotiation params. */ 4/* We apparently at least want defs for the lower 13, not sure we care about
5#define CODE_NOP '\xf1' /**< No operation (keep-alive). */ 5 * the rest of the chars, maybe escape.
6#define CODE_DM '\xf2' /**< Datastream side of a Synch. */ 6 */
7#define CODE_BRK '\xf3' /**< Break character. */ 7#define CH_NUL '\x00' /* NUL */
8#define CODE_IP '\xf4' /**< Interrupt Process character. */ 8#define CH_SOH '\x01' /* Start Of Heading */
9#define CODE_AO '\xf5' /**< Abort Output character. */ 9#define CH_STX '\x02' /* Start of Text */
10#define CODE_AYT '\xf6' /**< Are You There? character. */ 10#define CH_ETX '\x03' /* End of Text */
11#define CODE_EC '\xf7' /**< Erase Character character. */ 11#define CH_EOT '\x04' /* End of transmission */
12#define CODE_EL '\xf8' /**< Erase Line character. */ 12#define CH_ENQ '\x05' /* Enquiery */
13#define CODE_GA '\xf9' /**< Go Ahead signal. */ 13#define CH_ACK '\x06' /* Acknowledge */
14#define CODE_SB '\xfa' /**< Begin subnegotiation options. */ 14#define CH_BEL '\x07' /* Bell */
15#define CODE_WILL '\xfb' /**< Desire to do something. */ 15#define CH_BS '\x08' /* Backspace */
16#define CODE_WONT '\xfc' /**< Refuse to perform. */ 16#define CH_TAB '\x09' /* Horizontal Tab */
17#define CODE_DO '\xfd' /**< Request option. */ 17#define CH_LF '\x0A' /* NL Line feed, new line */
18#define CODE_DONT '\xfe' /**< Demand a stop. */ 18#define CH_VT '\x0B' /* Vertical Tab */
19 19#define CH_FF '\x0C' /* Form feed, new page */
20#define CODE_IAC '\xff' /**< Interpret-As-Command. */ 20#define CH_CR '\x0D' /* Carriage return */
21 21#define CH_ESC '\x1B' /* Escape */
22#define OPT_BINARY '\x00' /**< Binary mode (file transfers?). */ 22#define CH_DEL '\x7F' /* Delete */
23#define OPT_ECHO '\x01' /**< (local) Echo mode. */ 23
24#define CODE_SE '\xf0' /* End of subnegotiation params. */
25#define CODE_NOP '\xf1' /* No operation (keep-alive). */
26#define CODE_DM '\xf2' /* Datastream side of a Synch. */
27#define CODE_BRK '\xf3' /* Break character. */
28#define CODE_IP '\xf4' /* Interrupt Process character. */
29#define CODE_AO '\xf5' /* Abort Output character. */
30#define CODE_AYT '\xf6' /* Are You There? character. */
31#define CODE_EC '\xf7' /* Erase Character character. */
32#define CODE_EL '\xf8' /* Erase Line character. */
33#define CODE_GA '\xf9' /* Go Ahead signal. */
34#define CODE_SB '\xfa' /* Begin subnegotiation options. */
35#define CODE_WILL '\xfb' /* Desire to do something. */
36#define CODE_WONT '\xfc' /* Refuse to perform. */
37#define CODE_DO '\xfd' /* Request option. */
38#define CODE_DONT '\xfe' /* Demand a stop. */
39
40#define CODE_IAC '\xff' /* Interpret-As-Command. */
41
42#define OPT_BINARY '\x00' /* Binary mode (file transfers?). */
43#define OPT_ECHO '\x01' /* (local) Echo mode. */
44#define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */
45#define OPT_STATUS '\x05' /* Allow status messages. */
46#define OPT_TIMING '\x06' /* Place a timing mark in the code. */
47#define OPT_EXASCII '\x11' /* Extended ASCII. */
48#define OPT_LOGOUT '\x12' /* Logout. */
49#define OPT_TTYPE '\x18' /* Terminal Type. */
50#define OPT_NAWS '\x1f' /* Negotiate about window size. */
51#define OPT_TSPEED '\x20' /* Terminal Speed. */
52#define OPT_NEWENV '\x27' /* New Environment Option. */
53#define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */
54
55#ifndef __TELNET_DEBUG
56# define printCode( a ) (void)0
57# define printOpt( a ) (void)0
58#endif
24 59
25Bu::ProtocolTelnet::ProtocolTelnet() : 60Bu::ProtocolTelnet::ProtocolTelnet() :
26 oBinary( *this, OPT_BINARY ), 61 oBinary( *this, OPT_BINARY ),
27 oEcho( *this, OPT_ECHO ) 62 oEcho( *this, OPT_ECHO ),
63 oNAWS( *this, OPT_NAWS ),
64 oSuppressGA(*this, OPT_SUPGA ),
65 bCanonical( true ),
66 bSubOpt( false )
28{ 67{
29} 68}
30 69
@@ -34,13 +73,410 @@ Bu::ProtocolTelnet::~ProtocolTelnet()
34 73
35void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) 74void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient )
36{ 75{
76 this->pClient = pClient;
37} 77}
38 78
39void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) 79void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient )
40{ 80{
81 char bc;
82 int iLeft;
83 while( (iLeft = pClient->getInputSize()) )
84 {
85 if( bSubOpt )
86 {
87 pClient->peek( &bc, 1 );
88 if( bc == CODE_IAC )
89 {
90 if( iLeft <= 1 ) return;
91 char bc2;
92 printCode( CODE_IAC );
93 pClient->peek( &bc2, 1, 1 );
94 printCode( bc2 );
95 if( bc2 == CODE_SE )
96 {
97 bSubOpt = false;
98 onSubOpt();
99 }
100 else if( bc2 == CODE_IAC )
101 {
102 sSubBuf += CODE_IAC;
103 }
104 else
105 {
106 // Error of some sort.
107 }
108 pClient->seek( 1 );
109 }
110 else
111 {
112 sSubBuf += bc;
113 }
114 pClient->seek( 1 );
115 }
116 else
117 {
118 pClient->peek( &bc, 1 );
119 if( bc == CODE_IAC )
120 {
121 if( iLeft <= 1 ) return;
122 char bc2;
123 pClient->peek( &bc2, 1, 1 );
124 printCode( bc );
125 printCode( bc2 );
126
127 switch( bc2 )
128 {
129 case CODE_WILL:
130 if( iLeft <= 2 ) return;
131 {
132 char bc3;
133 pClient->peek( &bc3, 1, 2 );
134 pClient->seek( 1 );
135 printOpt( bc3 );
136 onWill( bc3 );
137 }
138 break;
139
140 case CODE_WONT:
141 if( iLeft <= 2 ) return;
142 {
143 char bc3;
144 pClient->peek( &bc3, 1, 2 );
145 pClient->seek( 1 );
146 printOpt( bc3 );
147 onWont( bc3 );
148 }
149 break;
150
151 case CODE_DO:
152 if( iLeft <= 2 ) return;
153 {
154 char bc3;
155 pClient->peek( &bc3, 1, 2 );
156 pClient->seek( 1 );
157 printOpt( bc3 );
158 onDo( bc3 );
159 }
160 break;
161
162 case CODE_DONT:
163 if( iLeft <= 2 ) return;
164 {
165 char bc3;
166 pClient->peek( &bc3, 1, 2 );
167 pClient->seek( 1 );
168 printOpt( bc3 );
169 onDont( bc3 );
170 }
171 break;
172
173 case CODE_SB:
174 if( iLeft <= 2 ) return;
175 {
176 pClient->peek( &cSubOpt, 1, 2 );
177 pClient->seek( 1 );
178 printOpt( cSubOpt );
179 bSubOpt = true;
180 }
181 break;
182
183 case CODE_IAC:
184 sDataBuf += CODE_IAC;
185 printCode( CODE_IAC );
186 break;
187 }
188 pClient->seek( 1 );
189#ifdef __TELNET_DEBUG
190 printf("\n");
191#endif
192 }
193 else if( bc == CODE_SB )
194 {
195 }
196 else
197 {
198 // This is where control code handling goes
199 // Also, possibly, character code conversion, although I'm not
200 // sure that really matters anymore, go ASCII/UTF-8
201 if( bCanonical )
202 {
203 if( bc < 0x20 || bc >= CH_DEL )
204 {
205 if( bc == CH_CR )
206 {
207 if( iLeft <= 1 ) return;
208 char bc2;
209 pClient->peek( &bc2, 1, 1 );
210 if( bc2 == CH_NUL || bc2 == CH_LF )
211 {
212 onCtlChar( bc );
213 gotLine( sDataBuf );
214 sDataBuf.clear();
215 }
216 pClient->seek( 1 );
217 }
218 else
219 {
220 onCtlChar( bc );
221 }
222 }
223 else
224 {
225 sDataBuf += bc;
226 if( oEcho.isLocalSet() )
227 {
228 pClient->write( &bc, 1 );
229#ifdef __TELNET_DEBUG
230 printf("%c", bc );
231 fflush( stdout );
232#endif
233 }
234 }
235 }
236 else
237 {
238 sDataBuf += bc;
239 if( oEcho.isLocalSet() )
240 {
241 pClient->write( &bc, 1 );
242 }
243 }
244 }
245 pClient->seek( 1 );
246 }
247 }
248
249 // It's true, this code will not be executed if we only have half of an
250 // IAC code or multibyte escape sequence or something, but then again, it
251 // shouldn't be called then, and really, shouldn't be, it'll be called soon
252 // enough, when we get the rest of that code.
253 if( !bCanonical )
254 {
255 gotData( sDataBuf );
256 }
257}
258
259void Bu::ProtocolTelnet::setCanonical( bool bCon )
260{
261 bCanonical = bCon;
262}
263
264bool Bu::ProtocolTelnet::isCanonical()
265{
266 return bCanonical;
267}
268
269void Bu::ProtocolTelnet::write( const Bu::FString &sData )
270{
271 pClient->write( sData );
272}
273
274void Bu::ProtocolTelnet::write( char *pData, int iSize )
275{
276 pClient->write( pData, iSize );
277}
278
279void Bu::ProtocolTelnet::write( char cData )
280{
281 pClient->write( &cData, 1 );
282}
283
284void Bu::ProtocolTelnet::onWill( char cCode )
285{
286 try
287 {
288 Option *pOpt = hOpts[cCode];
289 if( pOpt->isRemoteEnabled() )
290 {
291 pOpt->fOpts |= Option::fRemoteIs;
292 char buf[3] = { CODE_IAC, CODE_DO, cCode };
293 pClient->write( buf, 3 );
294 }
295 else
296 {
297 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
298 pClient->write( buf, 3 );
299 }
300
301 }
302 catch( Bu::HashException &e )
303 {
304 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
305 pClient->write( buf, 3 );
306 }
307}
308
309void Bu::ProtocolTelnet::onWont( char cCode )
310{
311 try
312 {
313 Option *pOpt = hOpts[cCode];
314
315 pOpt->fOpts &= ~Option::fRemoteIs;
316 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
317 pClient->write( buf, 3 );
318 }
319 catch( Bu::HashException &e )
320 {
321 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
322 pClient->write( buf, 3 );
323 }
324}
325
326void Bu::ProtocolTelnet::onDo( char cCode )
327{
328 try
329 {
330 Option *pOpt = hOpts[cCode];
331 if( pOpt->isLocalEnabled() )
332 {
333 pOpt->fOpts |= Option::fLocalIs;
334 char buf[3] = { CODE_IAC, CODE_WILL, cCode };
335 pClient->write( buf, 3 );
336 }
337 else
338 {
339 char buf[3] = { CODE_IAC, CODE_WONT, cCode };
340 pClient->write( buf, 3 );
341 }
342
343 }
344 catch( Bu::HashException &e )
345 {
346 char buf[3] = { CODE_IAC, CODE_WONT, cCode };
347 pClient->write( buf, 3 );
348 }
349}
350
351void Bu::ProtocolTelnet::onDont( char cCode )
352{
353 try
354 {
355 Option *pOpt = hOpts[cCode];
356
357 pOpt->fOpts &= ~Option::fLocalIs;
358 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
359 pClient->write( buf, 3 );
360 }
361 catch( Bu::HashException &e )
362 {
363 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
364 pClient->write( buf, 3 );
365 }
41} 366}
42 367
368void Bu::ProtocolTelnet::onSubOpt()
369{
370 switch( cSubOpt )
371 {
372 case OPT_NAWS:
373 {
374 uint16_t iWidth, iHeight;
375 ((char *)&iWidth)[1] = sSubBuf[0];
376 ((char *)&iWidth)[0] = sSubBuf[1];
377 ((char *)&iHeight)[1] = sSubBuf[2];
378 ((char *)&iHeight)[0] = sSubBuf[3];
379 onSubNAWS( iWidth, iHeight );
380 }
381 break;
43 382
383 default:
384 onSubUnknown( cSubOpt, sSubBuf );
385 break;
386 }
387
388 sSubBuf.clear();
389}
390
391void Bu::ProtocolTelnet::onCtlChar( char cChr )
392{
393#ifdef __TELNET_DEBUG
394 switch( cChr )
395 {
396 case CH_NUL: printf("NUL "); break;
397 case CH_SOH: printf("SOH "); break;
398 case CH_STX: printf("STX "); break;
399 case CH_ETX: printf("ETX "); break;
400 case CH_EOT: printf("EOT "); break;
401 case CH_ENQ: printf("ENQ "); break;
402 case CH_ACK: printf("ACK "); break;
403 case CH_BEL: printf("BEL "); break;
404 case CH_BS: printf("BS "); break;
405 case CH_TAB: printf("TAB "); break;
406 case CH_LF: printf("LF "); break;
407 case CH_VT: printf("VT "); break;
408 case CH_FF: printf("FF "); break;
409 case CH_CR: printf("CR "); break;
410 case CH_ESC: printf("ESC "); break;
411 case CH_DEL: printf("DEL "); break;
412 default: printf("!![%02x] ", cChr ); break;
413 }
414 fflush( stdout );
415#endif
416
417 switch( cChr )
418 {
419 case CH_DEL:
420 {
421 if( sDataBuf.getSize() > 0 )
422 {
423 sDataBuf.resize( sDataBuf.getSize()-1 );
424 char buf[3] = { CH_BS, ' ', CH_BS };
425 pClient->write( buf, 3 );
426 }
427 }
428 break;
429
430 }
431}
432
433#ifdef __TELNET_DEBUG
434void Bu::ProtocolTelnet::printCode( char cCode )
435{
436 switch( cCode )
437 {
438 case CODE_SE: printf("SE "); break;
439 case CODE_NOP: printf("NOP "); break;
440 case CODE_DM: printf("DM "); break;
441 case CODE_BRK: printf("BRK "); break;
442 case CODE_IP: printf("IP "); break;
443 case CODE_AO: printf("AO "); break;
444 case CODE_AYT: printf("AYT "); break;
445 case CODE_EC: printf("EC "); break;
446 case CODE_EL: printf("EL "); break;
447 case CODE_GA: printf("GA "); break;
448 case CODE_SB: printf("SB "); break;
449 case CODE_WILL: printf("WILL "); break;
450 case CODE_WONT: printf("WONT "); break;
451 case CODE_DO: printf("DO "); break;
452 case CODE_DONT: printf("DONT "); break;
453 case CODE_IAC: printf("IAC "); break;
454 default: printf("??%02x ", cCode ); break;
455 }
456 fflush( stdout );
457}
458
459void Bu::ProtocolTelnet::printOpt( char cOpt )
460{
461 switch( cOpt )
462 {
463 case OPT_BINARY: printf("BINARY "); break;
464 case OPT_ECHO: printf("ECHO "); break;
465 case OPT_SUPGA: printf("SUPGA "); break;
466 case OPT_STATUS: printf("STATUS "); break;
467 case OPT_TIMING: printf("TIMING "); break;
468 case OPT_EXASCII: printf("EXASCII "); break;
469 case OPT_LOGOUT: printf("LOGOUT "); break;
470 case OPT_TTYPE: printf("TTYPE "); break;
471 case OPT_NAWS: printf("NAWS "); break;
472 case OPT_TSPEED: printf("TSPEED "); break;
473 case OPT_NEWENV: printf("NEWENV "); break;
474 case OPT_EXOPL: printf("EXOPL "); break;
475 default: printf("??%02x ", cOpt); break;
476 }
477 fflush( stdout );
478}
479#endif
44 480
45Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : 481Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) :
46 rPT( rPT ), 482 rPT( rPT ),
@@ -68,19 +504,31 @@ void Bu::ProtocolTelnet::Option::localSet( bool bSet )
68{ 504{
69 if( bSet == (bool)(fOpts&fLocalIs) ) return; 505 if( bSet == (bool)(fOpts&fLocalIs) ) return;
70 506
71 char buf[2]; 507 char buf[3] = { CODE_IAC, 0, cCode };
72 508
73 if( bSet ) 509 if( bSet )
74 { 510 {
75 buf[0] = CODE_WILL; 511 buf[1] = CODE_WILL;
76 buf[1] = cCode; 512 rPT.pClient->write( buf, 3 );
77 rPT.pClient->write( buf, 2 ); 513#ifdef __TELNET_DEBUG
514 printf("<= ");
515 rPT.printCode( buf[0] );
516 rPT.printCode( buf[1] );
517 rPT.printOpt( buf[2] );
518 printf("\n");
519#endif
78 } 520 }
79 else 521 else
80 { 522 {
81 buf[0] = CODE_WONT; 523 buf[1] = CODE_WONT;
82 buf[1] = cCode; 524 rPT.pClient->write( buf, 3 );
83 rPT.pClient->write( buf, 2 ); 525#ifdef __TELNET_DEBUG
526 printf("<= ");
527 rPT.printCode( buf[0] );
528 rPT.printCode( buf[1] );
529 rPT.printOpt( buf[2] );
530 printf("\n");
531#endif
84 } 532 }
85} 533}
86 534
@@ -101,21 +549,33 @@ void Bu::ProtocolTelnet::Option::remoteEnable( bool bSet )
101 549
102void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) 550void Bu::ProtocolTelnet::Option::remoteSet( bool bSet )
103{ 551{
104 if( bSet == (bool)(fOpts&fRemoteIs) ) return; 552 //if( bSet == (bool)(fOpts&fRemoteIs) ) return;
105 553
106 char buf[2]; 554 char buf[3] = { CODE_IAC, 0, cCode };
107 555
108 if( bSet ) 556 if( bSet )
109 { 557 {
110 buf[0] = CODE_DO; 558 buf[1] = CODE_DO;
111 buf[1] = cCode; 559 rPT.pClient->write( buf, 3 );
112 rPT.pClient->write( buf, 2 ); 560#ifdef __TELNET_DEBUG
561 printf("<= ");
562 rPT.printCode( buf[0] );
563 rPT.printCode( buf[1] );
564 rPT.printOpt( buf[2] );
565 printf("\n");
566#endif
113 } 567 }
114 else 568 else
115 { 569 {
116 buf[0] = CODE_DONT; 570 buf[1] = CODE_DONT;
117 buf[1] = cCode; 571 rPT.pClient->write( buf, 3 );
118 rPT.pClient->write( buf, 2 ); 572#ifdef __TELNET_DEBUG
573 printf("<= ");
574 rPT.printCode( buf[0] );
575 rPT.printCode( buf[1] );
576 rPT.printOpt( buf[2] );
577 printf("\n");
578#endif
119 } 579 }
120} 580}
121 581
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
diff --git a/src/tests/telnetsrv.cpp b/src/tests/telnetsrv.cpp
new file mode 100644
index 0000000..39e3217
--- /dev/null
+++ b/src/tests/telnetsrv.cpp
@@ -0,0 +1,85 @@
1#include "bu/server.h"
2#include "bu/protocoltelnet.h"
3#include "bu/client.h"
4
5class MyTelnet : public Bu::ProtocolTelnet
6{
7public:
8 MyTelnet()
9 {
10 }
11
12 virtual ~MyTelnet()
13 {
14 }
15
16 virtual void onNewConnection( Bu::Client *pClient )
17 {
18 Bu::ProtocolTelnet::onNewConnection( pClient );
19
20 //oNAWS.remoteSet();
21 oEcho.localSet();
22 oSuppressGA.remoteSet( true );
23 oSuppressGA.localSet( true );
24 setCanonical();
25 }
26
27 virtual void onSubNAWS( uint16_t iWidth, uint16_t iHeight )
28 {
29 printf("New dim = (%dx%d)\n", iWidth, iHeight );
30 }
31
32 virtual void gotLine( Bu::FString &sLine )
33 {
34 printf("Line: \"%s\"\n", sLine.getStr() );
35 write("\n\r", 2 );
36 }
37
38private:
39
40};
41
42class TelServer : public Bu::Server
43{
44public:
45 TelServer()
46 {
47 }
48
49 virtual ~TelServer()
50 {
51 }
52
53 virtual void onNewConnection( Bu::Client *pClient, int iPort )
54 {
55 printf("New connection.\n");
56
57 pClient->setProtocol( new MyTelnet() );
58 }
59
60 virtual void onClosedConnection( Bu::Client *pClient )
61 {
62 printf("Lost connection.\n");
63
64 delete pClient->getProtocol();
65 }
66
67private:
68
69};
70
71int main( int argc, char *argv[] )
72{
73 TelServer ts;
74
75 ts.addPort( 4000 );
76 ts.setTimeout( 0, 5000 );
77
78 printf("Initializing server on port: 4000\n");
79
80 for(;;)
81 {
82 ts.scan();
83 }
84}
85