forked from External/ergo
Merge pull request #8 from jlatt/cap-protocol
basic capability negotiation
This commit is contained in:
commit
4bcd42ff34
7 changed files with 222 additions and 101 deletions
113
irc/server.go
113
irc/server.go
|
|
@ -29,7 +29,6 @@ type Server struct {
|
|||
operators map[string][]byte
|
||||
password []byte
|
||||
signals chan os.Signal
|
||||
timeout chan *Client
|
||||
}
|
||||
|
||||
func NewServer(config *Config) *Server {
|
||||
|
|
@ -45,7 +44,6 @@ func NewServer(config *Config) *Server {
|
|||
newConns: make(chan net.Conn, 16),
|
||||
operators: config.Operators(),
|
||||
signals: make(chan os.Signal, 1),
|
||||
timeout: make(chan *Client, 16),
|
||||
}
|
||||
|
||||
if config.Server.Password != "" {
|
||||
|
|
@ -97,14 +95,6 @@ func (server *Server) processCommand(cmd Command) {
|
|||
}
|
||||
|
||||
switch client.phase {
|
||||
case Authorization:
|
||||
authCmd, ok := cmd.(AuthServerCommand)
|
||||
if !ok {
|
||||
client.Quit("unexpected command")
|
||||
return
|
||||
}
|
||||
authCmd.HandleAuthServer(server)
|
||||
|
||||
case Registration:
|
||||
regCmd, ok := cmd.(RegServerCommand)
|
||||
if !ok {
|
||||
|
|
@ -113,7 +103,7 @@ func (server *Server) processCommand(cmd Command) {
|
|||
}
|
||||
regCmd.HandleRegServer(server)
|
||||
|
||||
default:
|
||||
case Normal:
|
||||
srvCmd, ok := cmd.(ServerCommand)
|
||||
if !ok {
|
||||
client.ErrUnknownCommand(cmd.Code())
|
||||
|
|
@ -157,20 +147,10 @@ func (server *Server) Run() {
|
|||
|
||||
case client := <-server.idle:
|
||||
client.Idle()
|
||||
|
||||
case client := <-server.timeout:
|
||||
client.Quit("connection timeout")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) InitPhase() Phase {
|
||||
if server.password == nil {
|
||||
return Registration
|
||||
}
|
||||
return Authorization
|
||||
}
|
||||
|
||||
//
|
||||
// listen goroutine
|
||||
//
|
||||
|
|
@ -206,7 +186,7 @@ func (s *Server) listen(addr string) {
|
|||
//
|
||||
|
||||
func (s *Server) tryRegister(c *Client) {
|
||||
if c.HasNick() && c.HasUsername() {
|
||||
if c.HasNick() && c.HasUsername() && (c.capState != CapNegotiating) {
|
||||
c.Register()
|
||||
c.RplWelcome()
|
||||
c.RplYourHost()
|
||||
|
|
@ -266,18 +246,10 @@ func (s *Server) Nick() string {
|
|||
}
|
||||
|
||||
//
|
||||
// authorization commands
|
||||
// registration commands
|
||||
//
|
||||
|
||||
func (msg *ProxyCommand) HandleAuthServer(server *Server) {
|
||||
msg.Client().hostname = msg.hostname
|
||||
}
|
||||
|
||||
func (msg *CapCommand) HandleAuthServer(server *Server) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func (msg *PassCommand) HandleAuthServer(server *Server) {
|
||||
func (msg *PassCommand) HandleRegServer(server *Server) {
|
||||
client := msg.Client()
|
||||
if msg.err != nil {
|
||||
client.ErrPasswdMismatch()
|
||||
|
|
@ -285,27 +257,70 @@ func (msg *PassCommand) HandleAuthServer(server *Server) {
|
|||
return
|
||||
}
|
||||
|
||||
client.phase = Registration
|
||||
client.authorized = true
|
||||
}
|
||||
|
||||
func (msg *QuitCommand) HandleAuthServer(server *Server) {
|
||||
msg.Client().Quit(msg.message)
|
||||
}
|
||||
|
||||
//
|
||||
// registration commands
|
||||
//
|
||||
|
||||
func (msg *ProxyCommand) HandleRegServer(server *Server) {
|
||||
msg.Client().hostname = msg.hostname
|
||||
}
|
||||
|
||||
func (msg *CapCommand) HandleRegServer(server *Server) {
|
||||
// TODO
|
||||
client := msg.Client()
|
||||
|
||||
switch msg.subCommand {
|
||||
case CAP_LS:
|
||||
client.capState = CapNegotiating
|
||||
client.Reply("CAP LS * :%s", SupportedCapabilities)
|
||||
|
||||
case CAP_LIST:
|
||||
client.Reply("CAP LIST * :%s", client.capabilities)
|
||||
|
||||
case CAP_REQ:
|
||||
client.capState = CapNegotiating
|
||||
for capability := range msg.capabilities {
|
||||
if !SupportedCapabilities[capability] {
|
||||
client.Reply("CAP NAK * :%s", msg.capabilities)
|
||||
return
|
||||
}
|
||||
}
|
||||
for capability := range msg.capabilities {
|
||||
client.capabilities[capability] = true
|
||||
}
|
||||
client.Reply("CAP ACK * :%s", msg.capabilities)
|
||||
|
||||
case CAP_CLEAR:
|
||||
format := strings.TrimRight(
|
||||
strings.Repeat("%s%s ", len(client.capabilities)), " ")
|
||||
args := make([]interface{}, len(client.capabilities))
|
||||
index := 0
|
||||
for capability := range client.capabilities {
|
||||
args[index] = Disable
|
||||
args[index+1] = capability
|
||||
index += 2
|
||||
delete(client.capabilities, capability)
|
||||
}
|
||||
client.Reply("CAP ACK * :"+format, args...)
|
||||
|
||||
case CAP_END:
|
||||
client.capState = CapNegotiated
|
||||
server.tryRegister(client)
|
||||
|
||||
default:
|
||||
client.ErrInvalidCapCmd(msg.subCommand)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *NickCommand) HandleRegServer(s *Server) {
|
||||
client := m.Client()
|
||||
if !client.authorized {
|
||||
client.ErrPasswdMismatch()
|
||||
client.Quit("bad password")
|
||||
return
|
||||
}
|
||||
|
||||
if client.capState == CapNegotiating {
|
||||
client.capState = CapNegotiated
|
||||
}
|
||||
|
||||
if m.nickname == "" {
|
||||
client.ErrNoNicknameGiven()
|
||||
|
|
@ -327,11 +342,22 @@ func (m *NickCommand) HandleRegServer(s *Server) {
|
|||
}
|
||||
|
||||
func (msg *RFC1459UserCommand) HandleRegServer(server *Server) {
|
||||
client := msg.Client()
|
||||
if !client.authorized {
|
||||
client.ErrPasswdMismatch()
|
||||
client.Quit("bad password")
|
||||
return
|
||||
}
|
||||
msg.HandleRegServer2(server)
|
||||
}
|
||||
|
||||
func (msg *RFC2812UserCommand) HandleRegServer(server *Server) {
|
||||
client := msg.Client()
|
||||
if !client.authorized {
|
||||
client.ErrPasswdMismatch()
|
||||
client.Quit("bad password")
|
||||
return
|
||||
}
|
||||
flags := msg.Flags()
|
||||
if len(flags) > 0 {
|
||||
for _, mode := range msg.Flags() {
|
||||
|
|
@ -344,6 +370,9 @@ func (msg *RFC2812UserCommand) HandleRegServer(server *Server) {
|
|||
|
||||
func (msg *UserCommand) HandleRegServer2(server *Server) {
|
||||
client := msg.Client()
|
||||
if client.capState == CapNegotiating {
|
||||
client.capState = CapNegotiated
|
||||
}
|
||||
client.username, client.realname = msg.username, msg.realname
|
||||
server.tryRegister(client)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue