|
@@ -12,25 +12,24 @@ import (
|
12
|
12
|
// MonitorManager keeps track of who's monitoring which nicks.
|
13
|
13
|
type MonitorManager struct {
|
14
|
14
|
sync.RWMutex // tier 2
|
15
|
|
- // client -> nicks it's watching
|
16
|
|
- watching map[*Client]map[string]bool
|
17
|
|
- // nick -> clients watching it
|
18
|
|
- watchedby map[string]map[*Client]bool
|
19
|
|
- // (all nicks must be normalized externally by casefolding)
|
|
15
|
+ // client -> (casefolded nick it's watching -> uncasefolded nick)
|
|
16
|
+ watching map[*Session]map[string]string
|
|
17
|
+ // casefolded nick -> clients watching it
|
|
18
|
+ watchedby map[string]map[*Session]empty
|
20
|
19
|
}
|
21
|
20
|
|
22
|
21
|
func (mm *MonitorManager) Initialize() {
|
23
|
|
- mm.watching = make(map[*Client]map[string]bool)
|
24
|
|
- mm.watchedby = make(map[string]map[*Client]bool)
|
|
22
|
+ mm.watching = make(map[*Session]map[string]string)
|
|
23
|
+ mm.watchedby = make(map[string]map[*Session]empty)
|
25
|
24
|
}
|
26
|
25
|
|
27
|
26
|
// AlertAbout alerts everyone monitoring `client`'s nick that `client` is now {on,off}line.
|
28
|
27
|
func (manager *MonitorManager) AlertAbout(nick, cfnick string, online bool) {
|
29
|
|
- var watchers []*Client
|
|
28
|
+ var watchers []*Session
|
30
|
29
|
// safely copy the list of clients watching our nick
|
31
|
30
|
manager.RLock()
|
32
|
|
- for client := range manager.watchedby[cfnick] {
|
33
|
|
- watchers = append(watchers, client)
|
|
31
|
+ for session := range manager.watchedby[cfnick] {
|
|
32
|
+ watchers = append(watchers, session)
|
34
|
33
|
}
|
35
|
34
|
manager.RUnlock()
|
36
|
35
|
|
|
@@ -39,58 +38,67 @@ func (manager *MonitorManager) AlertAbout(nick, cfnick string, online bool) {
|
39
|
38
|
command = RPL_MONONLINE
|
40
|
39
|
}
|
41
|
40
|
|
42
|
|
- for _, mClient := range watchers {
|
43
|
|
- mClient.Send(nil, mClient.server.name, command, mClient.Nick(), nick)
|
|
41
|
+ for _, session := range watchers {
|
|
42
|
+ session.Send(nil, session.client.server.name, command, session.client.Nick(), nick)
|
44
|
43
|
}
|
45
|
44
|
}
|
46
|
45
|
|
47
|
46
|
// Add registers `client` to receive notifications about `nick`.
|
48
|
|
-func (manager *MonitorManager) Add(client *Client, nick string, limit int) error {
|
|
47
|
+func (manager *MonitorManager) Add(session *Session, nick string, limit int) error {
|
|
48
|
+ cfnick, err := CasefoldName(nick)
|
|
49
|
+ if err != nil {
|
|
50
|
+ return err
|
|
51
|
+ }
|
|
52
|
+
|
49
|
53
|
manager.Lock()
|
50
|
54
|
defer manager.Unlock()
|
51
|
55
|
|
52
|
|
- if manager.watching[client] == nil {
|
53
|
|
- manager.watching[client] = make(map[string]bool)
|
|
56
|
+ if manager.watching[session] == nil {
|
|
57
|
+ manager.watching[session] = make(map[string]string)
|
54
|
58
|
}
|
55
|
|
- if manager.watchedby[nick] == nil {
|
56
|
|
- manager.watchedby[nick] = make(map[*Client]bool)
|
|
59
|
+ if manager.watchedby[cfnick] == nil {
|
|
60
|
+ manager.watchedby[cfnick] = make(map[*Session]empty)
|
57
|
61
|
}
|
58
|
62
|
|
59
|
|
- if len(manager.watching[client]) >= limit {
|
|
63
|
+ if len(manager.watching[session]) >= limit {
|
60
|
64
|
return errMonitorLimitExceeded
|
61
|
65
|
}
|
62
|
66
|
|
63
|
|
- manager.watching[client][nick] = true
|
64
|
|
- manager.watchedby[nick][client] = true
|
|
67
|
+ manager.watching[session][cfnick] = nick
|
|
68
|
+ manager.watchedby[cfnick][session] = empty{}
|
65
|
69
|
return nil
|
66
|
70
|
}
|
67
|
71
|
|
68
|
72
|
// Remove unregisters `client` from receiving notifications about `nick`.
|
69
|
|
-func (manager *MonitorManager) Remove(client *Client, nick string) error {
|
|
73
|
+func (manager *MonitorManager) Remove(session *Session, nick string) (err error) {
|
|
74
|
+ cfnick, err := CasefoldName(nick)
|
|
75
|
+ if err != nil {
|
|
76
|
+ return
|
|
77
|
+ }
|
|
78
|
+
|
70
|
79
|
manager.Lock()
|
71
|
80
|
defer manager.Unlock()
|
72
|
|
- // deleting from nil maps is fine
|
73
|
|
- delete(manager.watching[client], nick)
|
74
|
|
- delete(manager.watchedby[nick], client)
|
|
81
|
+ delete(manager.watching[session], cfnick)
|
|
82
|
+ delete(manager.watchedby[cfnick], session)
|
75
|
83
|
return nil
|
76
|
84
|
}
|
77
|
85
|
|
78
|
86
|
// RemoveAll unregisters `client` from receiving notifications about *all* nicks.
|
79
|
|
-func (manager *MonitorManager) RemoveAll(client *Client) {
|
|
87
|
+func (manager *MonitorManager) RemoveAll(session *Session) {
|
80
|
88
|
manager.Lock()
|
81
|
89
|
defer manager.Unlock()
|
82
|
90
|
|
83
|
|
- for nick := range manager.watching[client] {
|
84
|
|
- delete(manager.watchedby[nick], client)
|
|
91
|
+ for cfnick := range manager.watching[session] {
|
|
92
|
+ delete(manager.watchedby[cfnick], session)
|
85
|
93
|
}
|
86
|
|
- delete(manager.watching, client)
|
|
94
|
+ delete(manager.watching, session)
|
87
|
95
|
}
|
88
|
96
|
|
89
|
97
|
// List lists all nicks that `client` is registered to receive notifications about.
|
90
|
|
-func (manager *MonitorManager) List(client *Client) (nicks []string) {
|
|
98
|
+func (manager *MonitorManager) List(session *Session) (nicks []string) {
|
91
|
99
|
manager.RLock()
|
92
|
100
|
defer manager.RUnlock()
|
93
|
|
- for nick := range manager.watching[client] {
|
|
101
|
+ for _, nick := range manager.watching[session] {
|
94
|
102
|
nicks = append(nicks, nick)
|
95
|
103
|
}
|
96
|
104
|
return nicks
|