1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
l4g "code.google.com/p/log4go"
"github.com/mattermost/platform/model"
)
type TeamHub struct {
connections map[*WebConn]bool
broadcast chan *model.Message
register chan *WebConn
unregister chan *WebConn
stop chan bool
teamId string
}
func NewTeamHub(teamId string) *TeamHub {
return &TeamHub{
broadcast: make(chan *model.Message),
register: make(chan *WebConn),
unregister: make(chan *WebConn),
connections: make(map[*WebConn]bool),
stop: make(chan bool),
teamId: teamId,
}
}
func (h *TeamHub) Register(webConn *WebConn) {
h.register <- webConn
}
func (h *TeamHub) Unregister(webConn *WebConn) {
h.unregister <- webConn
}
func (h *TeamHub) Stop() {
h.stop <- true
}
func (h *TeamHub) Start() {
go func() {
for {
select {
case webCon := <-h.register:
h.connections[webCon] = true
case webCon := <-h.unregister:
if _, ok := h.connections[webCon]; ok {
delete(h.connections, webCon)
close(webCon.Send)
}
case msg := <-h.broadcast:
for webCon := range h.connections {
if ShouldSendEvent(webCon, msg) {
select {
case webCon.Send <- msg:
default:
close(webCon.Send)
delete(h.connections, webCon)
}
}
}
case s := <-h.stop:
if s {
l4g.Debug("team hub stopping for teamId=%v", h.teamId)
for webCon := range h.connections {
webCon.WebSocket.Close()
}
return
}
}
}
}()
}
func (h *TeamHub) UpdateChannelAccessCache(userId string, channelId string) {
for webCon := range h.connections {
if webCon.UserId == userId {
webCon.updateChannelAccessCache(channelId)
break
}
}
}
func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool {
if webCon.UserId == msg.UserId {
// Don't need to tell the user they are typing
if msg.Action == model.ACTION_TYPING {
return false
}
} else {
// Don't share a user's view events with other users
if msg.Action == model.ACTION_CHANNEL_VIEWED {
return false
}
// Only report events to a user who is the subject of the event, or is in the channel of the event
if len(msg.ChannelId) > 0 {
allowed, ok := webCon.ChannelAccessCache[msg.ChannelId]
if !ok {
allowed = webCon.updateChannelAccessCache(msg.ChannelId)
}
if !allowed {
return false
}
}
}
return true
}
|