|
@@ -68,11 +68,23 @@ func NewChannel(s *Server, name string, addDefaultModes bool) *Channel {
|
68
|
68
|
func (channel *Channel) IsEmpty() bool {
|
69
|
69
|
channel.membersMutex.RLock()
|
70
|
70
|
defer channel.membersMutex.RUnlock()
|
|
71
|
+
|
|
72
|
+ return channel.isEmptyNoMutex()
|
|
73
|
+}
|
|
74
|
+
|
|
75
|
+func (channel *Channel) isEmptyNoMutex() bool {
|
71
|
76
|
return len(channel.members) == 0
|
72
|
77
|
}
|
73
|
78
|
|
74
|
79
|
func (channel *Channel) Names(client *Client) {
|
75
|
|
- currentNicks := channel.Nicks(client)
|
|
80
|
+ channel.membersMutex.RLock()
|
|
81
|
+ defer channel.membersMutex.RUnlock()
|
|
82
|
+
|
|
83
|
+ channel.namesNoMutex(client)
|
|
84
|
+}
|
|
85
|
+
|
|
86
|
+func (channel *Channel) namesNoMutex(client *Client) {
|
|
87
|
+ currentNicks := channel.nicksNoMutex(client)
|
76
|
88
|
// assemble and send replies
|
77
|
89
|
maxNamLen := 480 - len(client.server.name) - len(client.nick)
|
78
|
90
|
var buffer string
|
|
@@ -101,6 +113,12 @@ func (channel *Channel) ClientIsAtLeast(client *Client, permission ChannelMode)
|
101
|
113
|
channel.membersMutex.RLock()
|
102
|
114
|
defer channel.membersMutex.RUnlock()
|
103
|
115
|
|
|
116
|
+ return channel.clientIsAtLeastNoMutex(client, permission)
|
|
117
|
+}
|
|
118
|
+
|
|
119
|
+func (channel *Channel) clientIsAtLeastNoMutex(client *Client, permission ChannelMode) bool {
|
|
120
|
+ // requires RLock()
|
|
121
|
+
|
104
|
122
|
// get voice, since it's not a part of ChannelPrivModes
|
105
|
123
|
if channel.members.HasMode(client, permission) {
|
106
|
124
|
return true
|
|
@@ -141,10 +159,7 @@ func (modes ChannelModeSet) Prefixes(isMultiPrefix bool) string {
|
141
|
159
|
return prefixes
|
142
|
160
|
}
|
143
|
161
|
|
144
|
|
-func (channel *Channel) Nicks(target *Client) []string {
|
145
|
|
- channel.membersMutex.RLock()
|
146
|
|
- defer channel.membersMutex.RUnlock()
|
147
|
|
-
|
|
162
|
+func (channel *Channel) nicksNoMutex(target *Client) []string {
|
148
|
163
|
isMultiPrefix := (target != nil) && target.capabilities[MultiPrefix]
|
149
|
164
|
isUserhostInNames := (target != nil) && target.capabilities[UserhostInNames]
|
150
|
165
|
nicks := make([]string, len(channel.members))
|
|
@@ -218,12 +233,11 @@ func (channel *Channel) CheckKey(key string) bool {
|
218
|
233
|
|
219
|
234
|
func (channel *Channel) Join(client *Client, key string) {
|
220
|
235
|
channel.membersMutex.Lock()
|
221
|
|
- defer channel.membersMutex.Unlock()
|
222
|
|
-
|
223
|
236
|
if channel.members.Has(client) {
|
224
|
237
|
// already joined, no message?
|
225
|
238
|
return
|
226
|
239
|
}
|
|
240
|
+ channel.membersMutex.Unlock()
|
227
|
241
|
|
228
|
242
|
if channel.IsFull() {
|
229
|
243
|
client.Send(nil, client.server.name, ERR_CHANNELISFULL, channel.name, "Cannot join channel (+l)")
|
|
@@ -241,6 +255,8 @@ func (channel *Channel) Join(client *Client, key string) {
|
241
|
255
|
return
|
242
|
256
|
}
|
243
|
257
|
|
|
258
|
+ channel.membersMutex.Lock()
|
|
259
|
+ defer channel.membersMutex.Unlock()
|
244
|
260
|
if channel.lists[BanMask].Match(client.nickMaskCasefolded) &&
|
245
|
261
|
!isInvited &&
|
246
|
262
|
!channel.lists[ExceptMask].Match(client.nickMaskCasefolded) {
|
|
@@ -270,8 +286,8 @@ func (channel *Channel) Join(client *Client, key string) {
|
270
|
286
|
} else {
|
271
|
287
|
client.Send(nil, client.nickMaskString, "JOIN", channel.name)
|
272
|
288
|
}
|
273
|
|
- channel.GetTopic(client)
|
274
|
|
- channel.Names(client)
|
|
289
|
+ channel.getTopicNoMutex(client) // we already have Lock
|
|
290
|
+ channel.namesNoMutex(client)
|
275
|
291
|
}
|
276
|
292
|
|
277
|
293
|
func (channel *Channel) Part(client *Client, message string) {
|
|
@@ -293,6 +309,10 @@ func (channel *Channel) GetTopic(client *Client) {
|
293
|
309
|
channel.membersMutex.RLock()
|
294
|
310
|
defer channel.membersMutex.RUnlock()
|
295
|
311
|
|
|
312
|
+ channel.getTopicNoMutex(client)
|
|
313
|
+}
|
|
314
|
+
|
|
315
|
+func (channel *Channel) getTopicNoMutex(client *Client) {
|
296
|
316
|
if !channel.members.Has(client) {
|
297
|
317
|
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, client.nick, channel.name, "You're not on that channel")
|
298
|
318
|
return
|
|
@@ -507,23 +527,26 @@ func (channel *Channel) Quit(client *Client) {
|
507
|
527
|
channel.membersMutex.Lock()
|
508
|
528
|
defer channel.membersMutex.Unlock()
|
509
|
529
|
|
|
530
|
+ channel.quitNoMutex(client)
|
|
531
|
+}
|
|
532
|
+
|
|
533
|
+func (channel *Channel) quitNoMutex(client *Client) {
|
510
|
534
|
channel.members.Remove(client)
|
511
|
535
|
client.channels.Remove(channel)
|
512
|
536
|
|
513
|
|
- if channel.IsEmpty() {
|
|
537
|
+ if channel.isEmptyNoMutex() {
|
514
|
538
|
channel.server.channels.Remove(channel)
|
515
|
539
|
}
|
516
|
540
|
}
|
517
|
541
|
|
518
|
|
-func (channel *Channel) Kick(client *Client, target *Client, comment string) {
|
519
|
|
- channel.membersMutex.Lock()
|
520
|
|
- defer channel.membersMutex.Unlock()
|
|
542
|
+func (channel *Channel) kickNoMutex(client *Client, target *Client, comment string) {
|
|
543
|
+ // needs a Lock()
|
521
|
544
|
|
522
|
545
|
if !(client.flags[Operator] || channel.members.Has(client)) {
|
523
|
546
|
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
|
524
|
547
|
return
|
525
|
548
|
}
|
526
|
|
- if !channel.ClientIsAtLeast(client, ChannelOperator) {
|
|
549
|
+ if !channel.clientIsAtLeastNoMutex(client, ChannelOperator) {
|
527
|
550
|
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
|
528
|
551
|
return
|
529
|
552
|
}
|
|
@@ -539,7 +562,7 @@ func (channel *Channel) Kick(client *Client, target *Client, comment string) {
|
539
|
562
|
for member := range channel.members {
|
540
|
563
|
member.Send(nil, client.nickMaskString, "KICK", channel.name, target.nick, comment)
|
541
|
564
|
}
|
542
|
|
- channel.Quit(target)
|
|
565
|
+ channel.quitNoMutex(target)
|
543
|
566
|
}
|
544
|
567
|
|
545
|
568
|
func (channel *Channel) Invite(invitee *Client, inviter *Client) {
|