forked from External/ergo
move capability handling code to a single file
This commit is contained in:
parent
e15f47c766
commit
0126edc7af
4 changed files with 116 additions and 102 deletions
116
irc/capability.go
Normal file
116
irc/capability.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue