diff --git a/irc/accountreg.go b/irc/accountreg.go index eaae39e4..07211e1c 100644 --- a/irc/accountreg.go +++ b/irc/accountreg.go @@ -182,7 +182,7 @@ func accRegisterHandler(server *Server, client *Client, msg ircmsg.IrcMessage) b } } if credentialType == "certfp" && client.certfp == "" { - client.Send(nil, server.name, ERR_REG_INVALID_CRED_TYPE, client.nick, credentialType, callbackNamespace, "You are not using a certificiate") + client.Send(nil, server.name, ERR_REG_INVALID_CRED_TYPE, client.nick, credentialType, callbackNamespace, "You are not using a TLS certificate") removeFailedAccRegisterData(server.store, casefoldedAccount) return false } diff --git a/irc/capability.go b/irc/capability.go index 5284ce17..40542a27 100644 --- a/irc/capability.go +++ b/irc/capability.go @@ -14,22 +14,39 @@ import ( type Capability string const ( - AccountNotify Capability = "account-notify" - AccountTag Capability = "account-tag" - AwayNotify Capability = "away-notify" - CapNotify Capability = "cap-notify" - ChgHost Capability = "chghost" - EchoMessage Capability = "echo-message" - ExtendedJoin Capability = "extended-join" - InviteNotify Capability = "invite-notify" - MaxLine Capability = "draft/maxline" - MessageIDs Capability = "draft/message-ids" - MessageTags Capability = "draft/message-tags-0.2" - MultiPrefix Capability = "multi-prefix" - Rename Capability = "draft/rename" - SASL Capability = "sasl" - ServerTime Capability = "server-time" - STS Capability = "draft/sts" + // AccountNotify is this IRCv3 capability: http://ircv3.net/specs/extensions/account-notify-3.1.html + AccountNotify Capability = "account-notify" + // AccountTag is this IRCv3 capability: http://ircv3.net/specs/extensions/account-tag-3.2.html + AccountTag Capability = "account-tag" + // AwayNotify is this IRCv3 capability: http://ircv3.net/specs/extensions/away-notify-3.1.html + AwayNotify Capability = "away-notify" + // CapNotify is this IRCv3 capability: http://ircv3.net/specs/extensions/cap-notify-3.2.html + CapNotify Capability = "cap-notify" + // ChgHost is this IRCv3 capability: http://ircv3.net/specs/extensions/chghost-3.2.html + ChgHost Capability = "chghost" + // EchoMessage is this IRCv3 capability: http://ircv3.net/specs/extensions/echo-message-3.2.html + EchoMessage Capability = "echo-message" + // ExtendedJoin is this IRCv3 capability: http://ircv3.net/specs/extensions/extended-join-3.1.html + ExtendedJoin Capability = "extended-join" + // InviteNotify is this IRCv3 capability: http://ircv3.net/specs/extensions/invite-notify-3.2.html + InviteNotify Capability = "invite-notify" + // MaxLine is this proposed capability: https://github.com/DanielOaks/ircv3-specifications/blob/master+line-lengths/extensions/line-lengths.md + MaxLine Capability = "draft/maxline" + // MessageIDs is this draft IRCv3 capability: http://ircv3.net/specs/extensions/message-ids.html + MessageIDs Capability = "draft/message-ids" + // MessageTags is this draft IRCv3 capability: http://ircv3.net/specs/core/message-tags-3.3.html + MessageTags Capability = "draft/message-tags-0.2" + // MultiPrefix is this IRCv3 capability: http://ircv3.net/specs/extensions/multi-prefix-3.1.html + MultiPrefix Capability = "multi-prefix" + // Rename is this proposed capability: https://github.com/SaberUK/ircv3-specifications/blob/rename/extensions/rename.md + Rename Capability = "draft/rename" + // SASL is this IRCv3 capability: http://ircv3.net/specs/extensions/sasl-3.2.html + SASL Capability = "sasl" + // ServerTime is this IRCv3 capability: http://ircv3.net/specs/extensions/server-time-3.2.html + ServerTime Capability = "server-time" + // STS is this draft IRCv3 capability: http://ircv3.net/specs/core/sts-3.3.html + STS Capability = "draft/sts" + // UserhostInNames is this IRCv3 capability: http://ircv3.net/specs/extensions/userhost-in-names-3.2.html UserhostInNames Capability = "userhost-in-names" ) diff --git a/irc/client.go b/irc/client.go index c5b04b14..3ceb228a 100644 --- a/irc/client.go +++ b/irc/client.go @@ -23,14 +23,19 @@ import ( ) const ( - IDLE_TIMEOUT = time.Minute + time.Second*30 // how long before a client is considered idle - QUIT_TIMEOUT = time.Minute // how long after idle before a client is kicked + // IdleTimeout is how long without traffic before a client's considered idle. + IdleTimeout = time.Minute + time.Second*30 + // QuitTimeout is how long without traffic (after they're considered idle) that clients are killed. + QuitTimeout = time.Minute + // IdentTimeoutSeconds is how many seconds before our ident (username) check times out. IdentTimeoutSeconds = 5 ) var ( - TIMEOUT_STATED_SECONDS = strconv.Itoa(int((IDLE_TIMEOUT + QUIT_TIMEOUT).Seconds())) - ErrNickAlreadySet = errors.New("Nickname is already set") + // TimeoutStatedSeconds is how many seconds before clients are timed out (IdleTimeout plus QuitTimeout). + TimeoutStatedSeconds = strconv.Itoa(int((IdleTimeout + QuitTimeout).Seconds())) + // ErrNickAlreadySet is a weird error that's sent when the server's consistency has been compromised. + ErrNickAlreadySet = errors.New("Nickname is already set") ) // Client is an IRC client. @@ -233,9 +238,9 @@ func (client *Client) Touch() { } if client.idleTimer == nil { - client.idleTimer = time.AfterFunc(IDLE_TIMEOUT, client.connectionIdle) + client.idleTimer = time.AfterFunc(IdleTimeout, client.connectionIdle) } else { - client.idleTimer.Reset(IDLE_TIMEOUT) + client.idleTimer.Reset(IdleTimeout) } } @@ -248,9 +253,9 @@ func (client *Client) connectionIdle() { client.Send(nil, "", "PING", client.nick) if client.quitTimer == nil { - client.quitTimer = time.AfterFunc(QUIT_TIMEOUT, client.connectionTimeout) + client.quitTimer = time.AfterFunc(QuitTimeout, client.connectionTimeout) } else { - client.quitTimer.Reset(QUIT_TIMEOUT) + client.quitTimer.Reset(QuitTimeout) } } @@ -258,7 +263,7 @@ func (client *Client) connectionIdle() { // ping or any other activity back from the client. When this happens we assume the // connection has died and remove the client from the network. func (client *Client) connectionTimeout() { - client.Quit(fmt.Sprintf("Ping timeout: %s seconds", TIMEOUT_STATED_SECONDS)) + client.Quit(fmt.Sprintf("Ping timeout: %s seconds", TimeoutStatedSeconds)) client.isQuitting = true } diff --git a/irc/config.go b/irc/config.go index 8d0b24cf..8a5dae7c 100644 --- a/irc/config.go +++ b/irc/config.go @@ -98,6 +98,7 @@ type OperConfig struct { Modes string } +// PasswordBytes returns the bytes represented by the password hash. func (conf *OperConfig) PasswordBytes() []byte { bytes, err := DecodePasswordHash(conf.Password) if err != nil { diff --git a/irc/help.go b/irc/help.go index b1006262..67f74584 100644 --- a/irc/help.go +++ b/irc/help.go @@ -15,9 +15,12 @@ import ( type HelpEntryType int const ( - CommandHelpEntry HelpEntryType = 0 + // CommandHelpEntry is a help entry explaining a client command. + CommandHelpEntry HelpEntryType = 0 + // InformationHelpEntry is a help entry explaining general server info. InformationHelpEntry HelpEntryType = 1 - ISupportHelpEntry HelpEntryType = 2 + // ISupportHelpEntry is a help entry explaining a specific RPL_ISUPPORT token. + ISupportHelpEntry HelpEntryType = 2 ) // HelpEntry represents an entry in the Help map. diff --git a/irc/logger/logger.go b/irc/logger/logger.go index 3ac28bae..7bf2b32b 100644 --- a/irc/logger/logger.go +++ b/irc/logger/logger.go @@ -32,6 +32,7 @@ const ( ) var ( + // LogLevelNames takes a config name and gives the real log level. LogLevelNames = map[string]Level{ "debug": LogDebug, "info": LogInfo, @@ -41,6 +42,7 @@ var ( "error": LogError, "errors": LogError, } + // LogLevelDisplayNames gives the display name to use for our log levels. LogLevelDisplayNames = map[Level]string{ LogDebug: "debug", LogInfo: "info", diff --git a/irc/modes.go b/irc/modes.go index 00675132..340bfafe 100644 --- a/irc/modes.go +++ b/irc/modes.go @@ -22,8 +22,11 @@ func (op ModeOp) String() string { } const ( - Add ModeOp = '+' - List ModeOp = '=' + // Add is used when adding the given key. + Add ModeOp = '+' + // List is used when listing modes (for instance, listing the current bans on a channel). + List ModeOp = '=' + // Remove is used when taking away the given key. Remove ModeOp = '-' ) @@ -105,6 +108,7 @@ const ( ) var ( + // SupportedUserModes are the user modes that we actually support (modifying). SupportedUserModes = Modes{ Away, Invisible, Operator, ServerNotice, UserRoleplaying, } @@ -135,6 +139,7 @@ var ( Halfop Mode = 'h' // arg Voice Mode = 'v' // arg + // SupportedChannelModes are the channel modes that we support. SupportedChannelModes = Modes{ BanMask, ExceptMask, InviteMask, InviteOnly, Key, NoOutside, OpOnlyTopic, Secret, UserLimit, ChanRoleplaying, @@ -142,6 +147,7 @@ var ( // supportedChannelModesString acts as a cache for when we introduce users supportedChannelModesString = SupportedChannelModes.String() + // DefaultChannelModes are enabled on brand new channels when they're created. DefaultChannelModes = Modes{ NoOutside, OpOnlyTopic, } diff --git a/irc/websocket.go b/irc/websocket.go index 2ccdc56a..fad90cc3 100644 --- a/irc/websocket.go +++ b/irc/websocket.go @@ -25,12 +25,14 @@ var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } +// WSContainer holds the websocket. type WSContainer struct { *websocket.Conn } -func (this WSContainer) Read(msg []byte) (int, error) { - ty, bytes, err := this.ReadMessage() +// Read reads new incoming messages. +func (ws WSContainer) Read(msg []byte) (int, error) { + ty, bytes, err := ws.ReadMessage() if ty == websocket.TextMessage { n := copy(msg, []byte(string(bytes)+"\r\n\r\n")) return n, err @@ -39,14 +41,16 @@ func (this WSContainer) Read(msg []byte) (int, error) { return 0, nil } -func (this WSContainer) Write(msg []byte) (int, error) { - err := this.WriteMessage(websocket.TextMessage, msg) +// Write writes lines out to the websocket. +func (ws WSContainer) Write(msg []byte) (int, error) { + err := ws.WriteMessage(websocket.TextMessage, msg) return len(msg), err } -func (this WSContainer) SetDeadline(t time.Time) error { - if err := this.SetWriteDeadline(t); err != nil { +// SetDeadline sets the read and write deadline on this websocket. +func (ws WSContainer) SetDeadline(t time.Time) error { + if err := ws.SetWriteDeadline(t); err != nil { return err } - return this.SetReadDeadline(t) + return ws.SetReadDeadline(t) } diff --git a/irc/whowas.go b/irc/whowas.go index f5ebbe8f..8f49eaae 100644 --- a/irc/whowas.go +++ b/irc/whowas.go @@ -8,6 +8,7 @@ import ( "sync" ) +// WhoWasList holds our list of prior clients (for use with the WHOWAS command). type WhoWasList struct { buffer []*WhoWas start int @@ -16,6 +17,7 @@ type WhoWasList struct { accessMutex sync.RWMutex } +// WhoWas is an entry in the WhoWasList. type WhoWas struct { nicknameCasefolded string nickname string @@ -24,12 +26,14 @@ type WhoWas struct { realname string } +// NewWhoWasList returns a new WhoWasList func NewWhoWasList(size uint) *WhoWasList { return &WhoWasList{ buffer: make([]*WhoWas, size+1), } } +// Append adds an entry to the WhoWasList. func (list *WhoWasList) Append(client *Client) { list.accessMutex.Lock() defer list.accessMutex.Unlock() @@ -47,6 +51,7 @@ func (list *WhoWasList) Append(client *Client) { } } +// Find tries to find an entry in our WhoWasList with the given details. func (list *WhoWasList) Find(nickname string, limit int64) []*WhoWas { list.accessMutex.RLock() defer list.accessMutex.RUnlock() @@ -81,7 +86,7 @@ func (list *WhoWasList) prev(index int) int { return index } -// Iterate the buffer in reverse. +// Each iterates the WhoWasList in reverse. func (list *WhoWasList) Each() <-chan *WhoWas { ch := make(chan *WhoWas) go func() {