diff --git a/irc/reply.go b/irc/reply.go index 8f1af885..7df09b25 100644 --- a/irc/reply.go +++ b/irc/reply.go @@ -15,8 +15,14 @@ func joinedLen(names []string) int { } type BaseReply struct { - source Identifier + id string message string + source Identifier +} + +func (reply *BaseReply) SetSource(source Identifier) { + reply.id = source.Id() + reply.source = source } func (reply *BaseReply) Source() Identifier { @@ -33,22 +39,22 @@ func NewStringReply(source Identifier, code string, reply := &StringReply{ code: code, } + reply.SetSource(source) reply.message = fmt.Sprintf(format, args...) - reply.source = source return reply } func (reply *StringReply) Format(client *Client) []string { message := fmt.Sprintf("%s %s", reply.code, reply.message) if Identifier(client.server) != reply.source { - message = fmt.Sprintf(":%s %s", reply.source.Id(), message) + message = fmt.Sprintf(":%s %s", reply.id, message) } return []string{message} } func (reply *StringReply) String() string { return fmt.Sprintf("Reply(source=%s, code=%s, message=%s)", - reply.source, reply.code, reply.message) + reply.id, reply.code, reply.message) } type NumericReply struct { @@ -61,8 +67,8 @@ func NewNumericReply(source Identifier, code int, format string, reply := &NumericReply{ code: code, } + reply.SetSource(source) reply.message = fmt.Sprintf(format, args...) - reply.source = source return reply } @@ -70,14 +76,14 @@ func (reply *NumericReply) Format(client *Client) []string { message := fmt.Sprintf("%03d %s %s", reply.code, client.Nick(), reply.message) if Identifier(client.server) != reply.source { - message = fmt.Sprintf(":%s %s", reply.source.Id(), message) + message = fmt.Sprintf(":%s %s", reply.id, message) } return []string{message} } func (reply *NumericReply) String() string { return fmt.Sprintf("Reply(source=%s, code=%d, message=%s)", - reply.source, reply.code, reply.message) + reply.id, reply.code, reply.message) } // names reply @@ -88,12 +94,11 @@ type NamesReply struct { } func NewNamesReply(channel *Channel) Reply { - return &NamesReply{ - BaseReply: &BaseReply{ - source: channel, - }, + reply := &NamesReply{ channel: channel, } + reply.SetSource(channel) + return reply } func (reply *NamesReply) Format(client *Client) []string { @@ -401,3 +406,7 @@ func ErrChanOPrivIsNeeded(channel *Channel) Reply { func ErrNoMOTD(server *Server) Reply { return NewNumericReply(server, ERR_NOMOTD, ":MOTD File is missing") } + +func ErrNoNicknameGiven(server *Server) Reply { + return NewNumericReply(server, ERR_NONICKNAMEGIVEN, ":No nickname given") +} diff --git a/irc/server.go b/irc/server.go index aeca8847..7eb018d8 100644 --- a/irc/server.go +++ b/irc/server.go @@ -233,11 +233,17 @@ func (m *PassCommand) HandleServer(s *Server) { func (m *NickCommand) HandleServer(s *Server) { c := m.Client() + if m.nickname == "" { + c.Reply(ErrNoNicknameGiven(s)) + return + } + if s.clients[m.nickname] != nil { c.Reply(ErrNickNameInUse(s, m.nickname)) return } + // Make reply before changing nick. reply := RplNick(c, m.nickname) s.clients.Remove(c) diff --git a/irc/types.go b/irc/types.go index d62f4826..2cf20b86 100644 --- a/irc/types.go +++ b/irc/types.go @@ -1,6 +1,7 @@ package irc import ( + "errors" "fmt" ) @@ -51,9 +52,17 @@ func (channels ChannelNameMap) Remove(channel *Channel) error { type ClientNameMap map[string]*Client +var ( + ErrNickMissing = errors.New("nick missing") + ErrNicknameInUse = errors.New("nickname in use") +) + func (clients ClientNameMap) Add(client *Client) error { + if !client.HasNick() { + return ErrNickMissing + } if clients[client.nick] != nil { - return fmt.Errorf("%s: already set", client.nick) + return ErrNicknameInUse } clients[client.nick] = client return nil