互动
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.

185 lines
4.4 KiB

5 years ago
5 years ago
5 years ago
  1. package ws
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/rs/zerolog/log"
  6. "gopkg.in/olahol/melody.v1"
  7. "sync"
  8. )
  9. // 根据主活动划分房间 ==> 适配现有的可以
  10. // 在主活动开始的时候
  11. // HandleConnect 处理房间号
  12. // HandleMessage 处理逻辑函数 包括登录, 同步 .... 发送到特定的用户
  13. // HandleDisconnect 处理房间删除, 链接删除
  14. // 登录, 用户注册
  15. // tag 或者 ?activity_id=? 作为一个标志
  16. // 同步消息 => 发送给所有的用户 使用协程池
  17. // NewWebSocket
  18. // Connect
  19. // Disconnect
  20. // Message
  21. // Run
  22. var N = NewNode()
  23. type Node struct {
  24. conns map[*melody.Session]*Client
  25. main *Client // 通过client 发送信息
  26. rooms map[string]*Room // 房间
  27. handles map[string]logic // 逻辑函数
  28. rwmux *sync.RWMutex
  29. }
  30. func NewNode() *Node {
  31. node := new(Node)
  32. node.conns = make(map[*melody.Session]*Client, 0)
  33. node.main = new(Client)
  34. node.rooms = make(map[string]*Room, 0)
  35. node.handles = make(map[string]logic, 0)
  36. node.rwmux = new(sync.RWMutex)
  37. return node
  38. }
  39. func (t *Node) handleMelodyConnect(client *Client) {
  40. log.Printf("[websocket] [ws] [room:%s] [client:%s] %s\n", client.RoomId, client.Id, client.Request.URL)
  41. }
  42. // 处理msg
  43. func (t *Node) handleMelodyMessage(client *Client, msg *Message) {
  44. if !client.Online && msg.Type != TypeLogin {
  45. _ = client.WriteJson(map[string]interface{}{
  46. "msg": "尚未登录",
  47. "code": 504,
  48. })
  49. return
  50. }
  51. if fn, ok := t.handles[msg.Type]; ok {
  52. fn(client, msg)
  53. }
  54. log.Printf("[websocket] [message] [room:%s] [client:%s] %v\n", client.RoomId, client.Id, msg)
  55. }
  56. // 删掉注册的
  57. func (t *Node) handleMelodyDisconnect(client *Client) {
  58. //if client.Online && strings.HasPrefix(client.Id, IDCustomer) {
  59. // if client.Pid == 0 { // 主账号下线 通知子账号
  60. // msg := &Message{
  61. // Type: TypeNotice,
  62. // Dest: 0,
  63. // Tag: IDCustomer,
  64. // RoomId: client.RoomId,
  65. // From: client.Id,
  66. // Data: map[string]interface{}{
  67. // "id": client.AccountId,
  68. // "content": "主账号下线",
  69. // },
  70. // }
  71. // t.Send(msg)
  72. // } else { // 子账号下线 通知主账号
  73. // msg := &Message{
  74. // Type: TypeNotice,
  75. // Dest: client.Pid,
  76. // Tag: IDCustomer,
  77. // RoomId: client.RoomId,
  78. // From: client.Id,
  79. // Data: map[string]interface{}{
  80. // "id": client.AccountId,
  81. // "content": "子账号下线",
  82. // },
  83. // }
  84. // t.Send(msg)
  85. // }
  86. //}
  87. // 释放内存
  88. if room, ok := t.rooms[client.RoomId]; ok {
  89. room.DeleteClient(client.Id)
  90. if room.Len() <= 0 {
  91. t.DeleteRoom(room.Id)
  92. }
  93. }
  94. log.Printf("[websocket] [disconnect] [room:%s] [client:%s] online=>%v\n", client.RoomId, client.Id, client.Online)
  95. }
  96. func (t *Node) SetMiddleware(name string, fn logic) {
  97. t.handles[name] = fn
  98. }
  99. func (t *Node) RegisterClient(c *Client) error {
  100. if room, ok := t.rooms[c.RoomId]; ok {
  101. room.rwmux.Lock()
  102. defer room.rwmux.Unlock()
  103. room.clients[c.Id] = c
  104. return nil
  105. }
  106. return errors.New("加入房间失败")
  107. }
  108. // 所有人同步
  109. func (t *Node) BroadcastAll(msg *Message, c *Client) {
  110. // 发送给连上ws的所有人
  111. m := msg.Encode()
  112. for _, client := range t.conns {
  113. if client == c {
  114. continue
  115. }
  116. _ = client.Write(m)
  117. }
  118. }
  119. func (t *Node) Send(msg *Message) {
  120. if msg.Dest == 0 && msg.Tag == "" { // 代表发送给所有人
  121. t.Broadcast(msg)
  122. } else if msg.Dest == 0 && msg.Tag != "" { // 代表发给某个团体
  123. t.BroadcastTag(msg)
  124. } else if msg.Dest != 0 && msg.Tag != "" {
  125. t.BroadcastDest(msg)
  126. } else {
  127. log.Printf("[websocket] [send] msg=>%v", msg)
  128. }
  129. }
  130. // 发送给所有的
  131. // delete 删除 room client
  132. func (t *Node) Broadcast(msg *Message) {
  133. m := msg.Encode()
  134. if room, ok := t.rooms[msg.RoomId]; ok && room != nil {
  135. for _, client := range room.clients {
  136. if client.Id != msg.From {
  137. _ = client.Write(m)
  138. }
  139. }
  140. }
  141. }
  142. func (t *Node) BroadcastTag(msg *Message) {
  143. m := msg.Encode()
  144. if room, ok := t.rooms[msg.RoomId]; ok {
  145. for _, client := range room.clients {
  146. if client.AccountType == msg.Tag && client.Id != msg.From {
  147. _ = client.Write(m)
  148. }
  149. }
  150. }
  151. }
  152. func (t *Node) BroadcastDest(msg *Message) {
  153. m := msg.Encode()
  154. if room, ok := t.rooms[msg.RoomId]; ok {
  155. client := room.clients[fmt.Sprintf("%s:%d", msg.Tag, msg.Dest)]
  156. if client.Id != msg.From {
  157. _ = client.Write(m)
  158. }
  159. }
  160. }
  161. func (t *Node) DeleteRoom(roomId string) {
  162. t.rwmux.Lock()
  163. defer t.rwmux.Unlock()
  164. delete(t.rooms, roomId)
  165. }