client.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package server
  2. import (
  3. // "fmt"
  4. "net"
  5. "time"
  6. // "errors"
  7. // "io"
  8. "github.com/beoran/woe/monolog"
  9. "github.com/beoran/woe/telnet"
  10. "github.com/beoran/woe/world"
  11. )
  12. /* Specific properties of a client. */
  13. type ClientInfo struct {
  14. w int
  15. h int
  16. mtts int
  17. naws bool
  18. compress2 bool
  19. mssp bool
  20. zmp bool
  21. msp bool
  22. msdp bool
  23. mxp bool
  24. ttype bool
  25. terminals []string
  26. terminal string
  27. }
  28. type Client struct {
  29. server * Server
  30. id int
  31. conn net.Conn
  32. alive bool
  33. timeout int
  34. datachan chan []byte
  35. errchan chan error
  36. timechan chan time.Time
  37. telnet * telnet.Telnet
  38. info ClientInfo
  39. // Account of client or nil if not yet selected.
  40. account* world.Account
  41. // Character client is plaing with or nil if not yet selected.
  42. character * world.Character
  43. }
  44. func NewClient(server * Server, id int, conn net.Conn) * Client {
  45. datachan := make (chan []byte, 1024)
  46. errchan := make (chan error, 1)
  47. timechan := make (chan time.Time, 32)
  48. telnet := telnet.New()
  49. info := ClientInfo{w : -1, h : -1, terminal: "none"}
  50. return &Client{server, id, conn, true, -1, datachan, errchan, timechan, telnet, info, nil, nil}
  51. }
  52. func (me * Client) Close() {
  53. me.conn.Close()
  54. me.alive = false
  55. if me.account != nil {
  56. me.server.World.RemoveAccount(me.account.Name)
  57. }
  58. me.account = nil
  59. }
  60. /** Goroutine that does the actual reading of input data, and sends it to the
  61. * needed channels. */
  62. func (me * Client) ServeRead() {
  63. for (me.alive) {
  64. buffer := make([]byte, 1024, 1024)
  65. read , err := me.conn.Read(buffer);
  66. if err != nil {
  67. me.errchan <- err
  68. return
  69. }
  70. // reply will be stored in me.telnet.Events channel
  71. me.telnet.ProcessBytes(buffer[:read])
  72. }
  73. }
  74. /* Goroutine that sends any data that must be sent through the Telnet protocol
  75. * to the connected client.
  76. */
  77. func (me * Client) ServeWrite() {
  78. for (me.alive) {
  79. select {
  80. case data := <- me.telnet.ToClient:
  81. monolog.Log("SERVEWRITE","Will send to client: %v", data)
  82. me.conn.Write(data)
  83. }
  84. }
  85. }
  86. func (me * Client) TryReadEvent(millis int) (event telnet.Event, timeout bool, close bool) {
  87. var timerchan <-chan(time.Time)
  88. if millis >= 0 {
  89. timerchan = time.Tick(time.Millisecond * time.Duration(millis))
  90. } else {
  91. /* If time is negative, block by using a fake time channel that never gets sent anyting */
  92. timerchan = make(<-chan(time.Time))
  93. }
  94. select {
  95. case event := <- me.telnet.Events:
  96. return event, false, false
  97. case err := <- me.errchan:
  98. monolog.Info("Connection closed: %s\n", err)
  99. me.Close()
  100. return nil, false, true
  101. case _ = <- timerchan:
  102. return nil, true, false
  103. }
  104. }
  105. func (me * Client) HandleNAWSEvent(nawsevent * telnet.NAWSEvent) {
  106. me.info.w = nawsevent.W
  107. me.info.h = nawsevent.H
  108. monolog.Info("Client %d window size #{%d}x#{%d}", me.id, me.info.w, me.info.h)
  109. me.info.naws = true
  110. }
  111. func (me * Client) TryRead(millis int) (data []byte, timeout bool, close bool) {
  112. for (me.alive) {
  113. event, timeout, close := me.TryReadEvent(millis)
  114. if event == nil && (timeout || close) {
  115. return nil, timeout, close
  116. }
  117. switch event := event.(type) {
  118. case * telnet.DataEvent:
  119. monolog.Log("TELNETDATAEVENT", "Telnet data event %T : %d.", event, len(event.Data))
  120. return event.Data, false, false
  121. case * telnet.NAWSEvent:
  122. monolog.Log("TELNETNAWSEVENT", "Telnet NAWS event %T.", event)
  123. me.HandleNAWSEvent(event);
  124. default:
  125. monolog.Info("Ignoring telnet event %T : %v for now.", event, event)
  126. }
  127. }
  128. return nil, false, true
  129. }
  130. func (me * Client) Serve() (err error) {
  131. // buffer := make([]byte, 1024, 1024)
  132. go me.ServeWrite()
  133. go me.ServeRead()
  134. me.SetupTelnet()
  135. if me.server.World != nil {
  136. me.Printf(me.server.World.MOTD)
  137. }
  138. if (!me.AccountDialog()) {
  139. time.Sleep(3);
  140. // sleep so output gets flushed, hopefully.
  141. // Also slow down brute force attacks.
  142. me.Close()
  143. return nil
  144. }
  145. if (!me.CharacterDialog()) {
  146. time.Sleep(3);
  147. // sleep so output gets flushed, hopefully.
  148. // Also slow down brute force attacks.
  149. me.Close()
  150. return nil
  151. }
  152. me.Printf("Welcome, %s\n", me.account.Name)
  153. for (me.alive) {
  154. me.HandleCommand()
  155. /*
  156. data, _, _ := me.TryRead(3000)
  157. if data == nil {
  158. // me.telnet.TelnetPrintf("Too late!\r\n")
  159. } else {
  160. me.server.Broadcast(string(data))
  161. }
  162. */
  163. }
  164. return nil
  165. }
  166. func (me * Client) Disconnect() {
  167. me.alive = false
  168. }
  169. func (me * Client) IsAlive() bool {
  170. return me.alive
  171. }
  172. func (me * Client) WriteString(str string) {
  173. me.conn.Write([]byte(str))
  174. }
  175. /** Accessor */
  176. func (me * Client) GetServer() (* Server) {
  177. return me.server;
  178. }
  179. /** Accessor */
  180. func (me * Client) GetWorld() (* world.World) {
  181. return me.server.World;
  182. }
  183. /** Accessor */
  184. func (me * Client) GetAccount() (* world.Account) {
  185. return me.account;
  186. }