Mostly style stuff.

This commit is contained in:
Jeremy Latt 2013-05-09 11:05:10 -07:00
parent 39f815df01
commit 65af2b4320
7 changed files with 112 additions and 100 deletions

View File

@ -89,14 +89,18 @@ func (channel *Channel) GetTopic(replier Replier) {
replier.Replies() <- RplTopic(channel) replier.Replies() <- RplTopic(channel)
} }
func (channel *Channel) Id() string { func (channel Channel) Id() string {
return channel.name return channel.name
} }
func (channel *Channel) PublicId() string { func (channel Channel) PublicId() string {
return channel.name return channel.name
} }
func (channel Channel) Commands() chan<- ChannelCommand {
return channel.commands
}
// //
// commands // commands
// //

View File

@ -7,11 +7,6 @@ import (
"time" "time"
) )
type Replier interface {
Identifier
Replies() chan<- Reply
}
type Client struct { type Client struct {
conn net.Conn conn net.Conn
username string username string
@ -53,7 +48,7 @@ func (c *Client) readConn(recv <-chan string) {
m, err := ParseCommand(str) m, err := ParseCommand(str)
if err != nil { if err != nil {
c.replies <- ErrNeedMoreParams(c.server, str) c.Replies() <- ErrNeedMoreParams(c.server, str)
continue continue
} }
@ -70,15 +65,15 @@ func (c *Client) writeConn(write chan<- string, replies <-chan Reply) {
} }
} }
func (c *Client) Replies() chan<- Reply { func (c Client) Replies() chan<- Reply {
return c.replies return c.replies
} }
func (c *Client) Server() *Server { func (c Client) Server() *Server {
return c.server return c.server
} }
func (c *Client) Nick() string { func (c Client) Nick() string {
if c.user != nil { if c.user != nil {
return c.user.nick return c.user.nick
} }
@ -90,33 +85,33 @@ func (c *Client) Nick() string {
return "*" return "*"
} }
func (c *Client) UModeString() string { func (c Client) UModeString() string {
return "" return ""
} }
func (c *Client) HasNick() bool { func (c Client) HasNick() bool {
return c.nick != "" return c.nick != ""
} }
func (c *Client) HasUser() bool { func (c Client) HasUser() bool {
return c.username != "" return c.username != ""
} }
func (c *Client) Username() string { func (c Client) Username() string {
if c.HasUser() { if c.HasUser() {
return c.username return c.username
} }
return "*" return "*"
} }
func (c *Client) UserHost() string { func (c Client) UserHost() string {
return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Username(), c.hostname) return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Username(), c.hostname)
} }
func (c *Client) Id() string { func (c Client) Id() string {
return c.UserHost() return c.UserHost()
} }
func (c *Client) PublicId() string { func (c Client) PublicId() string {
return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Nick(), c.server.Id()) return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Nick(), c.server.Id())
} }

View File

@ -6,8 +6,32 @@ import (
"strings" "strings"
) )
type Command interface {
Client() *Client
HandleServer(*Server)
}
type EditableCommand interface {
Command
SetClient(*Client)
}
var ( var (
NotEnoughArgsError = errors.New("not enough arguments") NotEnoughArgsError = errors.New("not enough arguments")
ErrParseCommand = errors.New("failed to parse message")
parseCommandFuncs = map[string]func([]string) (EditableCommand, error){
"JOIN": NewJoinCommand,
"MODE": NewModeCommand,
"NICK": NewNickCommand,
"PART": NewPartCommand,
"PASS": NewPassCommand,
"PING": NewPingCommand,
"PONG": NewPongCommand,
"PRIVMSG": NewPrivMsgCommand,
"QUIT": NewQuitCommand,
"TOPIC": NewTopicCommand,
"USER": NewUserMsgCommand,
}
) )
type BaseCommand struct { type BaseCommand struct {
@ -25,28 +49,6 @@ func (base *BaseCommand) SetClient(c *Client) {
base.client = c base.client = c
} }
type EditableCommand interface {
Command
SetClient(*Client)
}
var (
ErrParseCommand = errors.New("failed to parse message")
parseCommandFuncs = map[string]func([]string) (EditableCommand, error){
"JOIN": NewJoinCommand,
"MODE": NewModeCommand,
"NICK": NewNickCommand,
"PART": NewPartCommand,
"PASS": NewPassCommand,
"PING": NewPingCommand,
"PONG": NewPongCommand,
"PRIVMSG": NewPrivMsgCommand,
"QUIT": NewQuitCommand,
"TOPIC": NewTopicCommand,
"USER": NewUserMsgCommand,
}
)
func ParseCommand(line string) (EditableCommand, error) { func ParseCommand(line string) (EditableCommand, error) {
command, args := parseLine(line) command, args := parseLine(line)
constructor := parseCommandFuncs[command] constructor := parseCommandFuncs[command]

View File

@ -12,6 +12,11 @@ type Identifier interface {
Nick() string Nick() string
} }
type Replier interface {
Identifier
Replies() chan<- Reply
}
type Reply interface { type Reply interface {
String(client *Client) string String(client *Client) string
Source() Identifier Source() Identifier
@ -30,24 +35,24 @@ func NewBasicReply(source Identifier, code string,
return &BasicReply{source, code, fullMessage} return &BasicReply{source, code, fullMessage}
} }
func (reply *BasicReply) String(client *Client) string { func (reply BasicReply) String(client *Client) string {
return reply.message return reply.message
} }
func (reply *BasicReply) Source() Identifier { func (reply BasicReply) Source() Identifier {
return reply.source return reply.source
} }
type NumericReply struct { type NumericReply struct {
*BasicReply BasicReply
} }
func NewNumericReply(source Identifier, code string, func NewNumericReply(source Identifier, code string,
format string, args ...interface{}) *NumericReply { format string, args ...interface{}) *NumericReply {
return &NumericReply{&BasicReply{source, code, fmt.Sprintf(format, args...)}} return &NumericReply{BasicReply{source, code, fmt.Sprintf(format, args...)}}
} }
func (reply *NumericReply) String(client *Client) string { func (reply NumericReply) String(client *Client) string {
return fmt.Sprintf(":%s %s %s %s\r\n", reply.source.Id(), reply.code, client.Nick(), return fmt.Sprintf(":%s %s %s %s\r\n", reply.source.Id(), reply.code, client.Nick(),
reply.message) reply.message)
} }

View File

@ -12,11 +12,6 @@ type ChannelNameMap map[string]*Channel
type UserNameMap map[string]*User type UserNameMap map[string]*User
type ServiceNameMap map[string]*Service type ServiceNameMap map[string]*Service
type Command interface {
Client() *Client
HandleServer(*Server)
}
type Server struct { type Server struct {
hostname string hostname string
ctime time.Time ctime time.Time
@ -83,7 +78,7 @@ func (s *Server) GetOrMakeChannel(name string) *Channel {
} }
// Send a message to clients of channels fromClient is a member. // Send a message to clients of channels fromClient is a member.
func (s *Server) InterestedUsers(fromUser *User) UserSet { func (s Server) InterestedUsers(fromUser *User) UserSet {
users := make(UserSet) users := make(UserSet)
users.Add(fromUser) users.Add(fromUser)
for channel := range fromUser.channels { for channel := range fromUser.channels {
@ -102,20 +97,20 @@ func (s *Server) tryRegister(c *Client) {
c.registered = true c.registered = true
replies := []Reply{RplWelcome(s, c), RplYourHost(s, c), RplCreated(s), RplMyInfo(s)} replies := []Reply{RplWelcome(s, c), RplYourHost(s, c), RplCreated(s), RplMyInfo(s)}
for _, reply := range replies { for _, reply := range replies {
c.replies <- reply c.Replies() <- reply
} }
} }
} }
func (s *Server) Id() string { func (s Server) Id() string {
return s.hostname return s.hostname
} }
func (s *Server) PublicId() string { func (s Server) PublicId() string {
return s.Id() return s.Id()
} }
func (s *Server) Nick() string { func (s Server) Nick() string {
return s.name return s.name
} }
@ -128,11 +123,11 @@ func (s *Server) DeleteChannel(channel *Channel) {
// //
func (m *UnknownCommand) HandleServer(s *Server) { func (m *UnknownCommand) HandleServer(s *Server) {
m.Client().replies <- ErrUnknownCommand(s, m.command) m.Client().Replies() <- ErrUnknownCommand(s, m.command)
} }
func (m *PingCommand) HandleServer(s *Server) { func (m *PingCommand) HandleServer(s *Server) {
m.Client().replies <- RplPong(s) m.Client().Replies() <- RplPong(s)
} }
func (m *PongCommand) HandleServer(s *Server) { func (m *PongCommand) HandleServer(s *Server) {
@ -142,7 +137,7 @@ func (m *PongCommand) HandleServer(s *Server) {
func (m *PassCommand) HandleServer(s *Server) { func (m *PassCommand) HandleServer(s *Server) {
err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password)) err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password))
if err != nil { if err != nil {
m.Client().replies <- ErrPasswdMismatch(s) m.Client().Replies() <- ErrPasswdMismatch(s)
return return
} }
@ -153,19 +148,19 @@ func (m *PassCommand) HandleServer(s *Server) {
func (m *NickCommand) HandleServer(s *Server) { func (m *NickCommand) HandleServer(s *Server) {
c := m.Client() c := m.Client()
if c.user == nil { if c.user == nil {
c.replies <- RplNick(c, m.nickname) c.Replies() <- RplNick(c, m.nickname)
c.nick = m.nickname c.nick = m.nickname
s.tryRegister(c) s.tryRegister(c)
return return
} }
c.user.replies <- ErrNoPrivileges(s) c.user.Replies() <- ErrNoPrivileges(s)
} }
func (m *UserMsgCommand) HandleServer(s *Server) { func (m *UserMsgCommand) HandleServer(s *Server) {
c := m.Client() c := m.Client()
if c.username != "" { if c.username != "" {
c.replies <- ErrAlreadyRegistered(s) c.Replies() <- ErrAlreadyRegistered(s)
return return
} }
@ -180,7 +175,7 @@ func (m *QuitCommand) HandleServer(s *Server) {
if user != nil { if user != nil {
reply := RplQuit(c, m.message) reply := RplQuit(c, m.message)
for user := range s.InterestedUsers(c.user) { for user := range s.InterestedUsers(c.user) {
user.replies <- reply user.Replies() <- reply
} }
} }
c.conn.Close() c.conn.Close()
@ -194,7 +189,7 @@ func (m *QuitCommand) HandleServer(s *Server) {
BaseCommand: BaseCommand{c}, BaseCommand: BaseCommand{c},
} }
for channel := range user.channels { for channel := range user.channels {
channel.commands <- cmd channel.Commands() <- cmd
} }
} }
} }
@ -204,7 +199,7 @@ func (m *JoinCommand) HandleServer(s *Server) {
if c.user == nil { if c.user == nil {
for name := range m.channels { for name := range m.channels {
c.replies <- ErrNoSuchChannel(s, name) c.Replies() <- ErrNoSuchChannel(s, name)
} }
return return
} }
@ -214,13 +209,13 @@ func (m *JoinCommand) HandleServer(s *Server) {
BaseCommand: BaseCommand{c}, BaseCommand: BaseCommand{c},
} }
for channel := range c.user.channels { for channel := range c.user.channels {
channel.commands <- cmd channel.Commands() <- cmd
} }
return return
} }
for name := range m.channels { for name := range m.channels {
s.GetOrMakeChannel(name).commands <- m s.GetOrMakeChannel(name).Commands() <- m
} }
} }
@ -229,7 +224,7 @@ func (m *PartCommand) HandleServer(s *Server) {
if user == nil { if user == nil {
for _, chname := range m.channels { for _, chname := range m.channels {
m.Client().replies <- ErrNoSuchChannel(s, chname) m.Client().Replies() <- ErrNoSuchChannel(s, chname)
} }
return return
} }
@ -238,11 +233,11 @@ func (m *PartCommand) HandleServer(s *Server) {
channel := s.channels[chname] channel := s.channels[chname]
if channel == nil { if channel == nil {
user.replies <- ErrNoSuchChannel(s, channel.name) user.Replies() <- ErrNoSuchChannel(s, channel.name)
continue continue
} }
channel.commands <- m channel.Commands() <- m
} }
} }
@ -250,52 +245,52 @@ func (m *TopicCommand) HandleServer(s *Server) {
user := m.Client().user user := m.Client().user
if user == nil { if user == nil {
m.Client().replies <- ErrNoSuchChannel(s, m.channel) m.Client().Replies() <- ErrNoSuchChannel(s, m.channel)
return return
} }
channel := s.channels[m.channel] channel := s.channels[m.channel]
if channel == nil { if channel == nil {
user.replies <- ErrNoSuchChannel(s, m.channel) user.Replies() <- ErrNoSuchChannel(s, m.channel)
return return
} }
channel.commands <- m channel.Commands() <- m
} }
func (m *PrivMsgCommand) HandleServer(s *Server) { func (m *PrivMsgCommand) HandleServer(s *Server) {
service := s.services[m.target] service := s.services[m.target]
if service != nil { if service != nil {
service.commands <- m service.Commands() <- m
return return
} }
user := m.Client().user user := m.Client().user
if user == nil { if user == nil {
m.Client().replies <- ErrNoSuchNick(s, m.target) m.Client().Replies() <- ErrNoSuchNick(s, m.target)
return return
} }
if m.TargetIsChannel() { if m.TargetIsChannel() {
channel := s.channels[m.target] channel := s.channels[m.target]
if channel == nil { if channel == nil {
user.replies <- ErrNoSuchChannel(s, m.target) user.Replies() <- ErrNoSuchChannel(s, m.target)
return return
} }
channel.commands <- m channel.Commands() <- m
return return
} }
target := s.users[m.target] target := s.users[m.target]
if target == nil { if target == nil {
user.replies <- ErrNoSuchNick(s, m.target) user.Replies() <- ErrNoSuchNick(s, m.target)
return return
} }
target.commands <- m target.Commands() <- m
} }
func (m *ModeCommand) HandleServer(s *Server) { func (m *ModeCommand) HandleServer(s *Server) {
m.Client().replies <- RplUModeIs(s, m.Client()) m.Client().Replies() <- RplUModeIs(s, m.Client())
} }

View File

@ -28,8 +28,7 @@ func NewService(s *Server, name string) *Service {
return service return service
} }
func (service *Service) HandleMsg(m *PrivMsgCommand) { func (service *Service) HandleMsg(m *PrivMsgCommand) {}
}
func (service *Service) receiveCommands(commands <-chan ServiceCommand) { func (service *Service) receiveCommands(commands <-chan ServiceCommand) {
for command := range commands { for command := range commands {
@ -38,20 +37,24 @@ func (service *Service) receiveCommands(commands <-chan ServiceCommand) {
} }
} }
func (service *Service) Id() string { func (service Service) Id() string {
return fmt.Sprintf("%s!%s@%s", service.name, service.name, service.server.name) return fmt.Sprintf("%s!%s@%s", service.name, service.name, service.server.name)
} }
func (service *Service) PublicId() string { func (service Service) PublicId() string {
return service.Id() return service.Id()
} }
func (service *Service) Nick() string { func (service Service) Nick() string {
return service.name return service.name
} }
func (service *Service) Reply(client *Client, message string) { func (service *Service) Reply(client *Client, message string) {
client.replies <- RplPrivMsg(service, client, message) client.Replies() <- RplPrivMsg(service, client, message)
}
func (service Service) Commands() chan<- ServiceCommand {
return service.commands
} }
// //

View File

@ -32,25 +32,29 @@ func (set UserSet) Remove(user *User) {
} }
func NewUser(nick string, password string, server *Server) *User { func NewUser(nick string, password string, server *Server) *User {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
panic("bcrypt failed; cannot generate password hash")
}
commands := make(chan UserCommand) commands := make(chan UserCommand)
replies := make(chan Reply) replies := make(chan Reply)
user := &User{ user := &User{
nick: nick, nick: nick,
hash: hash,
server: server, server: server,
clients: make(ClientSet), clients: make(ClientSet),
channels: make(ChannelSet), channels: make(ChannelSet),
replies: replies, replies: replies,
} }
user.SetPassword(password)
go user.receiveCommands(commands) go user.receiveCommands(commands)
go user.receiveReplies(replies) go user.receiveReplies(replies)
return user return user
} }
func (user *User) SetPassword(password string) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
panic("bcrypt failed; cannot generate password hash")
}
user.hash = hash
}
func (user *User) receiveCommands(commands <-chan UserCommand) { func (user *User) receiveCommands(commands <-chan UserCommand) {
for command := range commands { for command := range commands {
log.Printf("%s %T %+v", user.Id(), command, command) log.Printf("%s %T %+v", user.Id(), command, command)
@ -63,25 +67,29 @@ func (user *User) receiveReplies(replies <-chan Reply) {
for reply := range replies { for reply := range replies {
log.Printf("%s %T %+v", user.Id(), reply, reply) log.Printf("%s %T %+v", user.Id(), reply, reply)
for client := range user.clients { for client := range user.clients {
client.replies <- reply client.Replies() <- reply
} }
} }
} }
// Identifier // Identifier
func (user *User) Id() string { func (user User) Id() string {
return fmt.Sprintf("%s!%s@%s", user.nick, user.nick, user.server.Id()) return fmt.Sprintf("%s!%s@%s", user.nick, user.nick, user.server.Id())
} }
func (user *User) PublicId() string { func (user User) PublicId() string {
return user.Id() return user.Id()
} }
func (user *User) Nick() string { func (user User) Nick() string {
return user.nick return user.nick
} }
func (user User) Commands() chan<- UserCommand {
return user.commands
}
func (user *User) Login(c *Client, nick string, password string) bool { func (user *User) Login(c *Client, nick string, password string) bool {
if nick != c.nick { if nick != c.nick {
return false return false
@ -93,7 +101,7 @@ func (user *User) Login(c *Client, nick string, password string) bool {
err := bcrypt.CompareHashAndPassword(user.hash, []byte(password)) err := bcrypt.CompareHashAndPassword(user.hash, []byte(password))
if err != nil { if err != nil {
c.replies <- ErrNoPrivileges(user.server) c.Replies() <- ErrNoPrivileges(user.server)
return false return false
} }
@ -101,8 +109,8 @@ func (user *User) Login(c *Client, nick string, password string) bool {
c.user = user c.user = user
for channel := range user.channels { for channel := range user.channels {
channel.GetTopic(c) channel.GetTopic(c)
c.replies <- RplNamReply(channel) c.Replies() <- RplNamReply(channel)
c.replies <- RplEndOfNames(channel.server) c.Replies() <- RplEndOfNames(channel.server)
} }
return true return true
} }
@ -115,11 +123,11 @@ func (user *User) LogoutClient(c *Client) bool {
return false return false
} }
func (user *User) HasClients() bool { func (user User) HasClients() bool {
return len(user.clients) > 0 return len(user.clients) > 0
} }
func (user *User) Replies() chan<- Reply { func (user User) Replies() chan<- Reply {
return user.replies return user.replies
} }
@ -128,5 +136,5 @@ func (user *User) Replies() chan<- Reply {
// //
func (m *PrivMsgCommand) HandleUser(user *User) { func (m *PrivMsgCommand) HandleUser(user *User) {
user.replies <- RplPrivMsg(m.Client(), user, m.message) user.Replies() <- RplPrivMsg(m.Client(), user, m.message)
} }