ws_conn.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package network
  2. import (
  3. "errors"
  4. "net"
  5. "sync"
  6. "leafstalk/log"
  7. "leafstalk/otherutils"
  8. "github.com/gorilla/websocket"
  9. )
  10. type WebsocketConnSet map[*websocket.Conn]struct{}
  11. type WSConn struct {
  12. sync.Mutex
  13. conn *websocket.Conn
  14. writeChan chan []byte
  15. maxMsgLen uint32
  16. closeFlag bool
  17. ip string
  18. }
  19. func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32) *WSConn {
  20. wsConn := new(WSConn)
  21. wsConn.conn = conn
  22. wsConn.writeChan = make(chan []byte, pendingWriteNum)
  23. wsConn.maxMsgLen = maxMsgLen
  24. go func() {
  25. for b := range wsConn.writeChan {
  26. if b == nil {
  27. break
  28. }
  29. b = EncryptByXxtea(b)
  30. err := conn.WriteMessage(websocket.BinaryMessage, b)
  31. if err != nil {
  32. break
  33. }
  34. }
  35. conn.Close()
  36. wsConn.Lock()
  37. wsConn.closeFlag = true
  38. wsConn.Unlock()
  39. }()
  40. return wsConn
  41. }
  42. func (wsConn *WSConn) doDestroy() {
  43. // wsConn.conn.UnderlyingConn().(*tls.Conn).SetLinger(0)
  44. // wsConn.conn.UnderlyingConn()
  45. wsConn.conn.Close()
  46. if !wsConn.closeFlag {
  47. close(wsConn.writeChan)
  48. wsConn.closeFlag = true
  49. }
  50. }
  51. func (wsConn *WSConn) Destroy() {
  52. wsConn.Lock()
  53. defer wsConn.Unlock()
  54. wsConn.doDestroy()
  55. }
  56. func (wsConn *WSConn) Close() {
  57. wsConn.Lock()
  58. defer wsConn.Unlock()
  59. if wsConn.closeFlag {
  60. return
  61. }
  62. wsConn.doWrite(nil)
  63. wsConn.closeFlag = true
  64. }
  65. func (wsConn *WSConn) doWrite(b []byte) {
  66. if len(wsConn.writeChan) == cap(wsConn.writeChan) {
  67. log.Debug("close conn: channel full")
  68. wsConn.doDestroy()
  69. return
  70. }
  71. wsConn.writeChan <- b
  72. }
  73. func (wsConn *WSConn) LocalAddr() net.Addr {
  74. return wsConn.conn.LocalAddr()
  75. }
  76. func (wsConn *WSConn) RemoteAddr() net.Addr {
  77. if len(wsConn.ip) > 0 {
  78. ip, err := net.ResolveIPAddr("ip", wsConn.ip)
  79. if err == nil {
  80. return ip
  81. }
  82. }
  83. return wsConn.conn.RemoteAddr()
  84. }
  85. // goroutine not safe
  86. func (wsConn *WSConn) ReadMsg() ([]byte, error) {
  87. _, b, err := wsConn.conn.ReadMessage()
  88. //log.Debugf("ReadMsg len %d", len(b))
  89. if b != nil {
  90. b = DecryptByXxtea(b)
  91. }
  92. return b, err
  93. }
  94. // args must not be modified by the others goroutines
  95. func (wsConn *WSConn) WriteMsg(args ...[]byte) error {
  96. wsConn.Lock()
  97. defer wsConn.Unlock()
  98. if wsConn.closeFlag {
  99. return nil
  100. }
  101. // get len
  102. var msgLen uint32
  103. for i := 0; i < len(args); i++ {
  104. msgLen += uint32(len(args[i]))
  105. }
  106. // check len
  107. if msgLen > wsConn.maxMsgLen {
  108. return errors.New("message too long")
  109. } else if msgLen < 1 {
  110. return errors.New("message too short")
  111. }
  112. // don't copy
  113. if len(args) == 1 {
  114. wsConn.doWrite(args[0])
  115. return nil
  116. }
  117. // merge the args
  118. msg := make([]byte, msgLen)
  119. l := 0
  120. for i := 0; i < len(args); i++ {
  121. copy(msg[l:], args[i])
  122. l += len(args[i])
  123. }
  124. wsConn.doWrite(msg)
  125. return nil
  126. }
  127. var (
  128. XXTEA_KEY = "covenant"
  129. )
  130. func SetXxteaPass(pass string) {
  131. XXTEA_KEY = pass
  132. }
  133. // 加密方法
  134. func EncryptByXxtea(data []byte) []byte {
  135. // return data
  136. return otherutils.Encrypt(data, []byte(XXTEA_KEY))
  137. }
  138. // 解密方法
  139. func DecryptByXxtea(data []byte) []byte {
  140. // return data
  141. return otherutils.Decrypt(data, []byte(XXTEA_KEY))
  142. }