telnet.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. package telnet
  2. // import "bytes"
  3. import "io"
  4. import "strings"
  5. import "fmt"
  6. import "compress/zlib"
  7. import "github.com/beoran/woe/monolog"
  8. // This Telnet module implements a subset of the Telnet protocol.
  9. // Telnet states
  10. type TelnetState int
  11. const (
  12. data_state TelnetState = iota
  13. iac_state = iota
  14. will_state = iota
  15. wont_state = iota
  16. do_state = iota
  17. dont_state = iota
  18. sb_state = iota
  19. sb_data_state = iota
  20. sb_data_iac_state = iota
  21. )
  22. // Telnet event type constants
  23. type EventType int
  24. const (
  25. TELNET_DATA_EVENT EventType = iota
  26. TELNET_NAWS_EVENT EventType = iota
  27. TELNET_TTYPE_EVENT EventType = iota
  28. TELNET_SUBNEGOTIATE_EVENT EventType = iota
  29. TELNET_IAC_EVENT EventType = iota
  30. TELNET_COMPRESS_EVENT EventType = iota
  31. TELNET_ENVIRONMENT_EVENT EventType = iota
  32. TELNET_MSSP_EVENT EventType = iota
  33. TELNET_ZMP_EVENT EventType = iota
  34. TELNET_WILL_EVENT EventType = iota
  35. TELNET_WONT_EVENT EventType = iota
  36. TELNET_DO_EVENT EventType = iota
  37. TELNET_DONT_EVENT EventType = iota
  38. TELNET_ERROR_EVENT EventType = iota
  39. TELNET_UNKNOWN_EVENT EventType = iota
  40. )
  41. // Telnet event types
  42. type Event interface {
  43. Type() EventType
  44. }
  45. type DataEvent struct {
  46. Data [] byte
  47. }
  48. func (me DataEvent) Type() EventType { return TELNET_DATA_EVENT; }
  49. type NAWSEvent struct {
  50. W int
  51. H int
  52. }
  53. func (me NAWSEvent) Type() EventType { return TELNET_NAWS_EVENT; }
  54. type TTypeEvent struct {
  55. Telopt byte
  56. Name string
  57. }
  58. func (me TTypeEvent) Type() EventType { return TELNET_TTYPE_EVENT; }
  59. type SubnegotiateEvent struct {
  60. Telopt byte
  61. Buffer [] byte
  62. }
  63. func (me SubnegotiateEvent) Type() EventType { return TELNET_SUBNEGOTIATE_EVENT; }
  64. type IACEvent struct {
  65. Telopt byte
  66. }
  67. func (me IACEvent) Type() EventType { return TELNET_IAC_EVENT; }
  68. type CompressEvent struct {
  69. Compress bool
  70. }
  71. func (me CompressEvent) Type() EventType { return TELNET_COMPRESS_EVENT; }
  72. // Storage for environment values
  73. type Environment struct {
  74. Type byte
  75. Value string
  76. }
  77. type EnvironmentEvent struct {
  78. Telopt byte
  79. Vars [] Environment
  80. }
  81. func (me EnvironmentEvent) Type() EventType { return TELNET_ENVIRONMENT_EVENT; }
  82. type MSSPEvent struct {
  83. Telopt byte
  84. Vars map[string] string
  85. }
  86. func (me MSSPEvent) Type() EventType { return TELNET_MSSP_EVENT; }
  87. type ZMPEvent struct {
  88. Vars []string
  89. }
  90. func (me ZMPEvent) Type() EventType { return TELNET_ZMP_EVENT; }
  91. type WillEvent struct {
  92. Telopt byte
  93. }
  94. func (me WillEvent) Type() EventType { return TELNET_WILL_EVENT; }
  95. type WontEvent struct {
  96. Telopt byte
  97. }
  98. func (me WontEvent) Type() EventType { return TELNET_WONT_EVENT; }
  99. type DoEvent struct {
  100. Telopt byte
  101. }
  102. func (me DoEvent) Type() EventType { return TELNET_DO_EVENT; }
  103. type DontEvent struct {
  104. Telopt byte
  105. }
  106. func (me DontEvent) Type() EventType { return TELNET_DONT_EVENT; }
  107. // For protocol errors.
  108. type ErrorEvent struct {
  109. error string
  110. }
  111. func (me ErrorEvent) Type() EventType { return TELNET_ERROR_EVENT; }
  112. // Returns the numerical event type of an event. Useful for direct comparison.
  113. func EventTypeOf(event Event) EventType {
  114. return event.Type()
  115. }
  116. // Returns true if the event is of the given type, or false if not
  117. func IsEventType(event Event, typ EventType) bool {
  118. return EventTypeOf(event) == typ;
  119. }
  120. type EventChannel chan(Event)
  121. type Telopt struct {
  122. telopt byte
  123. us byte
  124. him byte
  125. }
  126. type Telnet struct {
  127. Events EventChannel
  128. ToClient chan([]byte)
  129. telopts map[byte] Telopt
  130. state TelnetState
  131. compress bool
  132. zwriter zlib.Writer
  133. zreader io.ReadCloser
  134. buffer []byte
  135. sb_telopt byte
  136. }
  137. func New() (telnet * Telnet) {
  138. events := make(EventChannel, 64)
  139. toclient := make(chan([]byte), 64)
  140. telopts := make (map[byte] Telopt)
  141. state := data_state
  142. compress := false
  143. var zwriter zlib.Writer
  144. var zreader io.ReadCloser
  145. var buffer []byte = nil
  146. sb_telopt := byte(0)
  147. telnet = &Telnet { events, toclient, telopts, state, compress, zwriter, zreader, buffer, sb_telopt }
  148. return telnet
  149. }
  150. // Starts compresssion
  151. func (me * Telnet) StartCompression() {
  152. // var zwbuf bytes.Buffer
  153. // me.zwriter = zlib.NewWriter(&zwbuf);
  154. }
  155. // Closes the telnet connection, send last compressed data if needed.
  156. func (me * Telnet) Close() {
  157. if me.compress {
  158. me.zwriter.Close()
  159. me.zreader.Close()
  160. }
  161. }
  162. // Filters raw text, only compressing it if needed.
  163. func (me * Telnet) SendRaw(in []byte) {
  164. // XXX Handle compression here later
  165. me.ToClient <- in
  166. }
  167. // Filters text, escaping IAC bytes.
  168. func (me * Telnet) SendEscaped(in []byte) {
  169. buffer := make([]byte, len(in) * 2, len(in) * 2)
  170. outdex := 0
  171. /* Double IAC characters to escape them. */
  172. for index := 0; index < len(in) ; index++ {
  173. now := in[index]
  174. if now == TELNET_IAC {
  175. buffer[outdex] = TELNET_IAC;
  176. outdex++;
  177. }
  178. buffer[outdex] = now;
  179. outdex++;
  180. }
  181. me.SendRaw(buffer)
  182. }
  183. // Send negotiation bytes
  184. func (me * Telnet) SendNegotiate(cmd byte, telopt byte) {
  185. buffer := make([]byte, 3)
  186. buffer[0] = TELNET_IAC
  187. buffer[1] = cmd
  188. buffer[2] = telopt
  189. me.SendRaw(buffer)
  190. }
  191. func (me * Telnet) SendEvent(event Event) {
  192. me.Events <- event
  193. }
  194. // Parse a subnegotiation buffer for a naws event
  195. func (me * Telnet) SubnegotiateNAWS(buffer []byte) {
  196. // Some clients, like Gnome-Mud can't even get this right. Grrr!
  197. if buffer == nil || len(buffer) != 4 {
  198. monolog.Warning("Bad NAWS negotiation: #{buffer}")
  199. return
  200. }
  201. var w int = (int(buffer[0]) << 8) + int(buffer[1])
  202. var h int = (int(buffer[2]) << 8) + int(buffer[3])
  203. me.SendEvent(&NAWSEvent{w, h})
  204. }
  205. // process an ENVIRON/NEW-ENVIRON subnegotiation buffer
  206. func (me * Telnet) SubnegotiateEnviron(buffer []byte) {
  207. var vars []Environment
  208. var cmd []byte
  209. fb := buffer[0]
  210. // First byte must be a valid command
  211. if fb != TELNET_ENVIRON_SEND && fb != TELNET_ENVIRON_IS && fb != TELNET_ENVIRON_INFO {
  212. monolog.Warning("telopt environment subneg command not valid")
  213. }
  214. cmd = append(cmd, fb)
  215. if len(buffer) == 1 {
  216. me.SendEvent(&EnvironmentEvent{fb, vars})
  217. return
  218. }
  219. // Second byte must be VAR or USERVAR, if present
  220. sb := buffer[1]
  221. if sb != TELNET_ENVIRON_VAR && fb != TELNET_ENVIRON_USERVAR {
  222. monolog.Warning("telopt environment subneg missing variable type")
  223. return
  224. }
  225. // ensure last byte is not an escape byte (makes parsing later easier)
  226. lb := buffer[len(buffer) - 1]
  227. if lb == TELNET_ENVIRON_ESC {
  228. monolog.Warning("telopt environment subneg ends with ESC")
  229. return
  230. }
  231. /* XXX : not implemented yet
  232. var variable * Environment = nil
  233. index := 1
  234. escape := false
  235. for index := 1 ; index < len(buffer) ; index++ {
  236. c := buffer[index]
  237. switch c {
  238. case TELNET_ENVIRON_VAR:
  239. fallthrough
  240. case TELNET_ENVIRON_VALUE:
  241. fallthrough
  242. case TELNET_ENVIRON_USERVAR:
  243. if escape {
  244. escape = false
  245. variable.Value = append(variable.Value, c)
  246. } else if (variable != nil) {
  247. vars = append(vars, variable)
  248. variable = new(Environment)
  249. variable.Type = c
  250. } else {
  251. variable = new(Environment)
  252. variable.Type = c
  253. }
  254. case TELNET_ENVIRON_ESC:
  255. escape = true
  256. default:
  257. variable.Value = append(variable.Value, c)
  258. }
  259. }
  260. // Finally send event
  261. me.SendEvent(&EnvironmentEvent{fb, vars})
  262. */
  263. }
  264. const (
  265. MSTATE_NONE = 0
  266. MSTATE_VAR = 1
  267. MSTATE_VAL = 2
  268. )
  269. // process an MSSP subnegotiation buffer
  270. func (me * Telnet) SubnegotiateMSSP(buffer []byte) {
  271. if len(buffer) < 1 {
  272. return
  273. }
  274. fb := buffer[0]
  275. // first byte must be a valid command
  276. if fb != TELNET_MSSP_VAR {
  277. monolog.Warning("telopt MSSP subneg data not valid")
  278. return
  279. }
  280. variables := make(map[string] string)
  281. var variable []byte
  282. var value []byte
  283. mstate := MSTATE_NONE
  284. for index := 0 ; index < len(buffer) ; index ++ {
  285. c := buffer[index]
  286. switch c {
  287. case TELNET_MSSP_VAR:
  288. mstate = MSTATE_VAR
  289. if mstate == MSTATE_VAR {
  290. variables[string(variable)] = string(value)
  291. variable = nil
  292. value = nil
  293. }
  294. case TELNET_MSSP_VAL:
  295. mstate = MSTATE_VAL
  296. default:
  297. if mstate == MSTATE_VAL {
  298. variable = append(variable, c)
  299. } else {
  300. value = append(value, c)
  301. }
  302. }
  303. }
  304. me.SendEvent(&MSSPEvent{fb, variables})
  305. }
  306. // Parse ZMP command subnegotiation buffers
  307. func (me * Telnet) SubnegotiateZMP(buffer []byte) {
  308. var vars []string
  309. var variable []byte
  310. var b byte
  311. for index := 0 ; index < len(buffer) ; index++ {
  312. b = buffer[index]
  313. if b == 0 {
  314. vars = append(vars, string(variable))
  315. variable = nil
  316. } else {
  317. variable = append(variable, b)
  318. }
  319. }
  320. me.SendEvent(&ZMPEvent{vars})
  321. }
  322. // parse TERMINAL-TYPE command subnegotiation buffers
  323. func (me * Telnet) SubnegotiateTType(buffer []byte) {
  324. // make sure request is not empty
  325. if len(buffer) == 0 {
  326. monolog.Warning("Incomplete TERMINAL-TYPE request");
  327. return
  328. }
  329. fb := buffer[0]
  330. if fb != TELNET_TTYPE_IS && fb != TELNET_TTYPE_SEND {
  331. monolog.Warning("TERMINAL-TYPE request has invalid type %d (%v)", fb, buffer)
  332. return
  333. }
  334. term := string(buffer[1:])
  335. me.SendEvent(&TTypeEvent{fb, term})
  336. }
  337. // process a subnegotiation buffer; returns true if the current buffer
  338. // must be aborted and reprocessed due to COMPRESS2 being activated
  339. func (me * Telnet) DoSubnegotiate(buffer []byte) bool {
  340. switch me.sb_telopt {
  341. case TELNET_TELOPT_COMPRESS2:
  342. // received COMPRESS2 begin marker, setup our zlib box and
  343. // start handling the compressed stream if it's not already.
  344. me.compress = true
  345. me.SendEvent(&CompressEvent{me.compress})
  346. return true
  347. // specially handled subnegotiation telopt types
  348. case TELNET_TELOPT_TTYPE:
  349. me.SubnegotiateTType(buffer)
  350. case TELNET_TELOPT_ENVIRON:
  351. me.SubnegotiateEnviron(buffer)
  352. case TELNET_TELOPT_NEW_ENVIRON:
  353. me.SubnegotiateEnviron(buffer)
  354. case TELNET_TELOPT_MSSP:
  355. me.SubnegotiateMSSP(buffer)
  356. case TELNET_TELOPT_NAWS:
  357. me.SubnegotiateNAWS(buffer)
  358. case TELNET_TELOPT_ZMP:
  359. me.SubnegotiateZMP(buffer)
  360. default:
  361. // Send catch all subnegotiation event
  362. me.SendEvent(&SubnegotiateEvent{me.sb_telopt, buffer})
  363. }
  364. return false
  365. }
  366. func (me * Telnet) DoNegotiate(state TelnetState, telopt byte) bool {
  367. switch me.state {
  368. case will_state:
  369. me.SendEvent(&WillEvent{telopt})
  370. case wont_state:
  371. me.SendEvent(&WontEvent{telopt})
  372. case do_state:
  373. me.SendEvent(&DoEvent{telopt})
  374. case dont_state:
  375. me.SendEvent(&DontEvent{telopt})
  376. default:
  377. monolog.Warning("State not vvalid in telnet negotiation.")
  378. }
  379. me.state = data_state
  380. return false
  381. }
  382. // Send the current buffer as a DataEvent if it's not empty
  383. // Also empties the buffer if it wasn't emmpty
  384. func (me * Telnet) maybeSendDataEventAndEmptyBuffer() {
  385. if (me.buffer != nil) && (len(me.buffer) > 0) {
  386. me.SendEvent(&DataEvent{me.buffer})
  387. me.buffer = nil
  388. }
  389. }
  390. // Append a byte to the data buffer
  391. func (me * Telnet) appendByte(bin byte) {
  392. monolog.Debug("Appending to telnet buffer: %d %d", len(me.buffer), cap(me.buffer))
  393. me.buffer = append(me.buffer, bin)
  394. }
  395. // Process a byte in the data state
  396. func (me * Telnet) dataStateProcessByte(bin byte) bool {
  397. if bin == TELNET_IAC {
  398. // receive buffered bytes as data and go to IAC state if it's notempty
  399. me.maybeSendDataEventAndEmptyBuffer()
  400. me.state = iac_state
  401. } else {
  402. me.appendByte(bin)
  403. }
  404. return false
  405. }
  406. // Process a byte in the IAC state
  407. func (me * Telnet) iacStateProcessByte(bin byte) bool {
  408. switch bin {
  409. // subnegotiation
  410. case TELNET_SB:
  411. me.state = sb_state
  412. // negotiation commands
  413. case TELNET_WILL:
  414. me.state = will_state
  415. case TELNET_WONT:
  416. me.state = wont_state
  417. case TELNET_DO:
  418. me.state = do_state
  419. case TELNET_DONT:
  420. me.state = dont_state
  421. // IAC escaping
  422. case TELNET_IAC:
  423. me.appendByte(TELNET_IAC)
  424. me.maybeSendDataEventAndEmptyBuffer()
  425. me.state = data_state
  426. // some other command
  427. default:
  428. me.SendEvent(IACEvent { bin })
  429. me.state = data_state
  430. }
  431. return false
  432. }
  433. // Process a byte in the subnegotiation data state
  434. func (me * Telnet) sbdataStateProcessByte(bin byte) bool {
  435. // IAC command in subnegotiation -- either IAC SE or IAC IAC
  436. if (bin == TELNET_IAC) {
  437. me.state = sb_data_iac_state
  438. } else if me.sb_telopt == TELNET_TELOPT_COMPRESS && bin == TELNET_WILL {
  439. // MCCPv1 defined an invalid subnegotiation sequence (IAC SB 85 WILL SE)
  440. // to start compression. Catch and discard this case, only support
  441. // MMCPv2.
  442. me.state = data_state
  443. } else {
  444. me.appendByte(bin)
  445. }
  446. return false
  447. }
  448. // Process a byte in the IAC received when processing subnegotiation data state
  449. func (me * Telnet) sbdataiacStateProcessByte(bin byte) bool {
  450. switch bin {
  451. //end subnegotiation
  452. case TELNET_SE:
  453. me.state = data_state
  454. // process subnegotiation
  455. compress := me.DoSubnegotiate(me.buffer)
  456. // if compression was negotiated, the rest of the stream is compressed
  457. // and processing it requires decompressing it. Return true to signal
  458. // this.
  459. me.buffer = nil
  460. if compress {
  461. return true
  462. }
  463. // escaped IAC byte
  464. case TELNET_IAC:
  465. // push IAC into buffer
  466. me.appendByte(bin)
  467. me.state = sb_data_state
  468. // something else -- protocol error. attempt to process
  469. // content in subnegotiation buffer, then evaluate the
  470. // given command as an IAC code.
  471. default:
  472. monolog.Warning("Unexpected byte after IAC inside SB: %d", bin)
  473. me.state = iac_state
  474. // subnegotiate with the buffer anyway, even though it's an error
  475. compress := me.DoSubnegotiate(me.buffer)
  476. // if compression was negotiated, the rest of the stream is compressed
  477. // and processing it requires decompressing it. Return true to signal
  478. // this.
  479. me.buffer = nil
  480. if compress {
  481. return true
  482. }
  483. }
  484. return false
  485. }
  486. // Process a single byte received from the client
  487. func (me * Telnet) ProcessByte(bin byte) bool {
  488. monolog.Debug("ProcessByte %d %d", bin, me.state)
  489. switch me.state {
  490. // regular data
  491. case data_state:
  492. return me.dataStateProcessByte(bin)
  493. // IAC received before
  494. case iac_state:
  495. return me.iacStateProcessByte(bin)
  496. case will_state, wont_state, do_state, dont_state:
  497. return me.DoNegotiate(me.state, bin)
  498. // subnegotiation started, determine option to subnegotiate
  499. case sb_state:
  500. me.sb_telopt = bin
  501. me.state = sb_data_state
  502. // subnegotiation data, buffer bytes until the end request
  503. case sb_data_state:
  504. return me.sbdataStateProcessByte(bin)
  505. // IAC received inside a subnegotiation
  506. case sb_data_iac_state:
  507. return me.sbdataiacStateProcessByte(bin)
  508. default:
  509. // programing error, shouldn't happen
  510. panic("Error in telnet state machine!")
  511. }
  512. // return false to signal compression needn't start
  513. return false
  514. }
  515. // Process multiple bytes received from the client
  516. func (me * Telnet) ProcessBytes(bytes []byte) {
  517. for index := 0 ; index < len(bytes) ; {
  518. bin := bytes[index]
  519. compress := me.ProcessByte(bin)
  520. if compress {
  521. // paper over this for a while...
  522. // new_bytes = Zlib.inflate(arr.pack('c*')) rescue nil
  523. // if new_bytes
  524. //arr = new_bytes.bytes.to_a
  525. }
  526. index ++
  527. }
  528. me.maybeSendDataEventAndEmptyBuffer()
  529. }
  530. // Call this when the server receives data from the client
  531. func (me * Telnet) TelnetReceive(data []byte) {
  532. // the COMPRESS2 protocol seems to be half-duplex in that only
  533. // the server's data stream is compressed (unless maybe if the client
  534. // is asked to also compress with a DO command ?)
  535. me.ProcessBytes(data)
  536. }
  537. // Send a bytes array (raw) to the client
  538. func (me * Telnet) TelnetSendBytes(bytes ...byte) {
  539. me.SendRaw(bytes)
  540. }
  541. // Send an iac command
  542. func (me * Telnet) TelnetSendIac(cmd byte) {
  543. me.TelnetSendBytes(TELNET_IAC, cmd)
  544. }
  545. // Send negotiation. Currently rfc1143 is not implemented, so beware of
  546. // server client loops. The simplest way to avoid those is to never answer any
  547. // client requests, only send server requests.
  548. func (me * Telnet) TelnetSendNegotiate(cmd byte, telopt byte) {
  549. me.TelnetSendBytes(TELNET_IAC, cmd, telopt)
  550. }
  551. // Send non-command data (escapes IAC bytes)
  552. func (me * Telnet) TelnetSend(buffer []byte) {
  553. me.SendEscaped(buffer)
  554. }
  555. // send subnegotiation header
  556. func (me * Telnet) TelnetBeginSubnegotiation(telopt byte) {
  557. me.TelnetSendBytes(TELNET_IAC, TELNET_SB, telopt)
  558. }
  559. // send subnegotiation ending
  560. func (me * Telnet) TelnetEndSubnegotiation() {
  561. me.TelnetSendBytes(TELNET_IAC, TELNET_SE)
  562. }
  563. // Send complete subnegotiation
  564. func (me * Telnet) TelnetSubnegotiation(telopt byte, buffer []byte) {
  565. me.TelnetBeginSubnegotiation(telopt)
  566. if buffer != nil {
  567. me.TelnetSend(buffer)
  568. }
  569. me.TelnetEndSubnegotiation()
  570. }
  571. // Ask client to start accepting compress2 compression
  572. func (me * Telnet) TelnetBeginCompress2() {
  573. me.TelnetSendBytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_COMPRESS2, TELNET_IAC, TELNET_SE);
  574. me.compress = true
  575. }
  576. // Send formatted data to the client
  577. func (me * Telnet) TelnetRawPrintf(format string, args ...interface{}) {
  578. buf := fmt.Sprintf(format, args...)
  579. me.TelnetSend([]byte(buf))
  580. }
  581. const CRLF = "\r\n"
  582. const CRNUL = "\r\000"
  583. // send formatted data with \r and \n translation in addition to IAC IAC
  584. // escaping
  585. func (me * Telnet) TelnetPrintf(format string, args ...interface{}) {
  586. buf := fmt.Sprintf(format, args...)
  587. buf = strings.Replace(buf, "\r", CRNUL, -1)
  588. buf = strings.Replace(buf, "\n", CRLF , -1)
  589. me.TelnetSend([]byte(buf))
  590. }
  591. // NEW-ENVIRON subnegotation
  592. func (me * Telnet) TelnetNewenviron(cmd []byte) {
  593. me.TelnetSubnegotiation(TELNET_TELOPT_NEW_ENVIRON, cmd)
  594. }
  595. // send TERMINAL-TYPE SEND command
  596. func (me * Telnet) TelnetTTypeSend() {
  597. me.TelnetSendBytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_SEND, TELNET_IAC, TELNET_SE)
  598. }
  599. // send TERMINAL-TYPE IS command
  600. func (me * Telnet) TelnetTTypeIS(ttype string) {
  601. me.TelnetSendBytes(TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS)
  602. me.TelnetSend([]byte(ttype))
  603. }
  604. // send MSSP data
  605. func (me * Telnet) TelnetSendMSSP(mssp map[string] string) {
  606. var buf []byte
  607. for key, val := range mssp {
  608. buf = append(buf, TELNET_MSSP_VAR)
  609. buf = append(buf, key...)
  610. buf = append(buf, TELNET_MSSP_VAL)
  611. buf = append(buf, val...)
  612. }
  613. me.TelnetSubnegotiation(TELNET_TELOPT_MSSP, buf)
  614. }