From c2a5461cb8a71383c5f27cbf45a0dd1070882bf5 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 19 Nov 2021 19:21:48 +0100 Subject: [PATCH] Use RPL_LOGGEDIN/OUT to mirror upstream status This will allow clients to properly show/hide UI to login and register. --- downstream.go | 34 +++++++++++++++++++++++++++++----- upstream.go | 6 ++++++ user.go | 1 + 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/downstream.go b/downstream.go index 3524493..838671f 100644 --- a/downstream.go +++ b/downstream.go @@ -258,6 +258,7 @@ type downstreamConn struct { clientName string realname string hostname string + account string // RPL_LOGGEDIN/OUT state password string // empty after authentication network *network // can be nil isMultiUpstream bool @@ -759,11 +760,10 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir return fmt.Errorf("SASL authentication failed: %v", err) } else if done { dc.saslServer = nil - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_LOGGEDIN, - Params: []string{dc.nick, dc.prefix().String(), dc.user.Username, "You are now logged in"}, - }) + // Technically we should send RPL_LOGGEDIN here. However we use + // RPL_LOGGEDIN to mirror the upstream connection status. Let's see + // how many clients that breaks. See: + // https://github.com/ircv3/ircv3-specifications/pull/476 dc.SendMessage(&irc.Message{ Prefix: dc.srv.prefix(), Command: irc.RPL_SASLSUCCESS, @@ -1037,6 +1037,29 @@ func (dc *downstreamConn) updateRealname() { } } +func (dc *downstreamConn) updateAccount() { + uc := dc.upstream() + if uc == nil || uc.account == dc.account || !dc.caps["sasl"] { + return + } + + if uc.account != "" { + dc.SendMessage(&irc.Message{ + Prefix: dc.srv.prefix(), + Command: irc.RPL_LOGGEDIN, + Params: []string{dc.nick, dc.prefix().String(), uc.account, "You are logged in as " + uc.account}, + }) + } else { + dc.SendMessage(&irc.Message{ + Prefix: dc.srv.prefix(), + Command: irc.RPL_LOGGEDOUT, + Params: []string{dc.nick, dc.prefix().String(), "You are logged out"}, + }) + } + + dc.account = uc.account +} + func sanityCheckServer(ctx context.Context, addr string) error { ctx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() @@ -1260,6 +1283,7 @@ func (dc *downstreamConn) welcome(ctx context.Context) error { dc.updateNick() dc.updateRealname() + dc.updateAccount() if motd := dc.user.srv.Config().MOTD; motd != "" && dc.network == nil { for _, msg := range generateMOTD(dc.srv.prefix(), dc.nick, motd) { diff --git a/upstream.go b/upstream.go index c5f2059..294dd2b 100644 --- a/upstream.go +++ b/upstream.go @@ -586,9 +586,15 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error { return err } uc.logger.Printf("logged in with account %q", uc.account) + uc.forEachDownstream(func(dc *downstreamConn) { + dc.updateAccount() + }) case irc.RPL_LOGGEDOUT: uc.account = "" uc.logger.Printf("logged out") + uc.forEachDownstream(func(dc *downstreamConn) { + dc.updateAccount() + }) case irc.ERR_NICKLOCKED, irc.RPL_SASLSUCCESS, irc.ERR_SASLFAIL, irc.ERR_SASLTOOLONG, irc.ERR_SASLABORTED: var info string if err := parseMessageParams(msg, nil, &info); err != nil { diff --git a/user.go b/user.go index a92585e..2d139da 100644 --- a/user.go +++ b/user.go @@ -541,6 +541,7 @@ func (u *user) run() { dc.updateNick() dc.updateRealname() + dc.updateAccount() }) u.forEachDownstream(func(dc *downstreamConn) { if dc.caps["soju.im/bouncer-networks-notify"] {