commit 1d85e0b

delthas  ·  2022-09-02 11:44:31 +0000 UTC
parent 6ed5a57
Use WHOX rather than WHO when available

This will reduce network usage and possibly increase WHO cache hit ratio
on bouncers supporting a WHO cache.
2 files changed,  +25, -5
+1, -0
1@@ -43,6 +43,7 @@ const (
2 	rplVersion         = "351" // <version> <servername> :<comments>
3 	rplWhoreply        = "352" // <channel> <user> <host> <server> <nick> "H"/"G" ["*"] [("@"/"+")] :<hop count> <nick>
4 	rplNamreply        = "353" // <=/*/@> <channel> :1*(@/ /+user)
5+	rplWhospecialreply = "354" // [token] [channel] [user] [ip] [host] [server] [nick] [flags] [hopcount] [idle] [account] [oplevel] [:realname]
6 	rplEndofnames      = "366" // <channel> :End of names list
7 	rplBanlist         = "367" // <channel> <ban mask>
8 	rplEndofbanlist    = "368" // <channel> :End of ban list
+24, -5
 1@@ -134,6 +134,7 @@ type Session struct {
 2 	prefixSymbols string
 3 	prefixModes   string
 4 	monitor       bool
 5+	whox          bool
 6 
 7 	users          map[string]*User        // known users.
 8 	channels       map[string]Channel      // joined channels.
 9@@ -359,6 +360,15 @@ func (s *Session) ChangeNick(nick string) {
10 	s.out <- NewMessage("NICK", nick)
11 }
12 
13+func (s *Session) Who(target string) {
14+	if s.whox {
15+		// only request what we need, to optimize server who cache hits and reduce traffic
16+		s.out <- NewMessage("WHO", target, "%uhnf")
17+	} else {
18+		s.out <- NewMessage("WHO", target)
19+	}
20+}
21+
22 func (s *Session) ChangeMode(channel, flags string, args []string) {
23 	if flags != "" {
24 		args = append([]string{channel, flags}, args...)
25@@ -693,7 +703,7 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
26 			Name: s.nick, User: s.user, Host: s.host,
27 		}}
28 		if s.host == "" {
29-			s.out <- NewMessage("WHO", s.nick)
30+			s.Who(s.nick)
31 		}
32 	case rplIsupport:
33 		if len(msg.Params) < 3 {
34@@ -701,14 +711,21 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
35 		}
36 		s.updateFeatures(msg.Params[1 : len(msg.Params)-1])
37 		return RegisteredEvent{}, nil
38-	case rplWhoreply:
39+	case rplWhoreply, rplWhospecialreply:
40 		var nick, host, flags, username string
41-		if err := msg.ParseParams(nil, nil, &username, &host, nil, &nick, &flags, nil); err != nil {
42+		var err error
43+		if msg.Command == rplWhoreply {
44+			err = msg.ParseParams(nil, nil, &username, &host, nil, &nick, &flags, nil)
45+		} else {
46+			// we always request WHOX with %uhnf
47+			err = msg.ParseParams(nil, &username, &host, &nick, &flags)
48+		}
49+		if err != nil {
50 			return nil, err
51 		}
52 
53 		nickCf := s.Casemap(nick)
54-		away := flags[0] == 'G' // flags is not empty because it's not the trailing parameter
55+		away := strings.ContainsRune(flags, 'G')
56 
57 		if s.nickCf == nickCf {
58 			s.user = username
59@@ -794,7 +811,7 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
60 				// Only try to know who is away if the list is
61 				// updated by the server via away-notify.
62 				// Otherwise, it'll become outdated over time.
63-				s.out <- NewMessage("WHO", channel)
64+				s.Who(channel)
65 			}
66 		} else if c, ok := s.channels[channelCf]; ok {
67 			if _, ok := s.users[nickCf]; !ok {
68@@ -1525,6 +1542,8 @@ func (s *Session) updateFeatures(features []string) {
69 			numPrefixes := len(value)/2 - 1
70 			s.prefixModes = value[1 : numPrefixes+1]
71 			s.prefixSymbols = value[numPrefixes+2:]
72+		case "WHOX":
73+			s.whox = true
74 		}
75 	}
76 }