telnet.go 18 KB

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