Selaa lähdekoodia

correctly support disabling caps with CAP REQ, fixes #337

tags/v1.0.0-rc1
Shivaram Lingamneni 5 vuotta sitten
vanhempi
commit
f48af3ee44
5 muutettua tiedostoa jossa 55 lisäystä ja 9 poistoa
  1. 5
    0
      irc/caps/set.go
  2. 11
    0
      irc/caps/set_test.go
  3. 17
    8
      irc/handlers.go
  4. 16
    0
      irc/utils/bitset.go
  5. 6
    1
      irc/utils/bitset_test.go

+ 5
- 0
irc/caps/set.go Näytä tiedosto

@@ -59,6 +59,11 @@ func (s *Set) Union(other *Set) {
59 59
 	utils.BitsetUnion(s[:], other[:])
60 60
 }
61 61
 
62
+// Subtract removes all the capabilities of another set from this set.
63
+func (s *Set) Subtract(other *Set) {
64
+	utils.BitsetSubtract(s[:], other[:])
65
+}
66
+
62 67
 // Empty returns whether the set is empty.
63 68
 func (s *Set) Empty() bool {
64 69
 	return utils.BitsetEmpty(s[:])

+ 11
- 0
irc/caps/set_test.go Näytä tiedosto

@@ -60,6 +60,17 @@ func TestSets(t *testing.T) {
60 60
 	}
61 61
 }
62 62
 
63
+func TestSubtract(t *testing.T) {
64
+	s1 := NewSet(AccountTag, EchoMessage, UserhostInNames, ServerTime)
65
+
66
+	toRemove := NewSet(UserhostInNames, EchoMessage)
67
+	s1.Subtract(toRemove)
68
+
69
+	if !reflect.DeepEqual(s1, NewSet(AccountTag, ServerTime)) {
70
+		t.Errorf("subtract doesn't work")
71
+	}
72
+}
73
+
63 74
 func BenchmarkSetReads(b *testing.B) {
64 75
 	set := NewSet(UserhostInNames, EchoMessage)
65 76
 	b.ResetTimer()

+ 17
- 8
irc/handlers.go Näytä tiedosto

@@ -450,19 +450,27 @@ func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
450 450
 // CAP <subcmd> [<caps>]
451 451
 func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
452 452
 	subCommand := strings.ToUpper(msg.Params[0])
453
-	capabilities := caps.NewSet()
453
+	toAdd := caps.NewSet()
454
+	toRemove := caps.NewSet()
454 455
 	var capString string
455 456
 
456
-	var badCaps []string
457
+	badCaps := false
457 458
 	if len(msg.Params) > 1 {
458 459
 		capString = msg.Params[1]
459 460
 		strs := strings.Fields(capString)
460 461
 		for _, str := range strs {
462
+			remove := false
463
+			if str[0] == '-' {
464
+				str = str[1:]
465
+				remove = true
466
+			}
461 467
 			capab, err := caps.NameToCapability(str)
462
-			if err != nil || !SupportedCapabilities.Has(capab) {
463
-				badCaps = append(badCaps, str)
468
+			if err != nil || (!remove && !SupportedCapabilities.Has(capab)) {
469
+				badCaps = true
470
+			} else if !remove {
471
+				toAdd.Enable(capab)
464 472
 			} else {
465
-				capabilities.Enable(capab)
473
+				toRemove.Enable(capab)
466 474
 			}
467 475
 		}
468 476
 	}
@@ -490,16 +498,17 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
490 498
 		}
491 499
 
492 500
 		// make sure all capabilities actually exist
493
-		if len(badCaps) > 0 {
501
+		if badCaps {
494 502
 			rb.Add(nil, server.name, "CAP", client.nick, "NAK", capString)
495 503
 			return false
496 504
 		}
497
-		client.capabilities.Union(capabilities)
505
+		client.capabilities.Union(toAdd)
506
+		client.capabilities.Subtract(toRemove)
498 507
 		rb.Add(nil, server.name, "CAP", client.nick, "ACK", capString)
499 508
 
500 509
 		// if this is the first time the client is requesting a resume token,
501 510
 		// send it to them
502
-		if capabilities.Has(caps.Resume) {
511
+		if toAdd.Has(caps.Resume) {
503 512
 			token, err := client.generateResumeToken()
504 513
 			if err == nil {
505 514
 				rb.Add(nil, server.name, "RESUME", "TOKEN", token)

+ 16
- 0
irc/utils/bitset.go Näytä tiedosto

@@ -89,3 +89,19 @@ func BitsetCopy(set []uint64, other []uint64) {
89 89
 		atomic.StoreUint64(&set[i], data)
90 90
 	}
91 91
 }
92
+
93
+// BitsetSubtract modifies `set` to subtract the contents of `other`.
94
+// Similar caveats about race conditions as with `BitsetUnion` apply.
95
+func BitsetSubtract(set []uint64, other []uint64) {
96
+	for i := 0; i < len(set); i++ {
97
+		for {
98
+			ourAddr := &set[i]
99
+			ourBlock := atomic.LoadUint64(ourAddr)
100
+			otherBlock := atomic.LoadUint64(&other[i])
101
+			newBlock := ourBlock & (^otherBlock)
102
+			if atomic.CompareAndSwapUint64(ourAddr, ourBlock, newBlock) {
103
+				break
104
+			}
105
+		}
106
+	}
107
+}

+ 6
- 1
irc/utils/bitset_test.go Näytä tiedosto

@@ -73,8 +73,13 @@ func TestSets(t *testing.T) {
73 73
 	BitsetCopy(t3s, t1s)
74 74
 	for i = 0; i < 128; i++ {
75 75
 		expected := (i != 72)
76
-		if BitsetGet(t1s, i) != expected {
76
+		if BitsetGet(t3s, i) != expected {
77 77
 			t.Error("all bits should be set except 72")
78 78
 		}
79 79
 	}
80
+
81
+	BitsetSubtract(t3s, t2s)
82
+	if !BitsetGet(t3s, 0) || BitsetGet(t3s, 72) || !BitsetGet(t3s, 74) || BitsetGet(t3s, 71) {
83
+		t.Error("subtract doesn't work")
84
+	}
80 85
 }

Loading…
Peruuta
Tallenna