send proper replies for cap protocol

This commit is contained in:
Jeremy Latt 2014-03-02 12:54:48 -08:00
parent 36602c9a3c
commit 0874692aa8
4 changed files with 39 additions and 24 deletions

View File

@ -235,7 +235,10 @@ func (client *Client) ChangeNickname(nickname string) {
} }
} }
func (client *Client) Reply(reply string) { func (client *Client) Reply(reply string, args ...interface{}) {
if len(args) > 0 {
reply = fmt.Sprintf(reply, args...)
}
client.socket.Write(reply) client.socket.Write(reply)
} }

View File

@ -708,21 +708,13 @@ func NewOperCommand(args []string) (editableCommand, error) {
type CapCommand struct { type CapCommand struct {
BaseCommand BaseCommand
subCommand CapSubCommand subCommand CapSubCommand
args []string capabilities CapabilitySet
} }
func (msg *CapCommand) String() string { func (msg *CapCommand) String() string {
return fmt.Sprintf("CAP(subCommand=%s, args=%s)", msg.subCommand, msg.args) return fmt.Sprintf("CAP(subCommand=%s, capabilities=%s)",
} msg.subCommand, msg.capabilities)
func (msg *CapCommand) Capabilities() []Capability {
strs := strings.Split(msg.args[0], " ")
caps := make([]Capability, len(strs))
for index, str := range strs {
caps[index] = Capability(str)
}
return caps
} }
func NewCapCommand(args []string) (editableCommand, error) { func NewCapCommand(args []string) (editableCommand, error) {
@ -731,8 +723,15 @@ func NewCapCommand(args []string) (editableCommand, error) {
} }
cmd := &CapCommand{ cmd := &CapCommand{
subCommand: CapSubCommand(args[0]), subCommand: CapSubCommand(strings.ToUpper(args[0])),
args: args[1:], capabilities: make(CapabilitySet),
}
if len(args) > 1 {
strs := spacesExpr.Split(args[1], -1)
for _, str := range strs {
cmd.capabilities[Capability(str)] = true
}
} }
return cmd, nil return cmd, nil
} }

View File

@ -301,28 +301,36 @@ func (msg *CapCommand) HandleRegServer(server *Server) {
switch msg.subCommand { switch msg.subCommand {
case CAP_LS: case CAP_LS:
client.capState = CapNegotiating client.capState = CapNegotiating
client.Reply(fmt.Sprintf("CAP LS :%d", MultiPrefix)) client.Reply("CAP LS * :%s", SupportedCapabilities)
case CAP_LIST: case CAP_LIST:
client.Reply(fmt.Sprintf("CAP LIST :%s", client.capabilities)) client.Reply("CAP LIST * :%s", client.capabilities)
case CAP_REQ: case CAP_REQ:
client.capState = CapNegotiating client.capState = CapNegotiating
caps := msg.Capabilities() for capability := range msg.capabilities {
if (len(caps) != 1) && (caps[0] != MultiPrefix) { if !SupportedCapabilities[capability] {
client.Reply("CAP NAK :" + msg.args[0]) client.Reply("CAP NAK * :%s", msg.capabilities)
return return
}
} }
for _, capability := range caps { for capability := range msg.capabilities {
client.capabilities[capability] = true client.capabilities[capability] = true
} }
client.Reply("CAP ACK :" + msg.args[0]) client.Reply("CAP ACK * :%s", msg.capabilities)
case CAP_CLEAR: 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 { for capability := range client.capabilities {
args[index] = Disable
args[index+1] = capability
index += 2
delete(client.capabilities, capability) delete(client.capabilities, capability)
} }
client.Reply("CAP ACK :") client.Reply("CAP ACK * :"+format, args...)
case CAP_END: case CAP_END:
client.capState = CapNegotiated client.capState = CapNegotiated

View File

@ -16,6 +16,10 @@ type Capability string
type CapModifier rune type CapModifier rune
func (mod CapModifier) String() string {
return string(mod)
}
type CapState uint type CapState uint
type CapabilitySet map[Capability]bool type CapabilitySet map[Capability]bool
@ -25,6 +29,7 @@ func (set CapabilitySet) String() string {
index := 0 index := 0
for capability := range set { for capability := range set {
strs[index] = string(capability) strs[index] = string(capability)
index += 1
} }
return strings.Join(strs, " ") return strings.Join(strs, " ")
} }