This commit is contained in:
Shivaram Lingamneni 2019-07-01 09:21:38 -04:00
parent c96cec9388
commit 5a554ab4b0
6 changed files with 109 additions and 67 deletions

View File

@ -275,6 +275,7 @@ func (server *Server) RunClient(conn clientConn) {
client.rawHostname = session.rawHostname
client.proxiedIP = session.proxiedIP
server.stats.Add()
client.run(session)
}
@ -359,6 +360,15 @@ func (client *Client) IPString() string {
return ip
}
// t returns the translated version of the given string, based on the languages configured by the client.
func (client *Client) t(originalString string) string {
languageManager := client.server.Config().languageManager
if !languageManager.Enabled() {
return originalString
}
return languageManager.Translate(client.Languages(), originalString)
}
//
// command goroutine
//
@ -921,21 +931,6 @@ func (client *Client) LoggedIntoAccount() bool {
return client.Account() != ""
}
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
func (client *Client) RplISupport(rb *ResponseBuffer) {
translatedISupport := client.t("are supported by this server")
nick := client.Nick()
config := client.server.Config()
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
length := len(cachedTokenLine) + 2
tokenline := make([]string, length)
tokenline[0] = nick
copy(tokenline[1:], cachedTokenLine)
tokenline[length-1] = translatedISupport
rb.Add(nil, client.server.name, RPL_ISUPPORT, tokenline...)
}
}
// Quit sets the given quit message for the client.
// (You must ensure separately that destroy() is called, e.g., by returning `true` from
// the command handler or calling it yourself.)
@ -1094,16 +1089,8 @@ func (client *Client) destroy(session *Session) {
client.server.accounts.Logout(client)
// send quit messages to friends
if registered {
client.server.stats.ChangeTotal(-1)
}
if client.HasMode(modes.Invisible) {
client.server.stats.ChangeInvisible(-1)
}
if client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator) {
client.server.stats.ChangeOperators(-1)
}
client.server.stats.Remove(registered, client.HasMode(modes.Invisible),
client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator))
// this happens under failure to return from BRB
if quitMessage == "" {

View File

@ -1638,14 +1638,7 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
// LUSERS [<mask> [<server>]]
func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
//TODO(vegax87) Fix network statistics and additional parameters
totalCount, invisibleCount, operCount := server.stats.GetStats()
rb.Add(nil, server.name, RPL_LUSERCLIENT, client.nick, fmt.Sprintf(client.t("There are %[1]d users and %[2]d invisible on %[3]d server(s)"), totalCount-invisibleCount, invisibleCount, 1))
rb.Add(nil, server.name, RPL_LUSEROP, client.nick, strconv.Itoa(operCount), client.t("IRC Operators online"))
rb.Add(nil, server.name, RPL_LUSERCHANNELS, client.nick, strconv.Itoa(server.channels.Len()), client.t("channels formed"))
rb.Add(nil, server.name, RPL_LUSERME, client.nick, fmt.Sprintf(client.t("I have %[1]d clients and %[2]d servers"), totalCount, 1))
server.Lusers(client, rb)
return false
}
@ -2582,7 +2575,7 @@ func userhostHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *
// VERSION
func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
rb.Add(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
client.RplISupport(rb)
server.RplISupport(client, rb)
return false
}

View File

@ -164,6 +164,11 @@ func (lm *Manager) Count() int {
return len(lm.Languages)
}
// Enabled returns whether translation is enabled.
func (lm *Manager) Enabled() bool {
return len(lm.translations) != 0
}
// Translators returns the languages we have and the translators.
func (lm *Manager) Translators() []string {
var tlist sort.StringSlice

View File

@ -50,6 +50,8 @@ const (
RPL_TRACELOG = "261"
RPL_TRACEEND = "262"
RPL_TRYAGAIN = "263"
RPL_LOCALUSERS = "265"
RPL_GLOBALUSERS = "266"
RPL_WHOISCERTFP = "276"
RPL_AWAY = "301"
RPL_USERHOST = "302"

View File

@ -386,7 +386,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
c.SetRegistered()
// count new user in statistics
server.stats.ChangeTotal(1)
server.stats.Register()
server.monitorManager.AlertAbout(c, true)
server.playRegistrationBurst(session)
@ -410,7 +410,8 @@ func (server *Server) playRegistrationBurst(session *Session) {
session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
rb := NewResponseBuffer(session)
c.RplISupport(rb)
server.RplISupport(c, rb)
server.Lusers(c, rb)
server.MOTD(c, rb)
rb.Send(true)
@ -423,11 +424,34 @@ func (server *Server) playRegistrationBurst(session *Session) {
}
}
// t returns the translated version of the given string, based on the languages configured by the client.
func (client *Client) t(originalString string) string {
// TODO(slingamn) investigate a fast path for this, using an atomic load to see if translation is disabled
languages := client.Languages()
return client.server.Languages().Translate(languages, originalString)
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
func (server *Server) RplISupport(client *Client, rb *ResponseBuffer) {
translatedISupport := client.t("are supported by this server")
nick := client.Nick()
config := server.Config()
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
length := len(cachedTokenLine) + 2
tokenline := make([]string, length)
tokenline[0] = nick
copy(tokenline[1:], cachedTokenLine)
tokenline[length-1] = translatedISupport
rb.Add(nil, server.name, RPL_ISUPPORT, tokenline...)
}
}
func (server *Server) Lusers(client *Client, rb *ResponseBuffer) {
nick := client.Nick()
stats := server.stats.GetValues()
rb.Add(nil, server.name, RPL_LUSERCLIENT, nick, fmt.Sprintf(client.t("There are %[1]d users and %[2]d invisible on %[3]d server(s)"), stats.Total-stats.Invisible, stats.Invisible, 1))
rb.Add(nil, server.name, RPL_LUSEROP, nick, strconv.Itoa(stats.Operators), client.t("IRC Operators online"))
rb.Add(nil, server.name, RPL_LUSERUNKNOWN, nick, strconv.Itoa(stats.Unknown), client.t("unregistered connections"))
rb.Add(nil, server.name, RPL_LUSERCHANNELS, nick, strconv.Itoa(server.channels.Len()), client.t("channels formed"))
rb.Add(nil, server.name, RPL_LUSERME, nick, fmt.Sprintf(client.t("I have %[1]d clients and %[2]d servers"), stats.Total, 1))
total := strconv.Itoa(stats.Total)
max := strconv.Itoa(stats.Max)
rb.Add(nil, server.name, RPL_LOCALUSERS, nick, total, max, fmt.Sprintf(client.t("Current local users %[1]s, max %[2]s"), total, max))
rb.Add(nil, server.name, RPL_GLOBALUSERS, nick, total, max, fmt.Sprintf(client.t("Current global users %[1]s, max %[2]s"), total, max))
}
// MOTD serves the Message of the Day.

View File

@ -4,43 +4,74 @@ import (
"sync"
)
// Stats contains the numbers of total, invisible and operators on the server
type Stats struct {
sync.RWMutex
Total int
type StatsValues struct {
Unknown int // unregistered clients
Total int // registered clients, including invisible
Max int // high-water mark of registered clients
Invisible int
Operators int
}
// ChangeTotal increments the total user count on server
func (s *Stats) ChangeTotal(i int) {
s.Lock()
defer s.Unlock()
// Stats tracks statistics for a running server
type Stats struct {
StatsValues
s.Total += i
mutex sync.Mutex
}
// ChangeInvisible increments the invisible count
func (s *Stats) ChangeInvisible(i int) {
s.Lock()
defer s.Unlock()
s.Invisible += i
// Adds an unregistered client
func (s *Stats) Add() {
s.mutex.Lock()
s.Unknown += 1
s.mutex.Unlock()
}
// ChangeOperators increases the operator count
func (s *Stats) ChangeOperators(i int) {
s.Lock()
defer s.Unlock()
// Transition a client from unregistered to registered
func (s *Stats) Register() {
s.mutex.Lock()
s.Unknown -= 1
s.Total += 1
if s.Max < s.Total {
s.Max = s.Total
}
s.mutex.Unlock()
}
s.Operators += i
// Modify the Invisible count
func (s *Stats) ChangeInvisible(increment int) {
s.mutex.Lock()
s.Invisible += increment
s.mutex.Unlock()
}
// Modify the Operator count
func (s *Stats) ChangeOperators(increment int) {
s.mutex.Lock()
s.Operators += increment
s.mutex.Unlock()
}
// Remove a user from the server
func (s *Stats) Remove(registered, invisible, operator bool) {
s.mutex.Lock()
if registered {
s.Total -= 1
} else {
s.Unknown -= 1
}
if invisible {
s.Invisible -= 1
}
if operator {
s.Operators -= 1
}
s.mutex.Unlock()
}
// GetStats retrives total, invisible and oper count
func (s *Stats) GetStats() (int, int, int) {
s.Lock()
defer s.Unlock()
return s.Total, s.Invisible, s.Operators
func (s *Stats) GetValues() (result StatsValues) {
s.mutex.Lock()
result = s.StatsValues
s.mutex.Unlock()
return
}