Bläddra i källkod

channel: RWMutex for members access

tags/v0.6.0
Daniel Oaks 7 år sedan
förälder
incheckning
6f7c683247
5 ändrade filer med 69 tillägg och 0 borttagningar
  1. 47
    0
      irc/channel.go
  2. 2
    0
      irc/client.go
  3. 3
    0
      irc/modes.go
  4. 2
    0
      irc/roleplay.go
  5. 15
    0
      irc/server.go

+ 47
- 0
irc/channel.go Visa fil

@@ -11,6 +11,8 @@ import (
11 11
 	"strconv"
12 12
 	"time"
13 13
 
14
+	"sync"
15
+
14 16
 	"github.com/DanielOaks/girc-go/ircmsg"
15 17
 )
16 18
 
@@ -18,6 +20,7 @@ type Channel struct {
18 20
 	flags          ChannelModeSet
19 21
 	lists          map[ChannelMode]*UserMaskSet
20 22
 	key            string
23
+	membersMutex   sync.RWMutex
21 24
 	members        MemberSet
22 25
 	name           string
23 26
 	nameCasefolded string
@@ -63,6 +66,8 @@ func NewChannel(s *Server, name string, addDefaultModes bool) *Channel {
63 66
 }
64 67
 
65 68
 func (channel *Channel) IsEmpty() bool {
69
+	channel.membersMutex.RLock()
70
+	defer channel.membersMutex.RUnlock()
66 71
 	return len(channel.members) == 0
67 72
 }
68 73
 
@@ -93,6 +98,9 @@ func (channel *Channel) Names(client *Client) {
93 98
 
94 99
 // ClientIsAtLeast returns whether the client has at least the given channel privilege.
95 100
 func (channel *Channel) ClientIsAtLeast(client *Client, permission ChannelMode) bool {
101
+	channel.membersMutex.RLock()
102
+	defer channel.membersMutex.RUnlock()
103
+
96 104
 	// get voice, since it's not a part of ChannelPrivModes
97 105
 	if channel.members.HasMode(client, permission) {
98 106
 		return true
@@ -134,6 +142,9 @@ func (modes ChannelModeSet) Prefixes(isMultiPrefix bool) string {
134 142
 }
135 143
 
136 144
 func (channel *Channel) Nicks(target *Client) []string {
145
+	channel.membersMutex.RLock()
146
+	defer channel.membersMutex.RUnlock()
147
+
137 148
 	isMultiPrefix := (target != nil) && target.capabilities[MultiPrefix]
138 149
 	isUserhostInNames := (target != nil) && target.capabilities[UserhostInNames]
139 150
 	nicks := make([]string, len(channel.members))
@@ -160,7 +171,9 @@ func (channel *Channel) Nick() string {
160 171
 
161 172
 // <mode> <mode params>
162 173
 func (channel *Channel) ModeString(client *Client) (str string) {
174
+	channel.membersMutex.RLock()
163 175
 	isMember := client.flags[Operator] || channel.members.Has(client)
176
+	channel.membersMutex.RUnlock()
164 177
 	showKey := isMember && (channel.key != "")
165 178
 	showUserLimit := channel.userLimit > 0
166 179
 
@@ -192,6 +205,9 @@ func (channel *Channel) ModeString(client *Client) (str string) {
192 205
 }
193 206
 
194 207
 func (channel *Channel) IsFull() bool {
208
+	channel.membersMutex.RLock()
209
+	defer channel.membersMutex.RUnlock()
210
+
195 211
 	return (channel.userLimit > 0) &&
196 212
 		(uint64(len(channel.members)) >= channel.userLimit)
197 213
 }
@@ -201,6 +217,9 @@ func (channel *Channel) CheckKey(key string) bool {
201 217
 }
202 218
 
203 219
 func (channel *Channel) Join(client *Client, key string) {
220
+	channel.membersMutex.Lock()
221
+	defer channel.membersMutex.Unlock()
222
+
204 223
 	if channel.members.Has(client) {
205 224
 		// already joined, no message?
206 225
 		return
@@ -256,6 +275,9 @@ func (channel *Channel) Join(client *Client, key string) {
256 275
 }
257 276
 
258 277
 func (channel *Channel) Part(client *Client, message string) {
278
+	channel.membersMutex.RLock()
279
+	defer channel.membersMutex.RUnlock()
280
+
259 281
 	if !channel.members.Has(client) {
260 282
 		client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
261 283
 		return
@@ -268,6 +290,9 @@ func (channel *Channel) Part(client *Client, message string) {
268 290
 }
269 291
 
270 292
 func (channel *Channel) GetTopic(client *Client) {
293
+	channel.membersMutex.RLock()
294
+	defer channel.membersMutex.RUnlock()
295
+
271 296
 	if !channel.members.Has(client) {
272 297
 		client.Send(nil, client.server.name, ERR_NOTONCHANNEL, client.nick, channel.name, "You're not on that channel")
273 298
 		return
@@ -283,6 +308,9 @@ func (channel *Channel) GetTopic(client *Client) {
283 308
 }
284 309
 
285 310
 func (channel *Channel) SetTopic(client *Client, topic string) {
311
+	channel.membersMutex.RLock()
312
+	defer channel.membersMutex.RUnlock()
313
+
286 314
 	if !(client.flags[Operator] || channel.members.Has(client)) {
287 315
 		client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
288 316
 		return
@@ -307,6 +335,9 @@ func (channel *Channel) SetTopic(client *Client, topic string) {
307 335
 }
308 336
 
309 337
 func (channel *Channel) CanSpeak(client *Client) bool {
338
+	channel.membersMutex.RLock()
339
+	defer channel.membersMutex.RUnlock()
340
+
310 341
 	if client.flags[Operator] {
311 342
 		return true
312 343
 	}
@@ -335,6 +366,10 @@ func (channel *Channel) sendMessage(cmd string, minPrefix *ChannelMode, clientOn
335 366
 		client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
336 367
 		return
337 368
 	}
369
+
370
+	channel.membersMutex.RLock()
371
+	defer channel.membersMutex.RUnlock()
372
+
338 373
 	// for STATUSMSG
339 374
 	var minPrefixMode ChannelMode
340 375
 	if minPrefix != nil {
@@ -383,6 +418,9 @@ func (channel *Channel) applyModeFlag(client *Client, mode ChannelMode,
383 418
 
384 419
 func (channel *Channel) applyModeMember(client *Client, mode ChannelMode,
385 420
 	op ModeOp, nick string) *ChannelModeChange {
421
+	channel.membersMutex.Lock()
422
+	defer channel.membersMutex.Unlock()
423
+
386 424
 	if nick == "" {
387 425
 		//TODO(dan): shouldn't this be handled before it reaches this function?
388 426
 		client.Send(nil, client.server.name, ERR_NEEDMOREPARAMS, "MODE", "Not enough parameters")
@@ -466,6 +504,9 @@ func (channel *Channel) applyModeMask(client *Client, mode ChannelMode, op ModeO
466 504
 }
467 505
 
468 506
 func (channel *Channel) Quit(client *Client) {
507
+	channel.membersMutex.Lock()
508
+	defer channel.membersMutex.Unlock()
509
+
469 510
 	channel.members.Remove(client)
470 511
 	client.channels.Remove(channel)
471 512
 
@@ -475,6 +516,9 @@ func (channel *Channel) Quit(client *Client) {
475 516
 }
476 517
 
477 518
 func (channel *Channel) Kick(client *Client, target *Client, comment string) {
519
+	channel.membersMutex.Lock()
520
+	defer channel.membersMutex.Unlock()
521
+
478 522
 	if !(client.flags[Operator] || channel.members.Has(client)) {
479 523
 		client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
480 524
 		return
@@ -504,6 +548,9 @@ func (channel *Channel) Invite(invitee *Client, inviter *Client) {
504 548
 		return
505 549
 	}
506 550
 
551
+	channel.membersMutex.RLock()
552
+	defer channel.membersMutex.RUnlock()
553
+
507 554
 	if !channel.members.Has(inviter) {
508 555
 		inviter.Send(nil, inviter.server.name, ERR_NOTONCHANNEL, channel.name, "You're not on that channel")
509 556
 		return

+ 2
- 0
irc/client.go Visa fil

@@ -308,6 +308,8 @@ func (client *Client) Friends(Capabilities ...Capability) ClientSet {
308 308
 	}
309 309
 
310 310
 	for channel := range client.channels {
311
+		channel.membersMutex.RLock()
312
+		defer channel.membersMutex.RUnlock()
311 313
 		for member := range channel.members {
312 314
 			// make sure they have all the required caps
313 315
 			for _, Cap := range Capabilities {

+ 3
- 0
irc/modes.go Visa fil

@@ -345,6 +345,9 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
345 345
 	channelName, err := CasefoldChannel(msg.Params[0])
346 346
 	channel := server.channels.Get(channelName)
347 347
 
348
+	channel.membersMutex.Lock()
349
+	defer channel.membersMutex.Unlock()
350
+
348 351
 	if err != nil || channel == nil {
349 352
 		client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, msg.Params[0], "No such channel")
350 353
 		return false

+ 2
- 0
irc/roleplay.go Visa fil

@@ -87,12 +87,14 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
87 87
 			return
88 88
 		}
89 89
 
90
+		channel.membersMutex.RLock()
90 91
 		for member := range channel.members {
91 92
 			if member == client && !client.capabilities[EchoMessage] {
92 93
 				continue
93 94
 			}
94 95
 			member.Send(nil, source, "PRIVMSG", channel.name, message)
95 96
 		}
97
+		channel.membersMutex.RUnlock()
96 98
 	} else {
97 99
 		target, err := CasefoldName(targetString)
98 100
 		user := server.clients.Get(target)

+ 15
- 0
irc/server.go Visa fil

@@ -843,6 +843,9 @@ func (client *Client) WhoisChannelsNames(target *Client) []string {
843 843
 	var chstrs []string
844 844
 	index := 0
845 845
 	for channel := range client.channels {
846
+		channel.membersMutex.RLock()
847
+		defer channel.membersMutex.RUnlock()
848
+
846 849
 		// channel is secret and the target can't see it
847 850
 		if !target.flags[Operator] && channel.flags[Secret] && !channel.members.Has(target) {
848 851
 			continue
@@ -933,6 +936,9 @@ func (target *Client) RplWhoReply(channel *Channel, client *Client) {
933 936
 	}
934 937
 
935 938
 	if channel != nil {
939
+		channel.membersMutex.RLock()
940
+		defer channel.membersMutex.RUnlock()
941
+
936 942
 		flags += channel.members[client].Prefixes(target.capabilities[MultiPrefix])
937 943
 		channelName = channel.name
938 944
 	}
@@ -940,6 +946,9 @@ func (target *Client) RplWhoReply(channel *Channel, client *Client) {
940 946
 }
941 947
 
942 948
 func whoChannel(client *Client, channel *Channel, friends ClientSet) {
949
+	channel.membersMutex.RLock()
950
+	defer channel.membersMutex.RUnlock()
951
+
943 952
 	for member := range channel.members {
944 953
 		if !client.flags[Invisible] || friends[client] {
945 954
 			client.RplWhoReply(channel, member)
@@ -1372,6 +1381,9 @@ func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1372 1381
 		// make sure client has privs to kick the given user
1373 1382
 		//TODO(dan): split this into a separate function that checks if users have privs
1374 1383
 		// over other users, useful for things like -aoh as well
1384
+		channel.membersMutex.RLock()
1385
+		defer channel.membersMutex.RUnlock()
1386
+
1375 1387
 		var hasPrivs bool
1376 1388
 		for _, mode := range ChannelPrivModes {
1377 1389
 			if channel.members[client][mode] {
@@ -1448,6 +1460,9 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1448 1460
 }
1449 1461
 
1450 1462
 func (target *Client) RplList(channel *Channel) {
1463
+	channel.membersMutex.RLock()
1464
+	defer channel.membersMutex.RUnlock()
1465
+
1451 1466
 	// get the correct number of channel members
1452 1467
 	var memberCount int
1453 1468
 	if target.flags[Operator] || channel.members.Has(target) {

Laddar…
Avbryt
Spara