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)
}
func (channel *Channel) Id() string {
func (channel Channel) Id() string {
return channel.name
}
func (channel *Channel) PublicId() string {
func (channel Channel) PublicId() string {
return channel.name
}
func (channel Channel) Commands() chan<- ChannelCommand {
return channel.commands
}
//
// commands
//

View File

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

View File

@ -6,8 +6,32 @@ import (
"strings"
)
type Command interface {
Client() *Client
HandleServer(*Server)
}
type EditableCommand interface {
Command
SetClient(*Client)
}
var (
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 {
@ -25,28 +49,6 @@ func (base *BaseCommand) SetClient(c *Client) {
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) {
command, args := parseLine(line)
constructor := parseCommandFuncs[command]

View File

@ -12,6 +12,11 @@ type Identifier interface {
Nick() string
}
type Replier interface {
Identifier
Replies() chan<- Reply
}
type Reply interface {
String(client *Client) string
Source() Identifier
@ -30,24 +35,24 @@ func NewBasicReply(source Identifier, code string,
return &BasicReply{source, code, fullMessage}
}
func (reply *BasicReply) String(client *Client) string {
func (reply BasicReply) String(client *Client) string {
return reply.message
}
func (reply *BasicReply) Source() Identifier {
func (reply BasicReply) Source() Identifier {
return reply.source
}
type NumericReply struct {
*BasicReply
BasicReply
}
func NewNumericReply(source Identifier, code string,
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(),
reply.message)
}

View File

@ -12,11 +12,6 @@ type ChannelNameMap map[string]*Channel
type UserNameMap map[string]*User
type ServiceNameMap map[string]*Service
type Command interface {
Client() *Client
HandleServer(*Server)
}
type Server struct {
hostname string
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.
func (s *Server) InterestedUsers(fromUser *User) UserSet {
func (s Server) InterestedUsers(fromUser *User) UserSet {
users := make(UserSet)
users.Add(fromUser)
for channel := range fromUser.channels {
@ -102,20 +97,20 @@ func (s *Server) tryRegister(c *Client) {
c.registered = true
replies := []Reply{RplWelcome(s, c), RplYourHost(s, c), RplCreated(s), RplMyInfo(s)}
for _, reply := range replies {
c.replies <- reply
c.Replies() <- reply
}
}
}
func (s *Server) Id() string {
func (s Server) Id() string {
return s.hostname
}
func (s *Server) PublicId() string {
func (s Server) PublicId() string {
return s.Id()
}
func (s *Server) Nick() string {
func (s Server) Nick() string {
return s.name
}
@ -128,11 +123,11 @@ func (s *Server) DeleteChannel(channel *Channel) {
//
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) {
m.Client().replies <- RplPong(s)
m.Client().Replies() <- RplPong(s)
}
func (m *PongCommand) HandleServer(s *Server) {
@ -142,7 +137,7 @@ func (m *PongCommand) HandleServer(s *Server) {
func (m *PassCommand) HandleServer(s *Server) {
err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password))
if err != nil {
m.Client().replies <- ErrPasswdMismatch(s)
m.Client().Replies() <- ErrPasswdMismatch(s)
return
}
@ -153,19 +148,19 @@ func (m *PassCommand) HandleServer(s *Server) {
func (m *NickCommand) HandleServer(s *Server) {
c := m.Client()
if c.user == nil {
c.replies <- RplNick(c, m.nickname)
c.Replies() <- RplNick(c, m.nickname)
c.nick = m.nickname
s.tryRegister(c)
return
}
c.user.replies <- ErrNoPrivileges(s)
c.user.Replies() <- ErrNoPrivileges(s)
}
func (m *UserMsgCommand) HandleServer(s *Server) {
c := m.Client()
if c.username != "" {
c.replies <- ErrAlreadyRegistered(s)
c.Replies() <- ErrAlreadyRegistered(s)
return
}
@ -180,7 +175,7 @@ func (m *QuitCommand) HandleServer(s *Server) {
if user != nil {
reply := RplQuit(c, m.message)
for user := range s.InterestedUsers(c.user) {
user.replies <- reply
user.Replies() <- reply
}
}
c.conn.Close()
@ -194,7 +189,7 @@ func (m *QuitCommand) HandleServer(s *Server) {
BaseCommand: BaseCommand{c},
}
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 {
for name := range m.channels {
c.replies <- ErrNoSuchChannel(s, name)
c.Replies() <- ErrNoSuchChannel(s, name)
}
return
}
@ -214,13 +209,13 @@ func (m *JoinCommand) HandleServer(s *Server) {
BaseCommand: BaseCommand{c},
}
for channel := range c.user.channels {
channel.commands <- cmd
channel.Commands() <- cmd
}
return
}
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 {
for _, chname := range m.channels {
m.Client().replies <- ErrNoSuchChannel(s, chname)
m.Client().Replies() <- ErrNoSuchChannel(s, chname)
}
return
}
@ -238,11 +233,11 @@ func (m *PartCommand) HandleServer(s *Server) {
channel := s.channels[chname]
if channel == nil {
user.replies <- ErrNoSuchChannel(s, channel.name)
user.Replies() <- ErrNoSuchChannel(s, channel.name)
continue
}
channel.commands <- m
channel.Commands() <- m
}
}
@ -250,52 +245,52 @@ func (m *TopicCommand) HandleServer(s *Server) {
user := m.Client().user
if user == nil {
m.Client().replies <- ErrNoSuchChannel(s, m.channel)
m.Client().Replies() <- ErrNoSuchChannel(s, m.channel)
return
}
channel := s.channels[m.channel]
if channel == nil {
user.replies <- ErrNoSuchChannel(s, m.channel)
user.Replies() <- ErrNoSuchChannel(s, m.channel)
return
}
channel.commands <- m
channel.Commands() <- m
}
func (m *PrivMsgCommand) HandleServer(s *Server) {
service := s.services[m.target]
if service != nil {
service.commands <- m
service.Commands() <- m
return
}
user := m.Client().user
if user == nil {
m.Client().replies <- ErrNoSuchNick(s, m.target)
m.Client().Replies() <- ErrNoSuchNick(s, m.target)
return
}
if m.TargetIsChannel() {
channel := s.channels[m.target]
if channel == nil {
user.replies <- ErrNoSuchChannel(s, m.target)
user.Replies() <- ErrNoSuchChannel(s, m.target)
return
}
channel.commands <- m
channel.Commands() <- m
return
}
target := s.users[m.target]
if target == nil {
user.replies <- ErrNoSuchNick(s, m.target)
user.Replies() <- ErrNoSuchNick(s, m.target)
return
}
target.commands <- m
target.Commands() <- m
}
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
}
func (service *Service) HandleMsg(m *PrivMsgCommand) {
}
func (service *Service) HandleMsg(m *PrivMsgCommand) {}
func (service *Service) receiveCommands(commands <-chan ServiceCommand) {
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)
}
func (service *Service) PublicId() string {
func (service Service) PublicId() string {
return service.Id()
}
func (service *Service) Nick() string {
func (service Service) Nick() string {
return service.name
}
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 {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
panic("bcrypt failed; cannot generate password hash")
}
commands := make(chan UserCommand)
replies := make(chan Reply)
user := &User{
nick: nick,
hash: hash,
server: server,
clients: make(ClientSet),
channels: make(ChannelSet),
replies: replies,
}
user.SetPassword(password)
go user.receiveCommands(commands)
go user.receiveReplies(replies)
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) {
for command := range commands {
log.Printf("%s %T %+v", user.Id(), command, command)
@ -63,25 +67,29 @@ func (user *User) receiveReplies(replies <-chan Reply) {
for reply := range replies {
log.Printf("%s %T %+v", user.Id(), reply, reply)
for client := range user.clients {
client.replies <- reply
client.Replies() <- reply
}
}
}
// Identifier
func (user *User) Id() string {
func (user User) Id() string {
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()
}
func (user *User) Nick() string {
func (user User) Nick() string {
return user.nick
}
func (user User) Commands() chan<- UserCommand {
return user.commands
}
func (user *User) Login(c *Client, nick string, password string) bool {
if nick != c.nick {
return false
@ -93,7 +101,7 @@ func (user *User) Login(c *Client, nick string, password string) bool {
err := bcrypt.CompareHashAndPassword(user.hash, []byte(password))
if err != nil {
c.replies <- ErrNoPrivileges(user.server)
c.Replies() <- ErrNoPrivileges(user.server)
return false
}
@ -101,8 +109,8 @@ func (user *User) Login(c *Client, nick string, password string) bool {
c.user = user
for channel := range user.channels {
channel.GetTopic(c)
c.replies <- RplNamReply(channel)
c.replies <- RplEndOfNames(channel.server)
c.Replies() <- RplNamReply(channel)
c.Replies() <- RplEndOfNames(channel.server)
}
return true
}
@ -115,11 +123,11 @@ func (user *User) LogoutClient(c *Client) bool {
return false
}
func (user *User) HasClients() bool {
func (user User) HasClients() bool {
return len(user.clients) > 0
}
func (user *User) Replies() chan<- Reply {
func (user User) Replies() chan<- Reply {
return user.replies
}
@ -128,5 +136,5 @@ func (user *User) Replies() chan<- Reply {
//
func (m *PrivMsgCommand) HandleUser(user *User) {
user.replies <- RplPrivMsg(m.Client(), user, m.message)
user.Replies() <- RplPrivMsg(m.Client(), user, m.message)
}