setuptelnet.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package server
  2. import "github.com/beoran/woe/monolog"
  3. import t "github.com/beoran/woe/telnet"
  4. import "github.com/beoran/woe/telnet"
  5. import "strings"
  6. import "strconv"
  7. /* This file contains telnet setup helpers for the client. */
  8. // generic negotiation
  9. func (me * Client) SetupNegotiate(millis int, command byte, option byte, yes_event telnet.EventType, no_event telnet.EventType) (bool, telnet.Event) {
  10. me.telnet.TelnetSendNegotiate(command, option)
  11. tev, timeout, close := me.TryReadEvent(millis)
  12. if tev == nil || timeout || close {
  13. monolog.Info("Timeout or close in TryReadEvent")
  14. return false, nil
  15. }
  16. evtype := telnet.EventTypeOf(tev)
  17. if evtype == no_event {
  18. monolog.Info("Negative event no_event %v %v %v", tev, evtype, no_event)
  19. return false, tev
  20. }
  21. if evtype != yes_event {
  22. monolog.Info("Unexpected event yes_event %v %v %v", tev, evtype, yes_event)
  23. return false, tev
  24. }
  25. return true, tev
  26. }
  27. // Negotiate COMPRESS2 support
  28. func (me * Client) SetupCompress2() telnet.Event {
  29. ok, tev := me.SetupNegotiate(1000, t.TELNET_WILL, t.TELNET_TELOPT_COMPRESS2, t.TELNET_DO_EVENT, t.TELNET_DONT_EVENT)
  30. if (!ok) {
  31. return tev
  32. }
  33. me.telnet.TelnetBeginCompress2()
  34. monolog.Info("Client #{@id} started COMPRESS2 compression")
  35. me.info.compress2 = true
  36. return tev
  37. }
  38. // Negotiate NAWS (window size) support
  39. func (me * Client) SetupNAWS() telnet.Event {
  40. ok, tev := me.SetupNegotiate(1000, t.TELNET_DO, t.TELNET_TELOPT_NAWS, t.TELNET_WILL_EVENT, t.TELNET_WONT_EVENT)
  41. if (!ok) {
  42. return tev
  43. }
  44. tev2, _, _ := me.TryReadEvent(1000)
  45. if (tev2 == nil) || (!telnet.IsEventType(tev2, t.TELNET_NAWS_EVENT)) {
  46. return tev2
  47. }
  48. nawsevent, ok := tev2.(*telnet.NAWSEvent)
  49. if ok {
  50. me.info.w = nawsevent.W
  51. me.info.h = nawsevent.H
  52. monolog.Info("Client %d window size #{%d}x#{%d}", me.id, me.info.w, me.info.h)
  53. me.info.naws = true
  54. }
  55. return nil
  56. }
  57. func (me * Client) SetupMSSP() telnet.Event {
  58. ok, tev := me.SetupNegotiate(1000, t.TELNET_WILL, t.TELNET_TELOPT_MSSP, t.TELNET_DO_EVENT, t.TELNET_DONT_EVENT)
  59. if (!ok) {
  60. return tev
  61. }
  62. me.telnet.TelnetSendMSSP(MSSP)
  63. monolog.Info("Client %d accepts MSSP", me.id)
  64. me.info.mssp = true
  65. return nil
  66. }
  67. // Check for MXP (html-like) support (but don't implement it yet)
  68. func (me * Client) SetupMXP() telnet.Event {
  69. ok, tev := me.SetupNegotiate(1000, t.TELNET_DO, t.TELNET_TELOPT_MXP, t.TELNET_WILL_EVENT, t.TELNET_WONT_EVENT)
  70. if (!ok) {
  71. return tev
  72. }
  73. monolog.Info("Client %d accepts MXP", me.id)
  74. me.info.mxp = true
  75. return nil
  76. }
  77. // Check for MSP (sound) support (but don't implement it yet)
  78. func (me * Client) SetupMSP() telnet.Event {
  79. ok, tev := me.SetupNegotiate(1000, t.TELNET_DO, t.TELNET_TELOPT_MSP, t.TELNET_WILL_EVENT, t.TELNET_WONT_EVENT)
  80. if (!ok) {
  81. return tev
  82. }
  83. monolog.Info("Client %d accepts MSP", me.id)
  84. me.info.msp = true
  85. return nil
  86. }
  87. // Check for MSDP (two way MSSP) support (but don't implement it yet)
  88. func (me * Client) SetupMSDP() telnet.Event {
  89. ok, tev := me.SetupNegotiate(1000, t.TELNET_WILL, t.TELNET_TELOPT_MSDP, t.TELNET_DO_EVENT, t.TELNET_DONT_EVENT)
  90. if (!ok) {
  91. return tev
  92. }
  93. monolog.Info("Client %d accepts MSDP", me.id)
  94. me.info.msdp = true
  95. return nil
  96. }
  97. func (me * Client) HasTerminal(name string) bool {
  98. monolog.Debug("Client %d supports terminals? %s %v", me.id, name, me.info.terminals)
  99. for index := range me.info.terminals {
  100. if (me.info.terminals[index] == name) {
  101. return true
  102. }
  103. }
  104. return false
  105. }
  106. // Negotiate MTTS/TTYPE (TERMINAL TYPE) support
  107. func (me * Client) SetupTType() telnet.Event {
  108. me.info.terminals = nil
  109. ok, tev := me.SetupNegotiate(1000, t.TELNET_DO, t.TELNET_TELOPT_TTYPE, t.TELNET_WILL_EVENT, t.TELNET_WONT_EVENT)
  110. if (!ok) {
  111. return tev
  112. }
  113. var last string = "none"
  114. var now string = ""
  115. for last != now {
  116. last = now
  117. me.telnet.TelnetTTypeSend()
  118. var tev2 telnet.Event = nil
  119. // Some clients (like KildClient, but not TinTin or telnet),
  120. // insist on spamming useless NUL characters
  121. // here... So we have to retry a few times to get a ttype_is
  122. // throwing away any undesirable junk in between.
  123. GET_TTYPE: for index := 0 ; index < 3 ; index++ {
  124. tev2, _, _ = me.TryReadEvent(1000)
  125. etyp := telnet.EventTypeOf(tev2)
  126. monolog.Info("Waiting for TTYPE: %T %v %d", tev2, tev2, etyp)
  127. if tev2 != nil && telnet.IsEventType(tev2, t.TELNET_TTYPE_EVENT) {
  128. monolog.Info("TTYPE received: %T %v %d", tev2, tev2, etyp)
  129. break GET_TTYPE
  130. }
  131. }
  132. if tev2 == nil || !telnet.IsEventType(tev2, t.TELNET_TTYPE_EVENT) {
  133. etyp := telnet.EventTypeOf(tev2)
  134. monolog.Warning("Received no TTYPE: %T %v %d", tev2, tev2, etyp)
  135. return tev2
  136. }
  137. ttypeevent := tev2.(*telnet.TTypeEvent)
  138. now = ttypeevent.Name
  139. if (!me.HasTerminal(now)) {
  140. me.info.terminals = append(me.info.terminals, now)
  141. }
  142. me.info.terminal = now
  143. }
  144. monolog.Info("Client %d supports terminals %v", me.id, me.info.terminals)
  145. monolog.Info("Client %d active terminal %v", me.id, me.info.terminal)
  146. // MTTS support
  147. for i := range me.info.terminals {
  148. term := me.info.terminals[i]
  149. monolog.Info("Checking MTTS support: %s", term)
  150. if strings.HasPrefix(term, "MTTS ") {
  151. // it's an mtts terminal
  152. strnum := strings.TrimPrefix(term, "MTTS ")
  153. num, err := strconv.Atoi(strnum)
  154. if err == nil {
  155. me.info.mtts = num
  156. monolog.Info("Client %d supports mtts %d", me.id, me.info.mtts)
  157. } else {
  158. monolog.Warning("Client %d could not parse mtts %s %v", me.id, strnum, err)
  159. }
  160. }
  161. }
  162. me.info.ttype = true
  163. return nil
  164. }
  165. func (me * Client) SetupTelnet() {
  166. for {
  167. tev, _, _ := me.TryReadEvent(500)
  168. if tev != nil {
  169. monolog.Info("Client %d telnet setup received: %v", me.id, tev)
  170. } else {
  171. monolog.Info("Client %d no telnet setup received", me.id)
  172. break
  173. }
  174. }
  175. me.SetupMSSP()
  176. // me.SetupCompress2
  177. me.SetupNAWS()
  178. me.SetupTType()
  179. me.SetupMXP()
  180. me.SetupMSP()
  181. me.SetupMSDP()
  182. // me.ColorTest()
  183. }