From 6a2fba981226d0fd1bee543a9b74d9b1ffbb3068 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Mon, 3 Aug 2020 12:51:04 -0400 Subject: [PATCH 1/2] make it easier to patch out the maximum line length --- irc/client.go | 15 +++++++++------ irc/errors.go | 1 - irc/ircconn.go | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/irc/client.go b/irc/client.go index ed7f3e33..edbf44dd 100644 --- a/irc/client.go +++ b/irc/client.go @@ -27,6 +27,9 @@ import ( ) const ( + // maximum line length not including tags; don't change this for a public server + MaxLineLen = 512 + // IdentTimeout is how long before our ident (username) check times out. IdentTimeout = time.Second + 500*time.Millisecond IRCv3TimestampFormat = utils.IRCv3TimestampFormat @@ -185,8 +188,8 @@ func (s *Session) EndMultilineBatch(label string) (batch MultilineBatch, err err s.fakelag.Unsuspend() // heuristics to estimate how much data they used while fakelag was suspended - fakelagBill := (batch.lenBytes / 512) + 1 - fakelagBillLines := (batch.message.LenLines() * 60) / 512 + fakelagBill := (batch.lenBytes / MaxLineLen) + 1 + fakelagBillLines := (batch.message.LenLines() * 60) / MaxLineLen if fakelagBill < fakelagBillLines { fakelagBill = fakelagBillLines } @@ -666,7 +669,7 @@ func (client *Client) run(session *Session) { } } - msg, err := ircmsg.ParseLineStrict(line, true, 512) + msg, err := ircmsg.ParseLineStrict(line, true, MaxLineLen) if err == ircmsg.ErrorLineIsEmpty { continue } else if err == ircmsg.ErrorLineTooLong { @@ -1198,11 +1201,11 @@ func (client *Client) Quit(message string, session *Session) { // #364: don't send QUIT lines to unregistered clients if client.registered { quitMsg := ircmsg.MakeMessage(nil, client.nickMaskString, "QUIT", message) - finalData, _ = quitMsg.LineBytesStrict(false, 512) + finalData, _ = quitMsg.LineBytesStrict(false, MaxLineLen) } errorMsg := ircmsg.MakeMessage(nil, "", "ERROR", message) - errorMsgBytes, _ := errorMsg.LineBytesStrict(false, 512) + errorMsgBytes, _ := errorMsg.LineBytesStrict(false, MaxLineLen) finalData = append(finalData, errorMsgBytes...) sess.socket.SetFinalData(finalData) @@ -1536,7 +1539,7 @@ func (session *Session) SendRawMessage(message ircmsg.IrcMessage, blocking bool) } // assemble message - line, err := message.LineBytesStrict(false, 512) + line, err := message.LineBytesStrict(false, MaxLineLen) if err != nil { logline := fmt.Sprintf("Error assembling message for sending: %v\n%s", err, debug.Stack()) session.client.server.logger.Error("internal", logline) diff --git a/irc/errors.go b/irc/errors.go index d9fd66f3..ebf1e177 100644 --- a/irc/errors.go +++ b/irc/errors.go @@ -107,7 +107,6 @@ func (te *ThrottleError) Error() string { var ( ErrDatastorePathMissing = errors.New("Datastore path missing") ErrLimitsAreInsane = errors.New("Limits aren't setup properly, check them and make them sane") - ErrLineLengthsTooSmall = errors.New("Line lengths must be 512 or greater (check the linelen section under server->limits)") ErrLoggerExcludeEmpty = errors.New("Encountered logging type '-' with no type to exclude") ErrLoggerFilenameMissing = errors.New("Logging configuration specifies 'file' method but 'filename' is empty") ErrLoggerHasNoTypes = errors.New("Logger has no types to log") diff --git a/irc/ircconn.go b/irc/ircconn.go index b70a7984..9ddb0da7 100644 --- a/irc/ircconn.go +++ b/irc/ircconn.go @@ -13,7 +13,7 @@ import ( ) const ( - maxReadQBytes = ircmsg.MaxlenTagsFromClient + 512 + 1024 + maxReadQBytes = ircmsg.MaxlenTagsFromClient + MaxLineLen + 1024 ) var ( From 9000383f88c383880b1652df7f359f7ab730c357 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Mon, 3 Aug 2020 12:55:52 -0400 Subject: [PATCH 2/2] Move config errors to call sites Since allocating them is rare. --- irc/config.go | 18 +++++++++--------- irc/errors.go | 15 --------------- irc/gateways.go | 2 +- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/irc/config.go b/irc/config.go index fffa8543..31a4fdbe 100644 --- a/irc/config.go +++ b/irc/config.go @@ -640,7 +640,7 @@ func (conf *Config) OperatorClasses() (map[string]*OperClass, error) { lenOfLastOcs := -1 for { if lenOfLastOcs == len(ocs) { - return nil, ErrOperClassDependencies + return nil, errors.New("OperClasses contains a looping dependency, or a class extends from a class that doesn't exist") } lenOfLastOcs = len(ocs) @@ -869,24 +869,24 @@ func LoadConfig(filename string) (config *Config, err error) { config.Filename = filename if config.Network.Name == "" { - return nil, ErrNetworkNameMissing + return nil, errors.New("Network name missing") } if config.Server.Name == "" { - return nil, ErrServerNameMissing + return nil, errors.New("Server name missing") } if !utils.IsServerName(config.Server.Name) { - return nil, ErrServerNameNotHostname + return nil, errors.New("Server name must match the format of a hostname") } config.Server.nameCasefolded = strings.ToLower(config.Server.Name) if config.Datastore.Path == "" { - return nil, ErrDatastorePathMissing + return nil, errors.New("Datastore path missing") } //dan: automagically fix identlen until a few releases in the future (from now, 0.12.0), being a newly-introduced limit if config.Limits.IdentLen < 1 { config.Limits.IdentLen = 20 } if config.Limits.NickLen < 1 || config.Limits.ChannelLen < 2 || config.Limits.AwayLen < 1 || config.Limits.KickLen < 1 || config.Limits.TopicLen < 1 { - return nil, ErrLimitsAreInsane + return nil, errors.New("One or more limits values are too low") } if config.Limits.RegistrationMessages == 0 { config.Limits.RegistrationMessages = 1024 @@ -999,7 +999,7 @@ func LoadConfig(filename string) (config *Config, err error) { } } if methods["file"] && logConfig.Filename == "" { - return nil, ErrLoggerFilenameMissing + return nil, errors.New("Logging configuration specifies 'file' method but 'filename' is empty") } logConfig.MethodFile = methods["file"] logConfig.MethodStdout = methods["stdout"] @@ -1018,7 +1018,7 @@ func LoadConfig(filename string) (config *Config, err error) { continue } if typeStr == "-" { - return nil, ErrLoggerExcludeEmpty + return nil, errors.New("Encountered logging type '-' with no type to exclude") } if typeStr[0] == '-' { typeStr = typeStr[1:] @@ -1028,7 +1028,7 @@ func LoadConfig(filename string) (config *Config, err error) { } } if len(logConfig.Types) < 1 { - return nil, ErrLoggerHasNoTypes + return nil, errors.New("Logger has no types to log") } newLogConfigs = append(newLogConfigs, logConfig) diff --git a/irc/errors.go b/irc/errors.go index ebf1e177..01758997 100644 --- a/irc/errors.go +++ b/irc/errors.go @@ -102,18 +102,3 @@ type ThrottleError struct { func (te *ThrottleError) Error() string { return fmt.Sprintf(`Please wait at least %v and try again`, te.Duration) } - -// Config Errors -var ( - ErrDatastorePathMissing = errors.New("Datastore path missing") - ErrLimitsAreInsane = errors.New("Limits aren't setup properly, check them and make them sane") - ErrLoggerExcludeEmpty = errors.New("Encountered logging type '-' with no type to exclude") - ErrLoggerFilenameMissing = errors.New("Logging configuration specifies 'file' method but 'filename' is empty") - ErrLoggerHasNoTypes = errors.New("Logger has no types to log") - ErrNetworkNameMissing = errors.New("Network name missing") - ErrNoFingerprintOrPassword = errors.New("Fingerprint or password needs to be specified") - ErrNoListenersDefined = errors.New("Server listening addresses missing") - ErrOperClassDependencies = errors.New("OperClasses contains a looping dependency, or a class extends from a class that doesn't exist") - ErrServerNameMissing = errors.New("Server name missing") - ErrServerNameNotHostname = errors.New("Server name must match the format of a hostname") -) diff --git a/irc/gateways.go b/irc/gateways.go index ecc7899c..f7238b75 100644 --- a/irc/gateways.go +++ b/irc/gateways.go @@ -55,7 +55,7 @@ func (wc *webircConfig) Populate() (err error) { } if wc.Certfp == "" && wc.PasswordString == "" { - return ErrNoFingerprintOrPassword + return errors.New("webirc block has no certfp or password specified") } wc.allowedNets, err = utils.ParseNetList(wc.Hosts)