websocket 增加多分组 fork https://github.com/olahol/melody
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
4.8 KiB

10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package melody
  2. import (
  3. "errors"
  4. "github.com/gorilla/websocket"
  5. "net/http"
  6. "sync"
  7. )
  8. type handleMessageFunc func(*Session, []byte)
  9. type handleErrorFunc func(*Session, error)
  10. type handleSessionFunc func(*Session)
  11. type filterFunc func(*Session) bool
  12. // Melody implements a websocket manager.
  13. type Melody struct {
  14. Config *Config
  15. Upgrader *websocket.Upgrader
  16. messageHandler handleMessageFunc
  17. messageHandlerBinary handleMessageFunc
  18. errorHandler handleErrorFunc
  19. connectHandler handleSessionFunc
  20. disconnectHandler handleSessionFunc
  21. pongHandler handleSessionFunc
  22. hub *hub
  23. }
  24. // New creates a new melody instance with default Upgrader and Config.
  25. func New() *Melody {
  26. upgrader := &websocket.Upgrader{
  27. ReadBufferSize: 1024,
  28. WriteBufferSize: 1024,
  29. }
  30. hub := newHub()
  31. go hub.run()
  32. return &Melody{
  33. Config: newConfig(),
  34. Upgrader: upgrader,
  35. messageHandler: func(*Session, []byte) {},
  36. messageHandlerBinary: func(*Session, []byte) {},
  37. errorHandler: func(*Session, error) {},
  38. connectHandler: func(*Session) {},
  39. disconnectHandler: func(*Session) {},
  40. pongHandler: func(*Session) {},
  41. hub: hub,
  42. }
  43. }
  44. // HandleConnect fires fn when a session connects.
  45. func (m *Melody) HandleConnect(fn func(*Session)) {
  46. m.connectHandler = fn
  47. }
  48. // HandleDisconnect fires fn when a session disconnects.
  49. func (m *Melody) HandleDisconnect(fn func(*Session)) {
  50. m.disconnectHandler = fn
  51. }
  52. // HandlePong fires fn when a pong is received from a session.
  53. func (m *Melody) HandlePong(fn func(*Session)) {
  54. m.pongHandler = fn
  55. }
  56. // HandleMessage fires fn when a text message comes in.
  57. func (m *Melody) HandleMessage(fn func(*Session, []byte)) {
  58. m.messageHandler = fn
  59. }
  60. // HandleMessageBinary fires fn when a binary message comes in.
  61. func (m *Melody) HandleMessageBinary(fn func(*Session, []byte)) {
  62. m.messageHandlerBinary = fn
  63. }
  64. // HandleError fires fn when a session has an error.
  65. func (m *Melody) HandleError(fn func(*Session, error)) {
  66. m.errorHandler = fn
  67. }
  68. // HandleRequest upgrades http requests to websocket connections and dispatches them to be handled by the melody instance.
  69. func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) error {
  70. if m.hub.closed() {
  71. return errors.New("Melody instance is closed.")
  72. }
  73. conn, err := m.Upgrader.Upgrade(w, r, nil)
  74. if err != nil {
  75. return err
  76. }
  77. session := &Session{
  78. Request: r,
  79. Keys: nil,
  80. conn: conn,
  81. output: make(chan *envelope, m.Config.MessageBufferSize),
  82. melody: m,
  83. open: true,
  84. rwmutex: &sync.RWMutex{},
  85. }
  86. m.hub.register <- session
  87. m.connectHandler(session)
  88. go session.writePump()
  89. session.readPump()
  90. if !m.hub.closed() {
  91. m.hub.unregister <- session
  92. }
  93. session.close()
  94. m.disconnectHandler(session)
  95. return nil
  96. }
  97. // Broadcast broadcasts a text message to all sessions.
  98. func (m *Melody) Broadcast(msg []byte) error {
  99. if m.hub.closed() {
  100. return errors.New("Melody instance is closed.")
  101. }
  102. message := &envelope{t: websocket.TextMessage, msg: msg}
  103. m.hub.broadcast <- message
  104. return nil
  105. }
  106. // BroadcastFilter broadcasts a text message to all sessions that fn returns true for.
  107. func (m *Melody) BroadcastFilter(msg []byte, fn func(*Session) bool) error {
  108. if m.hub.closed() {
  109. return errors.New("Melody instance is closed.")
  110. }
  111. message := &envelope{t: websocket.TextMessage, msg: msg, filter: fn}
  112. m.hub.broadcast <- message
  113. return nil
  114. }
  115. // BroadcastOthers broadcasts a text message to all sessions except session s.
  116. func (m *Melody) BroadcastOthers(msg []byte, s *Session) error {
  117. return m.BroadcastFilter(msg, func(q *Session) bool {
  118. return s != q
  119. })
  120. }
  121. // BroadcastBinary broadcasts a binary message to all sessions.
  122. func (m *Melody) BroadcastBinary(msg []byte) error {
  123. if m.hub.closed() {
  124. return errors.New("Melody instance is closed.")
  125. }
  126. message := &envelope{t: websocket.BinaryMessage, msg: msg}
  127. m.hub.broadcast <- message
  128. return nil
  129. }
  130. // BroadcastBinaryFilter broadcasts a binary message to all sessions that fn returns true for.
  131. func (m *Melody) BroadcastBinaryFilter(msg []byte, fn func(*Session) bool) error {
  132. if m.hub.closed() {
  133. return errors.New("Melody instance is closed.")
  134. }
  135. message := &envelope{t: websocket.BinaryMessage, msg: msg, filter: fn}
  136. m.hub.broadcast <- message
  137. return nil
  138. }
  139. // BroadcastBinaryOthers broadcasts a binary message to all sessions except session s.
  140. func (m *Melody) BroadcastBinaryOthers(msg []byte, s *Session) error {
  141. return m.BroadcastBinaryFilter(msg, func(q *Session) bool {
  142. return s != q
  143. })
  144. }
  145. // Close closes the melody instance and all connected sessions.
  146. func (m *Melody) Close() error {
  147. if m.hub.closed() {
  148. return errors.New("Melody instance is already closed.")
  149. }
  150. m.hub.exit <- true
  151. return nil
  152. }
  153. // Len return the number of connected sessions.
  154. func (m *Melody) Len() int {
  155. return m.hub.len()
  156. }