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

move capability handling code to a single file

This commit is contained in:
Jeremy Latt 2014-03-12 17:38:11 -07:00
parent e15f47c766
commit 0126edc7af
4 changed files with 116 additions and 102 deletions

116
irc/capability.go Normal file
View File

@ -0,0 +1,116 @@
package irc
import (
"strings"
)
type CapSubCommand string
const (
CAP_LS CapSubCommand = "LS"
CAP_LIST CapSubCommand = "LIST"
CAP_REQ CapSubCommand = "REQ"
CAP_ACK CapSubCommand = "ACK"
CAP_NAK CapSubCommand = "NAK"
CAP_CLEAR CapSubCommand = "CLEAR"
CAP_END CapSubCommand = "END"
)
// Capabilities are optional features a client may request from a server.
type Capability string
const (
MultiPrefix Capability = "multi-prefix"
SASL Capability = "sasl"
)
var (
SupportedCapabilities = CapabilitySet{
MultiPrefix: true,
}
)
func (capability Capability) String() string {
return string(capability)
}
// CapModifiers are indicators showing the state of a capability after a REQ or
// ACK.
type CapModifier rune
const (
Ack CapModifier = '~'
Disable CapModifier = '-'
Sticky CapModifier = '='
)
func (mod CapModifier) String() string {
return string(mod)
}
type CapState uint
const (
CapNone CapState = iota
CapNegotiating CapState = iota
CapNegotiated CapState = iota
)
type CapabilitySet map[Capability]bool
func (set CapabilitySet) String() string {
strs := make([]string, len(set))
index := 0
for capability := range set {
strs[index] = string(capability)
index += 1
}
return strings.Join(strs, " ")
}
func (set CapabilitySet) DisableString() string {
parts := make([]string, len(set))
index := 0
for capability := range set {
parts[index] = Disable.String() + capability.String()
index += 1
}
return strings.Join(parts, " ")
}
func (msg *CapCommand) HandleRegServer(server *Server) {
client := msg.Client()
switch msg.subCommand {
case CAP_LS:
client.capState = CapNegotiating
client.Reply(RplCap(client, CAP_LS, SupportedCapabilities))
case CAP_LIST:
client.Reply(RplCap(client, CAP_LIST, client.capabilities))
case CAP_REQ:
for capability := range msg.capabilities {
if !SupportedCapabilities[capability] {
client.Reply(RplCap(client, CAP_NAK, msg.capabilities))
return
}
}
for capability := range msg.capabilities {
client.capabilities[capability] = true
}
client.Reply(RplCap(client, CAP_ACK, msg.capabilities))
case CAP_CLEAR:
reply := RplCap(client, CAP_ACK, client.capabilities.DisableString())
client.capabilities = make(CapabilitySet)
client.Reply(reply)
case CAP_END:
client.capState = CapNegotiated
server.tryRegister(client)
default:
client.ErrInvalidCapCmd(msg.subCommand)
}
}

View File

@ -196,14 +196,6 @@ const (
ERR_UMODEUNKNOWNFLAG NumericCode = 501
ERR_USERSDONTMATCH NumericCode = 502
CAP_LS CapSubCommand = "LS"
CAP_LIST CapSubCommand = "LIST"
CAP_REQ CapSubCommand = "REQ"
CAP_ACK CapSubCommand = "ACK"
CAP_NAK CapSubCommand = "NAK"
CAP_CLEAR CapSubCommand = "CLEAR"
CAP_END CapSubCommand = "END"
Add ModeOp = '+'
List ModeOp = '='
Remove ModeOp = '-'
@ -234,28 +226,9 @@ const (
Secret ChannelMode = 's' // flag, deprecated
UserLimit ChannelMode = 'l' // flag arg
Voice ChannelMode = 'v' // arg
MultiPrefix Capability = "multi-prefix"
SASL Capability = "sasl"
Disable CapModifier = '-'
Ack CapModifier = '~'
Sticky CapModifier = '='
)
var (
SupportedCapabilities = CapabilitySet{
MultiPrefix: true,
}
)
const (
Registration Phase = iota
Normal Phase = iota
)
const (
CapNone CapState = iota
CapNegotiating CapState = iota
CapNegotiated CapState = iota
)

View File

@ -275,43 +275,6 @@ func (msg *ProxyCommand) HandleRegServer(server *Server) {
msg.Client().hostname = msg.hostname
}
func (msg *CapCommand) HandleRegServer(server *Server) {
client := msg.Client()
switch msg.subCommand {
case CAP_LS:
client.capState = CapNegotiating
client.Reply(RplCap(client, CAP_LS, SupportedCapabilities))
case CAP_LIST:
client.Reply(RplCap(client, CAP_LIST, client.capabilities))
case CAP_REQ:
for capability := range msg.capabilities {
if !SupportedCapabilities[capability] {
client.Reply(RplCap(client, CAP_NAK, msg.capabilities))
return
}
}
for capability := range msg.capabilities {
client.capabilities[capability] = true
}
client.Reply(RplCap(client, CAP_ACK, msg.capabilities))
case CAP_CLEAR:
reply := RplCap(client, CAP_ACK, client.capabilities.DisableString())
client.capabilities = make(CapabilitySet)
client.Reply(reply)
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 {

View File

@ -9,44 +9,6 @@ import (
// simple types
//
type CapSubCommand string
type Capability string
func (capability Capability) String() string {
return string(capability)
}
type CapModifier rune
func (mod CapModifier) String() string {
return string(mod)
}
type CapState uint
type CapabilitySet map[Capability]bool
func (set CapabilitySet) String() string {
strs := make([]string, len(set))
index := 0
for capability := range set {
strs[index] = string(capability)
index += 1
}
return strings.Join(strs, " ")
}
func (set CapabilitySet) DisableString() string {
parts := make([]string, len(set))
index := 0
for capability := range set {
parts[index] = Disable.String() + capability.String()
index += 1
}
return strings.Join(parts, " ")
}
// add, remove, list modes
type ModeOp rune