telnet.go 20 KB

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