diff --git a/irc/accountreg.go b/irc/accountreg.go index 23d093b4..32ddda22 100644 --- a/irc/accountreg.go +++ b/irc/accountreg.go @@ -4,17 +4,11 @@ package irc import ( - "errors" "fmt" "github.com/tidwall/buntdb" ) -var ( - errAccountCreation = errors.New("Account could not be created") - errCertfpAlreadyExists = errors.New("An account already exists with your certificate") -) - // AccountRegistration manages the registration of accounts. type AccountRegistration struct { Enabled bool diff --git a/irc/accounts.go b/irc/accounts.go index e6297bba..ec20dd49 100644 --- a/irc/accounts.go +++ b/irc/accounts.go @@ -5,7 +5,6 @@ package irc import ( "encoding/json" - "errors" "fmt" "strconv" "time" @@ -37,9 +36,6 @@ var ( NoAccount = ClientAccount{ Name: "*", // * is used until actual account name is set } - - // generic sasl fail error - errSaslFail = errors.New("SASL failed") ) // ClientAccount represents a user account. diff --git a/irc/channel.go b/irc/channel.go index b0897ccd..6b4d3ffd 100644 --- a/irc/channel.go +++ b/irc/channel.go @@ -6,7 +6,6 @@ package irc import ( - "errors" "fmt" "strconv" "time" @@ -18,10 +17,6 @@ import ( "github.com/oragono/oragono/irc/modes" ) -var ( - ChannelAlreadyRegistered = errors.New("Channel is already registered") -) - // Channel represents a channel that clients can join. type Channel struct { flags modes.ModeSet @@ -132,7 +127,7 @@ func (channel *Channel) SetRegistered(founder string) error { defer channel.stateMutex.Unlock() if channel.registeredFounder != "" { - return ChannelAlreadyRegistered + return errChannelAlreadyRegistered } channel.registeredFounder = founder channel.registeredTime = time.Now() diff --git a/irc/channelmanager.go b/irc/channelmanager.go index 468393c9..9633801a 100644 --- a/irc/channelmanager.go +++ b/irc/channelmanager.go @@ -4,16 +4,9 @@ package irc import ( - "errors" "sync" ) -var ( - InvalidChannelName = errors.New("Invalid channel name") - NoSuchChannel = errors.New("No such channel") - ChannelNameInUse = errors.New("Channel name in use") -) - type channelManagerEntry struct { channel *Channel // this is a refcount for joins, so we can avoid a race where we incorrectly @@ -56,7 +49,7 @@ func (cm *ChannelManager) Join(client *Client, name string, key string) error { server := client.server casefoldedName, err := CasefoldChannel(name) if err != nil || len(casefoldedName) > server.Limits().ChannelLen { - return NoSuchChannel + return errNoSuchChannel } cm.Lock() @@ -117,7 +110,7 @@ func (cm *ChannelManager) maybeCleanup(entry *channelManagerEntry, afterJoin boo func (cm *ChannelManager) Part(client *Client, name string, message string) error { casefoldedName, err := CasefoldChannel(name) if err != nil { - return NoSuchChannel + return errNoSuchChannel } cm.RLock() @@ -125,7 +118,7 @@ func (cm *ChannelManager) Part(client *Client, name string, message string) erro cm.RUnlock() if entry == nil { - return NoSuchChannel + return errNoSuchChannel } entry.channel.Part(client, message) cm.maybeCleanup(entry, false) @@ -136,23 +129,23 @@ func (cm *ChannelManager) Part(client *Client, name string, message string) erro func (cm *ChannelManager) Rename(name string, newname string) error { cfname, err := CasefoldChannel(name) if err != nil { - return NoSuchChannel + return errNoSuchChannel } cfnewname, err := CasefoldChannel(newname) if err != nil { - return InvalidChannelName + return errInvalidChannelName } cm.Lock() defer cm.Unlock() if cm.chans[cfnewname] != nil { - return ChannelNameInUse + return errChannelNameInUse } entry := cm.chans[cfname] if entry == nil { - return NoSuchChannel + return errNoSuchChannel } delete(cm.chans, cfname) cm.chans[cfnewname] = entry diff --git a/irc/client.go b/irc/client.go index fcd90418..c98fd720 100644 --- a/irc/client.go +++ b/irc/client.go @@ -6,7 +6,6 @@ package irc import ( - "errors" "fmt" "log" "net" @@ -32,9 +31,7 @@ const ( ) var ( - // ErrNickAlreadySet is a weird error that's sent when the server's consistency has been compromised. - ErrNickAlreadySet = errors.New("Nickname is already set") - LoopbackIP = net.ParseIP("127.0.0.1") + LoopbackIP = net.ParseIP("127.0.0.1") ) // Client is an IRC client. @@ -397,7 +394,7 @@ func (client *Client) TryResume() { var params []string if 0 < len(oldModes) { params = []string{channel.name, "+" + oldModes} - for _ = range oldModes { + for range oldModes { params = append(params, client.nick) } } diff --git a/irc/client_lookup_set.go b/irc/client_lookup_set.go index babca39b..94e53cc4 100644 --- a/irc/client_lookup_set.go +++ b/irc/client_lookup_set.go @@ -5,7 +5,6 @@ package irc import ( - "errors" "fmt" "log" "regexp" @@ -17,11 +16,6 @@ import ( "sync" ) -var ( - ErrNickMissing = errors.New("nick missing") - ErrNicknameInUse = errors.New("nickname in use") -) - // ExpandUserHost takes a userhost, and returns an expanded version. func ExpandUserHost(userhost string) (expanded string) { expanded = userhost @@ -91,7 +85,7 @@ func (clients *ClientManager) Remove(client *Client) error { defer clients.Unlock() if !client.HasNick() { - return ErrNickMissing + return errNickMissing } clients.removeInternal(client) return nil @@ -111,7 +105,7 @@ func (clients *ClientManager) SetNick(client *Client, newNick string) error { currentNewEntry := clients.byNick[newcfnick] // the client may just be changing case if currentNewEntry != nil && currentNewEntry != client { - return ErrNicknameInUse + return errNicknameInUse } clients.byNick[newcfnick] = client client.updateNickMask(newNick) diff --git a/irc/config.go b/irc/config.go index 256244d7..3a7ecffb 100644 --- a/irc/config.go +++ b/irc/config.go @@ -8,7 +8,6 @@ package irc import ( "crypto/tls" "encoding/json" - "errors" "fmt" "io/ioutil" "log" @@ -41,7 +40,7 @@ type TLSListenConfig struct { func (conf *TLSListenConfig) Config() (*tls.Config, error) { cert, err := tls.LoadX509KeyPair(conf.Cert, conf.Key) if err != nil { - return nil, errors.New("tls cert+key: invalid pair") + return nil, ErrInvalidCertKeyPair } return &tls.Config{ @@ -232,7 +231,7 @@ func (conf *Config) OperatorClasses() (*map[string]OperClass, error) { lenOfLastOcs := -1 for { if lenOfLastOcs == len(ocs) { - return nil, errors.New("OperClasses contains a looping dependency, or a class extends from a class that doesn't exist") + return nil, ErrOperClassDependencies } lenOfLastOcs = len(ocs) @@ -369,22 +368,22 @@ func LoadConfig(filename string) (config *Config, err error) { } if config.Network.Name == "" { - return nil, errors.New("Network name missing") + return nil, ErrNetworkNameMissing } if config.Server.Name == "" { - return nil, errors.New("Server name missing") + return nil, ErrServerNameMissing } if !utils.IsHostname(config.Server.Name) { - return nil, errors.New("Server name must match the format of a hostname") + return nil, ErrServerNameNotHostname } if config.Datastore.Path == "" { - return nil, errors.New("Datastore path missing") + return nil, ErrDatastorePathMissing } if len(config.Server.Listen) == 0 { - return nil, errors.New("Server listening addresses missing") + return nil, ErrNoListenersDefined } if config.Limits.NickLen < 1 || config.Limits.ChannelLen < 2 || config.Limits.AwayLen < 1 || config.Limits.KickLen < 1 || config.Limits.TopicLen < 1 { - return nil, errors.New("Limits aren't setup properly, check them and make them sane") + return nil, ErrLimitsAreInsane } if config.Server.STS.Enabled { config.Server.STS.Duration, err = custime.ParseDuration(config.Server.STS.DurationString) @@ -422,7 +421,7 @@ func LoadConfig(filename string) (config *Config, err error) { config.Server.WebIRC = newWebIRC // process limits if config.Limits.LineLen.Tags < 512 || config.Limits.LineLen.Rest < 512 { - return nil, errors.New("Line lengths must be 512 or greater (check the linelen section under server->limits)") + return nil, ErrLineLengthsTooSmall } var newLogConfigs []logger.LoggingConfig for _, logConfig := range config.Logging { @@ -434,7 +433,7 @@ func LoadConfig(filename string) (config *Config, err error) { } } if methods["file"] && logConfig.Filename == "" { - return nil, errors.New("Logging configuration specifies 'file' method but 'filename' is empty") + return nil, ErrLoggerFilenameMissing } logConfig.MethodFile = methods["file"] logConfig.MethodStdout = methods["stdout"] @@ -453,7 +452,7 @@ func LoadConfig(filename string) (config *Config, err error) { continue } if typeStr == "-" { - return nil, errors.New("Encountered logging type '-' with no type to exclude") + return nil, ErrLoggerExcludeEmpty } if typeStr[0] == '-' { typeStr = typeStr[1:] @@ -463,7 +462,7 @@ func LoadConfig(filename string) (config *Config, err error) { } } if len(logConfig.Types) < 1 { - return nil, errors.New("Logger has no types to log") + return nil, ErrLoggerHasNoTypes } newLogConfigs = append(newLogConfigs, logConfig) diff --git a/irc/dline.go b/irc/dline.go index 4a104a3c..e0491228 100644 --- a/irc/dline.go +++ b/irc/dline.go @@ -4,7 +4,6 @@ package irc import ( - "errors" "fmt" "net" "sync" @@ -19,10 +18,6 @@ const ( keyDlineEntry = "bans.dline %s" ) -var ( - errNoExistingBan = errors.New("Ban does not exist") -) - // IPRestrictTime contains the expiration info about the given IP. type IPRestrictTime struct { // Duration is how long this block lasts for. diff --git a/irc/errors.go b/irc/errors.go new file mode 100644 index 00000000..9fc0d97b --- /dev/null +++ b/irc/errors.go @@ -0,0 +1,54 @@ +// Copyright (c) 2012-2014 Jeremy Latt +// Copyright (c) 2014-2015 Edmund Huber +// Copyright (c) 2016-2017 Daniel Oaks +// released under the MIT license + +package irc + +import "errors" + +// Runtime Errors +var ( + errAccountCreation = errors.New("Account could not be created") + errCertfpAlreadyExists = errors.New("An account already exists with your certificate") + errChannelAlreadyRegistered = errors.New("Channel is already registered") + errChannelNameInUse = errors.New("Channel name in use") + errInvalidChannelName = errors.New("Invalid channel name") + errMonitorLimitExceeded = errors.New("Monitor limit exceeded") + errNickMissing = errors.New("nick missing") + errNicknameInUse = errors.New("nickname in use") + errNoExistingBan = errors.New("Ban does not exist") + errNoSuchChannel = errors.New("No such channel") + errRenamePrivsNeeded = errors.New("Only chanops can rename channels") + errSaslFail = errors.New("SASL failed") +) + +// Socket Errors +var ( + errNoPeerCerts = errors.New("Client did not provide a certificate") + errNotTLS = errors.New("Not a TLS connection") +) + +// String Errors +var ( + errCouldNotStabilize = errors.New("Could not stabilize string while casefolding") + errStringIsEmpty = errors.New("String is empty") + errInvalidCharacter = errors.New("Invalid character") +) + +// Config Errors +var ( + ErrDatastorePathMissing = errors.New("Datastore path missing") + ErrInvalidCertKeyPair = errors.New("tls cert+key: invalid pair") + 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") + 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 d0589ff2..83c2dc74 100644 --- a/irc/gateways.go +++ b/irc/gateways.go @@ -6,7 +6,6 @@ package irc import ( - "errors" "fmt" "net" @@ -25,7 +24,7 @@ type webircConfig struct { // Populate fills out our password or fingerprint. func (wc *webircConfig) Populate() (err error) { if wc.Fingerprint == "" && wc.PasswordString == "" { - return errors.New("Fingerprint or password needs to be specified") + return ErrNoFingerprintOrPassword } if wc.PasswordString != "" { diff --git a/irc/handlers.go b/irc/handlers.go index 61c62a47..bd9302ed 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -976,7 +976,7 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { key = keys[i] } err := server.channels.Join(client, name, key) - if err == NoSuchChannel { + if err == errNoSuchChannel { client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.Nick(), name, client.t("No such channel")) } } @@ -1571,7 +1571,7 @@ func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bo } err = server.monitorManager.Add(client, casefoldedTarget, limit) - if err == ErrMonitorLimitExceeded { + if err == errMonitorLimitExceeded { client.Send(nil, server.name, ERR_MONLISTFULL, client.Nick(), strconv.Itoa(server.limits.MonitorEntries), strings.Join(targets, ",")) break } else if err != nil { @@ -1855,7 +1855,7 @@ func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { for _, chname := range channels { err := server.channels.Part(client, chname, reason) - if err == NoSuchChannel { + if err == errNoSuchChannel { client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, client.t("No such channel")) } } @@ -2023,13 +2023,13 @@ func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage) (resul // TODO: send correct error codes, e.g., ERR_CANNOTRENAME, ERR_CHANNAMEINUSE var code string switch err { - case NoSuchChannel: + case errNoSuchChannel: code = ERR_NOSUCHCHANNEL - case RenamePrivsNeeded: + case errRenamePrivsNeeded: code = ERR_CHANOPRIVSNEEDED - case InvalidChannelName: + case errInvalidChannelName: code = ERR_UNKNOWNERROR - case ChannelNameInUse: + case errChannelNameInUse: code = ERR_UNKNOWNERROR default: code = ERR_UNKNOWNERROR @@ -2040,12 +2040,12 @@ func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage) (resul oldName := strings.TrimSpace(msg.Params[0]) newName := strings.TrimSpace(msg.Params[1]) if oldName == "" || newName == "" { - errorResponse(InvalidChannelName, "") + errorResponse(errInvalidChannelName, "") return } casefoldedOldName, err := CasefoldChannel(oldName) if err != nil { - errorResponse(InvalidChannelName, oldName) + errorResponse(errInvalidChannelName, oldName) return } @@ -2056,12 +2056,12 @@ func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage) (resul channel := server.channels.Get(oldName) if channel == nil { - errorResponse(NoSuchChannel, oldName) + errorResponse(errNoSuchChannel, oldName) return } //TODO(dan): allow IRCops to do this? if !channel.ClientIsAtLeast(client, modes.Operator) { - errorResponse(RenamePrivsNeeded, oldName) + errorResponse(errRenamePrivsNeeded, oldName) return } diff --git a/irc/monitor.go b/irc/monitor.go index 5aa09858..970daecf 100644 --- a/irc/monitor.go +++ b/irc/monitor.go @@ -4,7 +4,6 @@ package irc import ( - "errors" "sync" "github.com/goshuirc/irc-go/ircmsg" @@ -29,9 +28,6 @@ func NewMonitorManager() *MonitorManager { return &mm } -// ErrMonitorLimitExceeded is used when the monitor list exceeds our limit. -var ErrMonitorLimitExceeded = errors.New("Monitor limit exceeded") - // AlertAbout alerts everyone monitoring `client`'s nick that `client` is now {on,off}line. func (manager *MonitorManager) AlertAbout(client *Client, online bool) { cfnick := client.NickCasefolded() @@ -67,7 +63,7 @@ func (manager *MonitorManager) Add(client *Client, nick string, limit int) error } if len(manager.watching[client]) >= limit { - return ErrMonitorLimitExceeded + return errMonitorLimitExceeded } manager.watching[client][nick] = true diff --git a/irc/nickname.go b/irc/nickname.go index 0179acb3..0100601d 100644 --- a/irc/nickname.go +++ b/irc/nickname.go @@ -42,7 +42,7 @@ func performNickChange(server *Server, client *Client, target *Client, newnick s origNick := target.Nick() origNickMask := target.NickMaskString() err = client.server.clients.SetNick(target, nickname) - if err == ErrNicknameInUse { + if err == errNicknameInUse { client.Send(nil, server.name, ERR_NICKNAMEINUSE, client.nick, nickname, client.t("Nickname is already in use")) return false } else if err != nil { diff --git a/irc/numerics.go b/irc/numerics.go index 182235ca..d8cc6b03 100644 --- a/irc/numerics.go +++ b/irc/numerics.go @@ -195,5 +195,6 @@ const ( ERR_NOLANGUAGE = "982" // draft numerics + ERR_CANNOT_RESUME = "999" ) diff --git a/irc/server.go b/irc/server.go index 7da27b69..6718fcfd 100644 --- a/irc/server.go +++ b/irc/server.go @@ -9,7 +9,6 @@ import ( "bufio" "crypto/tls" "encoding/base64" - "errors" "fmt" "log" "math/rand" @@ -43,8 +42,6 @@ var ( // common error responses couldNotParseIPMsg, _ = (&[]ircmsg.IrcMessage{ircmsg.MakeMessage(nil, "", "ERROR", "Unable to parse your IP address")}[0]).Line() - RenamePrivsNeeded = errors.New("Only chanops can rename channels") - // supportedUserModesString acts as a cache for when we introduce users supportedUserModesString = modes.SupportedUserModes.String() // supportedChannelModesString acts as a cache for when we introduce users @@ -349,10 +346,10 @@ func (server *Server) createListener(addr string, tlsConfig *tls.Config) *Listen // make listener var listener net.Listener var err error - optional_unix_prefix := "unix:" - optional_prefix_len := len(optional_unix_prefix) - if len(addr) >= optional_prefix_len && strings.ToLower(addr[0:optional_prefix_len]) == optional_unix_prefix { - addr = addr[optional_prefix_len:] + optionalUnixPrefix := "unix:" + optionalPrefixLen := len(optionalUnixPrefix) + if len(addr) >= optionalPrefixLen && strings.ToLower(addr[0:optionalPrefixLen]) == optionalUnixPrefix { + addr = addr[optionalPrefixLen:] if len(addr) == 0 || addr[0] != '/' { log.Fatal("Bad unix socket address", addr) } @@ -492,7 +489,7 @@ func (server *Server) tryRegister(c *Client) { oldModes := myModes.String() if 0 < len(oldModes) { params := []string{channel.name, "+" + oldModes} - for _ = range oldModes { + for range oldModes { params = append(params, c.nick) } diff --git a/irc/socket.go b/irc/socket.go index 1da4a1b3..e9122086 100644 --- a/irc/socket.go +++ b/irc/socket.go @@ -9,7 +9,6 @@ import ( "crypto/sha256" "crypto/tls" "encoding/hex" - "errors" "io" "net" "strings" @@ -18,8 +17,6 @@ import ( ) var ( - errNotTLS = errors.New("Not a TLS connection") - errNoPeerCerts = errors.New("Client did not provide a certificate") handshakeTimeout, _ = time.ParseDuration("5s") ) diff --git a/irc/strings.go b/irc/strings.go index 2d2cf7c1..2ccea99c 100644 --- a/irc/strings.go +++ b/irc/strings.go @@ -6,7 +6,6 @@ package irc import ( - "errors" "strings" "golang.org/x/text/secure/precis" @@ -16,12 +15,6 @@ const ( casemappingName = "rfc8265" ) -var ( - errCouldNotStabilize = errors.New("Could not stabilize string while casefolding") - errInvalidCharacter = errors.New("Invalid character") - errEmpty = errors.New("String is empty") -) - // Casefold returns a casefolded string, without doing any name or channel character checks. func Casefold(str string) (string, error) { var err error @@ -51,7 +44,7 @@ func CasefoldChannel(name string) (string, error) { if err != nil { return "", err } else if len(lowered) == 0 { - return "", errEmpty + return "", errStringIsEmpty } if lowered[0] != '#' { @@ -76,7 +69,7 @@ func CasefoldName(name string) (string, error) { if err != nil { return "", err } else if len(lowered) == 0 { - return "", errEmpty + return "", errStringIsEmpty } // space can't be used