From 960d51159c09a5a86a94b35e579376c149f0eaa5 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Tue, 1 Jan 2019 13:00:16 -0500 Subject: [PATCH] add ClientDetails struct for getting a snapshot of client state --- irc/client.go | 22 +++++++++++++++++++++- irc/getters.go | 18 +++++++++++------- irc/handlers.go | 2 +- irc/nickname.go | 2 +- irc/server.go | 11 +++++------ irc/whowas.go | 11 +---------- irc/whowas_test.go | 26 +++++++++++++------------- 7 files changed, 53 insertions(+), 39 deletions(-) diff --git a/irc/client.go b/irc/client.go index ebcaa066..849d69ea 100644 --- a/irc/client.go +++ b/irc/client.go @@ -52,7 +52,7 @@ type ResumeDetails struct { // Client is an IRC client. type Client struct { account string - accountName string + accountName string // display name of the account: uncasefolded, '*' if not logged in atime time.Time authorized bool awayMessage string @@ -100,6 +100,25 @@ type Client struct { history *history.Buffer } +// WhoWas is the subset of client details needed to answer a WHOWAS query +type WhoWas struct { + nick string + nickCasefolded string + username string + hostname string + realname string +} + +// ClientDetails is a standard set of details about a client +type ClientDetails struct { + WhoWas + + nickMask string + nickMaskCasefolded string + account string + accountName string +} + // NewClient sets up a new client and starts its goroutine. func NewClient(server *Server, conn net.Conn, isTLS bool) { now := time.Now() @@ -117,6 +136,7 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) { flags: modes.NewModeSet(), server: server, socket: socket, + accountName: "*", nick: "*", // * is used until actual nick is given nickCasefolded: "*", nickMaskString: "*", // * is used until actual nick is given diff --git a/irc/getters.go b/irc/getters.go index fcaab836..b2ac01c3 100644 --- a/irc/getters.go +++ b/irc/getters.go @@ -147,9 +147,6 @@ func (client *Client) Account() string { func (client *Client) AccountName() string { client.stateMutex.RLock() defer client.stateMutex.RUnlock() - if client.accountName == "" { - return "*" - } return client.accountName } @@ -217,15 +214,22 @@ func (client *Client) Channels() (result []*Channel) { } func (client *Client) WhoWas() (result WhoWas) { + return client.Details().WhoWas +} + +func (client *Client) Details() (result ClientDetails) { client.stateMutex.RLock() defer client.stateMutex.RUnlock() - result.nicknameCasefolded = client.nickCasefolded - result.nickname = client.nick + result.nick = client.nick + result.nickCasefolded = client.nickCasefolded result.username = client.username - result.hostname = client.hostname + result.hostname = client.username result.realname = client.realname - + result.nickMask = client.nickMaskString + result.nickMaskCasefolded = client.nickMaskCasefolded + result.account = client.account + result.accountName = client.accountName return } diff --git a/irc/handlers.go b/irc/handlers.go index 6aca801f..0537382f 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -2541,7 +2541,7 @@ func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re } } else { for _, whoWas := range results { - rb.Add(nil, server.name, RPL_WHOWASUSER, cnick, whoWas.nickname, whoWas.username, whoWas.hostname, "*", whoWas.realname) + rb.Add(nil, server.name, RPL_WHOWASUSER, cnick, whoWas.nick, whoWas.username, whoWas.hostname, "*", whoWas.realname) } } if len(nickname) > 0 { diff --git a/irc/nickname.go b/irc/nickname.go index c72de556..d1df3153 100644 --- a/irc/nickname.go +++ b/irc/nickname.go @@ -59,7 +59,7 @@ func performNickChange(server *Server, client *Client, target *Client, newnick s client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s [%s]", origNickMask, nickname, cfnick)) if hadNick { - target.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), whowas.nickname, nickname)) + target.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), whowas.nick, nickname)) target.server.whoWas.Append(whowas) for friend := range target.Friends() { friend.Send(nil, origNickMask, "NICK", nickname) diff --git a/irc/server.go b/irc/server.go index 5970f9b6..9beecb85 100644 --- a/irc/server.go +++ b/irc/server.go @@ -500,9 +500,9 @@ func (client *Client) WhoisChannelsNames(target *Client) []string { func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) { cnick := client.Nick() - targetInfo := target.WhoWas() - rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nickname, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname) - tnick := targetInfo.nickname + targetInfo := target.Details() + rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nick, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname) + tnick := targetInfo.nick whoischannels := client.WhoisChannelsNames(target) if whoischannels != nil { @@ -518,9 +518,8 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) { if target.HasMode(modes.TLS) { rb.Add(nil, client.server.name, RPL_WHOISSECURE, cnick, tnick, client.t("is using a secure connection")) } - taccount := target.AccountName() - if taccount != "*" { - rb.Add(nil, client.server.name, RPL_WHOISACCOUNT, cnick, tnick, taccount, client.t("is logged in as")) + if targetInfo.accountName != "*" { + rb.Add(nil, client.server.name, RPL_WHOISACCOUNT, cnick, tnick, targetInfo.accountName, client.t("is logged in as")) } if target.HasMode(modes.Bot) { rb.Add(nil, client.server.name, RPL_WHOISBOT, cnick, tnick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name))) diff --git a/irc/whowas.go b/irc/whowas.go index 3ecf870d..e12b587c 100644 --- a/irc/whowas.go +++ b/irc/whowas.go @@ -22,15 +22,6 @@ type WhoWasList struct { accessMutex sync.RWMutex // tier 1 } -// WhoWas is an entry in the WhoWasList. -type WhoWas struct { - nicknameCasefolded string - nickname string - username string - hostname string - realname string -} - // NewWhoWasList returns a new WhoWasList func NewWhoWasList(size int) *WhoWasList { return &WhoWasList{ @@ -82,7 +73,7 @@ func (list *WhoWasList) Find(nickname string, limit int) (results []WhoWas) { // iterate backwards through the ring buffer pos := list.prev(list.end) for limit == 0 || len(results) < limit { - if casefoldedNickname == list.buffer[pos].nicknameCasefolded { + if casefoldedNickname == list.buffer[pos].nickCasefolded { results = append(results, list.buffer[pos]) } if pos == list.start { diff --git a/irc/whowas_test.go b/irc/whowas_test.go index 4f011660..2ee76536 100644 --- a/irc/whowas_test.go +++ b/irc/whowas_test.go @@ -13,11 +13,11 @@ func makeTestWhowas(nick string) WhoWas { panic(err) } return WhoWas{ - nicknameCasefolded: cfnick, - nickname: nick, - username: "user", - hostname: "oragono.io", - realname: "Real Name", + nickCasefolded: cfnick, + nick: nick, + username: "user", + hostname: "oragono.io", + realname: "Real Name", } } @@ -36,48 +36,48 @@ func TestWhoWas(t *testing.T) { t.Fatalf("incorrect whowas results: %v", results) } results = wwl.Find("dan-", 10) - if len(results) != 1 || results[0].nickname != "dan-" { + if len(results) != 1 || results[0].nick != "dan-" { t.Fatalf("incorrect whowas results: %v", results) } wwl.Append(makeTestWhowas("slingamn")) results = wwl.Find("slingamN", 10) - if len(results) != 1 || results[0].nickname != "slingamn" { + if len(results) != 1 || results[0].nick != "slingamn" { t.Fatalf("incorrect whowas results: %v", results) } wwl.Append(makeTestWhowas("Dan-")) results = wwl.Find("dan-", 10) // reverse chronological order - if len(results) != 2 || results[0].nickname != "Dan-" || results[1].nickname != "dan-" { + if len(results) != 2 || results[0].nick != "Dan-" || results[1].nick != "dan-" { t.Fatalf("incorrect whowas results: %v", results) } // 0 means no limit results = wwl.Find("dan-", 0) - if len(results) != 2 || results[0].nickname != "Dan-" || results[1].nickname != "dan-" { + if len(results) != 2 || results[0].nick != "Dan-" || results[1].nick != "dan-" { t.Fatalf("incorrect whowas results: %v", results) } // a limit of 1 should return the most recent entry only results = wwl.Find("dan-", 1) - if len(results) != 1 || results[0].nickname != "Dan-" { + if len(results) != 1 || results[0].nick != "Dan-" { t.Fatalf("incorrect whowas results: %v", results) } wwl.Append(makeTestWhowas("moocow")) results = wwl.Find("moocow", 10) - if len(results) != 1 || results[0].nickname != "moocow" { + if len(results) != 1 || results[0].nick != "moocow" { t.Fatalf("incorrect whowas results: %v", results) } results = wwl.Find("dan-", 10) // should have overwritten the original entry, leaving the second - if len(results) != 1 || results[0].nickname != "Dan-" { + if len(results) != 1 || results[0].nick != "Dan-" { t.Fatalf("incorrect whowas results: %v", results) } // overwrite the second entry wwl.Append(makeTestWhowas("enckse")) results = wwl.Find("enckse", 10) - if len(results) != 1 || results[0].nickname != "enckse" { + if len(results) != 1 || results[0].nick != "enckse" { t.Fatalf("incorrect whowas results: %v", results) } results = wwl.Find("slingamn", 10)