commit fcd6b14
delthas
·
2025-03-17 22:45:42 +0000 UTC
parent aee34a4
Defer unimportant caps until CAP LS response This keeps our conn-reg 0-RTT but introduces a theoretical race condition on these CAPs (e.g. if we receive a SETNAME right after conn-reg). This helps us go below 20 messages for our conn-reg batch, which is the default limit on solanum and the one used by Libera. Fixes: https://todo.sr.ht/~delthas/senpai/200
1 files changed,
+49,
-28
+49,
-28
1@@ -50,28 +50,29 @@ func (auth *SASLPlain) Respond(challenge string) (res string, err error) {
2 }
3
4 // SupportedCapabilities is the set of capabilities supported by this library.
5-var SupportedCapabilities = map[string]struct{}{
6- "away-notify": {},
7- "batch": {},
8- "cap-notify": {},
9- "echo-message": {},
10- "extended-monitor": {},
11- "invite-notify": {},
12- "labeled-response": {},
13- "message-tags": {},
14- "multi-prefix": {},
15- "server-time": {},
16- "sasl": {},
17- "setname": {},
18- "standard-replies": {},
19-
20- "draft/chathistory": {},
21- "draft/event-playback": {},
22- "draft/metadata-2": {},
23- "draft/read-marker": {},
24- "soju.im/bouncer-networks-notify": {},
25- "soju.im/bouncer-networks": {},
26- "soju.im/search": {},
27+// Value is false if the cap is deferred (to work around some daemons agfressive rate pre-conn-reg backlog limiting)
28+var SupportedCapabilities = map[string]bool{
29+ "away-notify": false,
30+ "batch": true,
31+ "cap-notify": true,
32+ "echo-message": true,
33+ "extended-monitor": false,
34+ "invite-notify": false,
35+ "labeled-response": true,
36+ "message-tags": true,
37+ "multi-prefix": true,
38+ "sasl": true,
39+ "server-time": true,
40+ "setname": false,
41+ "standard-replies": true,
42+
43+ "draft/chathistory": true,
44+ "draft/event-playback": true,
45+ "draft/metadata-2": true,
46+ "draft/read-marker": true,
47+ "soju.im/bouncer-networks-notify": true,
48+ "soju.im/bouncer-networks": true,
49+ "soju.im/search": false,
50 }
51
52 // Values taken by the "@+typing=" client tag. TypingUnspec means the value or
53@@ -199,8 +200,10 @@ func NewSession(out chan<- Message, params SessionParams) *Session {
54 }
55
56 s.out <- NewMessage("CAP", "LS", "302")
57- for capability := range SupportedCapabilities {
58- s.out <- NewMessage("CAP", "REQ", capability)
59+ for capability, immediate := range SupportedCapabilities {
60+ if immediate || s.netID != "" {
61+ s.out <- NewMessage("CAP", "REQ", capability)
62+ }
63 }
64 s.out <- NewMessage("NICK", s.nick)
65 s.out <- NewMessage("USER", s.user, "0", "*", s.real)
66@@ -877,9 +880,18 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
67 // do nothing
68 case "CAP":
69 var subcommand, caps string
70- if err := msg.ParseParams(nil, &subcommand, &caps); err != nil {
71+ if err := msg.ParseParams(nil, &subcommand); err != nil {
72 return nil, err
73 }
74+ if len(msg.Params) > 3 && msg.Params[2] == "*" {
75+ if err := msg.ParseParams(nil, nil, nil, &caps); err != nil {
76+ return nil, err
77+ }
78+ } else {
79+ if err := msg.ParseParams(nil, nil, &caps); err != nil {
80+ return nil, err
81+ }
82+ }
83
84 switch subcommand {
85 case "ACK":
86@@ -912,16 +924,25 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
87 }
88 case "NAK":
89 // do nothing
90- case "NEW":
91+ case "LS", "NEW":
92+ var reqs []string
93 for _, c := range ParseCaps(caps) {
94 s.availableCaps[c.Name] = c.Value
95- if _, ok := SupportedCapabilities[c.Name]; !ok {
96+ immediate, ok := SupportedCapabilities[c.Name]
97+ if !ok {
98+ continue
99+ }
100+ if subcommand == "LS" && (immediate || s.netID != "") {
101+ // Already sent CAP, ignore
102 continue
103 }
104 if _, ok := s.enabledCaps[c.Name]; ok {
105 continue
106 }
107- s.out <- NewMessage("CAP", "REQ", c.Name)
108+ reqs = append(reqs, c.Name)
109+ }
110+ if len(reqs) > 0 {
111+ s.out <- NewMessage("CAP", "REQ", strings.Join(reqs, " "))
112 }
113 case "DEL":
114 for _, c := range ParseCaps(caps) {