3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-12-22 18:52:41 +01:00

break up types.go

- remove old interfaces, move to relevant files
- remove Phase in favor of a boolean flag
This commit is contained in:
Jeremy Latt 2014-03-12 17:52:25 -07:00
parent 0126edc7af
commit 2006aff9f7
6 changed files with 85 additions and 96 deletions

View File

@ -6,6 +6,12 @@ import (
"time" "time"
) )
const (
LOGIN_TIMEOUT = time.Minute / 2 // how long the client has to login
IDLE_TIMEOUT = time.Minute // how long before a client is considered idle
QUIT_TIMEOUT = time.Minute // how long after idle before a client is kicked
)
func IsNickname(nick string) bool { func IsNickname(nick string) bool {
return NicknameExpr.MatchString(nick) return NicknameExpr.MatchString(nick)
} }
@ -26,9 +32,9 @@ type Client struct {
idleTimer *time.Timer idleTimer *time.Timer
loginTimer *time.Timer loginTimer *time.Timer
nick string nick string
phase Phase
quitTimer *time.Timer quitTimer *time.Timer
realname string realname string
registered bool
server *Server server *Server
socket *Socket socket *Socket
username string username string
@ -45,7 +51,6 @@ func NewClient(server *Server, conn net.Conn) *Client {
commands: make(chan Command), commands: make(chan Command),
ctime: now, ctime: now,
flags: make(map[UserMode]bool), flags: make(map[UserMode]bool),
phase: Registration,
server: server, server: server,
} }
client.socket = NewSocket(conn, client.commands) client.socket = NewSocket(conn, client.commands)
@ -118,7 +123,10 @@ func (client *Client) Idle() {
} }
func (client *Client) Register() { func (client *Client) Register() {
client.phase = Normal if client.registered {
return
}
client.registered = true
client.loginTimer.Stop() client.loginTimer.Stop()
client.Touch() client.Touch()
} }

View File

@ -9,6 +9,13 @@ import (
"strings" "strings"
) )
type Command interface {
Client() *Client
Code() StringCode
SetClient(*Client)
SetCode(StringCode)
}
type checkPasswordCommand interface { type checkPasswordCommand interface {
LoadPassword(*Server) LoadPassword(*Server)
CheckPassword() CheckPassword()

View File

@ -3,7 +3,6 @@ package irc
import ( import (
"errors" "errors"
"regexp" "regexp"
"time"
) )
var ( var (
@ -21,10 +20,6 @@ const (
CRLF = "\r\n" CRLF = "\r\n"
MAX_REPLY_LEN = 512 - len(CRLF) MAX_REPLY_LEN = 512 - len(CRLF)
LOGIN_TIMEOUT = time.Minute / 2 // how long the client has to login
IDLE_TIMEOUT = time.Minute // how long before a client is considered idle
QUIT_TIMEOUT = time.Minute // how long after idle before a client is kicked
// string codes // string codes
AWAY StringCode = "AWAY" AWAY StringCode = "AWAY"
CAP StringCode = "CAP" CAP StringCode = "CAP"
@ -227,8 +222,3 @@ const (
UserLimit ChannelMode = 'l' // flag arg UserLimit ChannelMode = 'l' // flag arg
Voice ChannelMode = 'v' // arg Voice ChannelMode = 'v' // arg
) )
const (
Registration Phase = iota
Normal Phase = iota
)

View File

@ -6,7 +6,23 @@ import (
"time" "time"
) )
func NewStringReply(source Identifier, code StringCode, type ReplyCode interface {
String() string
}
type StringCode string
func (code StringCode) String() string {
return string(code)
}
type NumericCode uint
func (code NumericCode) String() string {
return fmt.Sprintf("%03d", code)
}
func NewStringReply(source Identifiable, code StringCode,
format string, args ...interface{}) string { format string, args ...interface{}) string {
var header string var header string
if source == nil { if source == nil {
@ -79,15 +95,15 @@ func (target *Client) MultilineReply(names []string, code NumericCode, format st
// messaging replies // messaging replies
// //
func RplPrivMsg(source Identifier, target Identifier, message string) string { func RplPrivMsg(source Identifiable, target Identifiable, message string) string {
return NewStringReply(source, PRIVMSG, "%s :%s", target.Nick(), message) return NewStringReply(source, PRIVMSG, "%s :%s", target.Nick(), message)
} }
func RplNotice(source Identifier, target Identifier, message string) string { func RplNotice(source Identifiable, target Identifiable, message string) string {
return NewStringReply(source, NOTICE, "%s :%s", target.Nick(), message) return NewStringReply(source, NOTICE, "%s :%s", target.Nick(), message)
} }
func RplNick(source Identifier, newNick string) string { func RplNick(source Identifiable, newNick string) string {
return NewStringReply(source, NICK, newNick) return NewStringReply(source, NICK, newNick)
} }
@ -108,11 +124,11 @@ func RplChannelMode(client *Client, channel *Channel,
return NewStringReply(client, MODE, "%s %s", channel, changes) return NewStringReply(client, MODE, "%s %s", channel, changes)
} }
func RplTopicMsg(source Identifier, channel *Channel) string { func RplTopicMsg(source Identifiable, channel *Channel) string {
return NewStringReply(source, TOPIC, "%s :%s", channel, channel.topic) return NewStringReply(source, TOPIC, "%s :%s", channel, channel.topic)
} }
func RplPing(target Identifier) string { func RplPing(target Identifiable) string {
return NewStringReply(nil, PING, ":%s", target.Nick()) return NewStringReply(nil, PING, ":%s", target.Nick())
} }

View File

@ -16,10 +16,15 @@ import (
"time" "time"
) )
var ( type ServerCommand interface {
SERVER_SIGNALS = []os.Signal{syscall.SIGINT, syscall.SIGHUP, Command
syscall.SIGTERM, syscall.SIGQUIT} HandleServer(*Server)
) }
type RegServerCommand interface {
Command
HandleRegServer(*Server)
}
type Server struct { type Server struct {
channels ChannelNameMap channels ChannelNameMap
@ -37,6 +42,11 @@ type Server struct {
whoWas *WhoWasList whoWas *WhoWasList
} }
var (
SERVER_SIGNALS = []os.Signal{syscall.SIGINT, syscall.SIGHUP,
syscall.SIGTERM, syscall.SIGQUIT}
)
func NewServer(config *Config) *Server { func NewServer(config *Config) *Server {
server := &Server{ server := &Server{
channels: make(ChannelNameMap), channels: make(ChannelNameMap),
@ -111,34 +121,33 @@ func (server *Server) processCommand(cmd Command) {
client := cmd.Client() client := cmd.Client()
Log.debug.Printf("%s → %s %s", client, server, cmd) Log.debug.Printf("%s → %s %s", client, server, cmd)
switch client.phase { if !client.registered {
case Registration:
regCmd, ok := cmd.(RegServerCommand) regCmd, ok := cmd.(RegServerCommand)
if !ok { if !ok {
client.Quit("unexpected command") client.Quit("unexpected command")
return return
} }
regCmd.HandleRegServer(server) regCmd.HandleRegServer(server)
return
case Normal:
srvCmd, ok := cmd.(ServerCommand)
if !ok {
client.ErrUnknownCommand(cmd.Code())
return
}
switch srvCmd.(type) {
case *PingCommand, *PongCommand:
client.Touch()
case *QuitCommand:
// no-op
default:
client.Active()
client.Touch()
}
srvCmd.HandleServer(server)
} }
srvCmd, ok := cmd.(ServerCommand)
if !ok {
client.ErrUnknownCommand(cmd.Code())
return
}
switch srvCmd.(type) {
case *PingCommand, *PongCommand:
client.Touch()
case *QuitCommand:
// no-op
default:
client.Active()
client.Touch()
}
srvCmd.HandleServer(server)
} }
func (server *Server) Shutdown() { func (server *Server) Shutdown() {
@ -197,14 +206,17 @@ func (s *Server) listen(addr string) {
// //
func (s *Server) tryRegister(c *Client) { func (s *Server) tryRegister(c *Client) {
if c.HasNick() && c.HasUsername() && (c.capState != CapNegotiating) { if c.registered || !c.HasNick() || !c.HasUsername() ||
c.Register() (c.capState == CapNegotiating) {
c.RplWelcome() return
c.RplYourHost()
c.RplCreated()
c.RplMyInfo()
s.MOTD(c)
} }
c.Register()
c.RplWelcome()
c.RplYourHost()
c.RplCreated()
c.RplMyInfo()
s.MOTD(c)
} }
func (server *Server) MOTD(client *Client) { func (server *Server) MOTD(client *Client) {

View File

@ -23,24 +23,6 @@ func (mode UserMode) String() string {
return string(mode) return string(mode)
} }
type Phase uint
type ReplyCode interface {
String() string
}
type StringCode string
func (code StringCode) String() string {
return string(code)
}
type NumericCode uint
func (code NumericCode) String() string {
return fmt.Sprintf("%03d", code)
}
// channel mode flags // channel mode flags
type ChannelMode rune type ChannelMode rune
@ -143,33 +125,7 @@ func (channels ChannelSet) First() *Channel {
// interfaces // interfaces
// //
type Identifier interface { type Identifiable interface {
Id() string Id() string
Nick() string Nick() string
} }
type Replier interface {
Reply(...string)
}
type Command interface {
Code() StringCode
Client() *Client
SetCode(StringCode)
SetClient(*Client)
}
type ServerCommand interface {
Command
HandleServer(*Server)
}
type AuthServerCommand interface {
Command
HandleAuthServer(*Server)
}
type RegServerCommand interface {
Command
HandleRegServer(*Server)
}