Queue WHOIS commands
This avoids having more than one in flight at a time (avoids hitting rate limits a bit) and routes back replies to the correct downstream connection (even if labeled-response isn't supported). Closes: https://todo.sr.ht/~emersion/soju/193
This commit is contained in:
parent
57eb54fb34
commit
846c99dedc
@ -2420,7 +2420,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
|||||||
params = []string{upstreamNick}
|
params = []string{upstreamNick}
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.SendMessageLabeled(ctx, dc.id, &irc.Message{
|
uc.enqueueCommand(dc, &irc.Message{
|
||||||
Command: "WHOIS",
|
Command: "WHOIS",
|
||||||
Params: params,
|
Params: params,
|
||||||
})
|
})
|
||||||
|
60
upstream.go
60
upstream.go
@ -350,7 +350,7 @@ func (uc *upstreamConn) sendNextPendingCommand(cmd string) {
|
|||||||
|
|
||||||
func (uc *upstreamConn) enqueueCommand(dc *downstreamConn, msg *irc.Message) {
|
func (uc *upstreamConn) enqueueCommand(dc *downstreamConn, msg *irc.Message) {
|
||||||
switch msg.Command {
|
switch msg.Command {
|
||||||
case "LIST", "WHO", "AUTHENTICATE", "REGISTER", "VERIFY":
|
case "LIST", "WHO", "WHOIS", "AUTHENTICATE", "REGISTER", "VERIFY":
|
||||||
// Supported
|
// Supported
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("Unsupported pending command %q", msg.Command))
|
panic(fmt.Errorf("Unsupported pending command %q", msg.Command))
|
||||||
@ -1435,11 +1435,16 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) {
|
dc, cmd := uc.currentPendingCommand("WHOIS")
|
||||||
|
if cmd == nil {
|
||||||
|
return fmt.Errorf("unexpected WHOIS reply %q: no matching pending WHOIS", msg.Command)
|
||||||
|
} else if dc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
msg := msg.Copy()
|
msg := msg.Copy()
|
||||||
msg.Params[1] = dc.marshalEntity(uc.network, nick)
|
msg.Params[1] = dc.marshalEntity(uc.network, nick)
|
||||||
dc.SendMessage(msg)
|
dc.SendMessage(msg)
|
||||||
})
|
|
||||||
case irc.RPL_WHOISCHANNELS:
|
case irc.RPL_WHOISCHANNELS:
|
||||||
var nick, channelList string
|
var nick, channelList string
|
||||||
if err := parseMessageParams(msg, nil, &nick, &channelList); err != nil {
|
if err := parseMessageParams(msg, nil, &nick, &channelList); err != nil {
|
||||||
@ -1447,20 +1452,25 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
|||||||
}
|
}
|
||||||
channels := splitSpace(channelList)
|
channels := splitSpace(channelList)
|
||||||
|
|
||||||
uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) {
|
dc, cmd := uc.currentPendingCommand("WHOIS")
|
||||||
nick := dc.marshalEntity(uc.network, nick)
|
if cmd == nil {
|
||||||
channelList := make([]string, len(channels))
|
return fmt.Errorf("unexpected RPL_WHOISCHANNELS: no matching pending WHOIS")
|
||||||
|
} else if dc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nick = dc.marshalEntity(uc.network, nick)
|
||||||
|
l := make([]string, len(channels))
|
||||||
for i, channel := range channels {
|
for i, channel := range channels {
|
||||||
prefix, channel := uc.parseMembershipPrefix(channel)
|
prefix, channel := uc.parseMembershipPrefix(channel)
|
||||||
channel = dc.marshalEntity(uc.network, channel)
|
channel = dc.marshalEntity(uc.network, channel)
|
||||||
channelList[i] = prefix.Format(dc) + channel
|
l[i] = prefix.Format(dc) + channel
|
||||||
}
|
}
|
||||||
channels := strings.Join(channelList, " ")
|
channelList = strings.Join(l, " ")
|
||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.RPL_WHOISCHANNELS,
|
Command: irc.RPL_WHOISCHANNELS,
|
||||||
Params: []string{dc.nick, nick, channels},
|
Params: []string{dc.nick, nick, channelList},
|
||||||
})
|
|
||||||
})
|
})
|
||||||
case irc.RPL_ENDOFWHOIS:
|
case irc.RPL_ENDOFWHOIS:
|
||||||
var nick string
|
var nick string
|
||||||
@ -1468,14 +1478,19 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) {
|
dc, cmd := uc.dequeueCommand("WHOIS")
|
||||||
nick := dc.marshalEntity(uc.network, nick)
|
if cmd == nil {
|
||||||
|
return fmt.Errorf("unexpected RPL_ENDOFWHOIS: no matching pending WHOIS")
|
||||||
|
} else if dc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nick = dc.marshalEntity(uc.network, nick)
|
||||||
dc.SendMessage(&irc.Message{
|
dc.SendMessage(&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
Prefix: dc.srv.prefix(),
|
||||||
Command: irc.RPL_ENDOFWHOIS,
|
Command: irc.RPL_ENDOFWHOIS,
|
||||||
Params: []string{dc.nick, nick, "End of /WHOIS list"},
|
Params: []string{dc.nick, nick, "End of /WHOIS list"},
|
||||||
})
|
})
|
||||||
})
|
|
||||||
case "INVITE":
|
case "INVITE":
|
||||||
var nick, channel string
|
var nick, channel string
|
||||||
if err := parseMessageParams(msg, &nick, &channel); err != nil {
|
if err := parseMessageParams(msg, &nick, &channel); err != nil {
|
||||||
@ -1634,6 +1649,25 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
|||||||
Params: []string{dc.nick, upstreamChannel, trailing},
|
Params: []string{dc.nick, upstreamChannel, trailing},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
case irc.ERR_NOSUCHNICK:
|
||||||
|
var nick, reason string
|
||||||
|
if err := parseMessageParams(msg, nil, &nick, &reason); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cm := uc.network.casemap
|
||||||
|
dc, cmd := uc.currentPendingCommand("WHOIS")
|
||||||
|
if cmd != nil && cm(cmd.Params[len(cmd.Params)-1]) == cm(nick) {
|
||||||
|
uc.dequeueCommand("WHOIS")
|
||||||
|
if dc != nil {
|
||||||
|
nick = dc.marshalEntity(uc.network, nick)
|
||||||
|
dc.SendMessage(&irc.Message{
|
||||||
|
Prefix: uc.srv.prefix(),
|
||||||
|
Command: msg.Command,
|
||||||
|
Params: []string{dc.nick, nick, reason},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
case irc.ERR_UNKNOWNCOMMAND, irc.RPL_TRYAGAIN:
|
case irc.ERR_UNKNOWNCOMMAND, irc.RPL_TRYAGAIN:
|
||||||
var command, reason string
|
var command, reason string
|
||||||
if err := parseMessageParams(msg, nil, &command, &reason); err != nil {
|
if err := parseMessageParams(msg, nil, &command, &reason); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user