Refactor IQ handling and merge payload iq struct fields for supported XEPs

This commit is contained in:
Mickael Remond 2016-02-15 15:22:51 +01:00
parent 3a516a43d3
commit 268acbff07
4 changed files with 83 additions and 8 deletions

View file

@ -66,8 +66,11 @@ type saslFailure struct {
type bindBind struct { type bindBind struct {
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"` XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
Resource string Resource string `xml:"resource,omitempty"`
Jid string Jid string `xml:"jid,omitempty"`
}
func (*bindBind) IsIQPayload() {
} }
// Session is obsolete in RFC 6121. // Session is obsolete in RFC 6121.

View file

@ -2,16 +2,24 @@ package iot
import "encoding/xml" import "encoding/xml"
/*
type Control struct { type Control struct {
ControlSet ControlSet `xml:",omitempty"` ControlSet ControlSet `xml:",omitempty"`
ControlGetForm ControlGetForm `xml:",omitempty"` ControlGetForm ControlGetForm `xml:",omitempty"`
} }
func (*Control) IQPayload() {
}
*/
type ControlSet struct { type ControlSet struct {
XMLName xml.Name `xml:"urn:xmpp:iot:control set"` XMLName xml.Name `xml:"urn:xmpp:iot:control set"`
Fields []ControlField `xml:",any"` Fields []ControlField `xml:",any"`
} }
func (*ControlSet) IsIQPayload() {
}
type ControlGetForm struct { type ControlGetForm struct {
XMLName xml.Name `xml:"urn:xmpp:iot:control getForm"` XMLName xml.Name `xml:"urn:xmpp:iot:control getForm"`
} }

View file

@ -10,9 +10,66 @@ import (
type ClientIQ struct { type ClientIQ struct {
XMLName xml.Name `xml:"jabber:client iq"` XMLName xml.Name `xml:"jabber:client iq"`
Packet Packet
Bind bindBind `xml:",omitempty"` Payload IQPayload `xml:",omitempty"`
iot.Control RawXML string `xml:",innerxml"`
RawXML string `xml:",innerxml"`
// TODO We need to support detecting the IQ namespace / Query packet // TODO We need to support detecting the IQ namespace / Query packet
// Error clientError // Error clientError
} }
type IQPayload interface {
IsIQPayload()
}
// UnmarshalXML implements custom parsing for IQs
func (iq *ClientIQ) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
iq.XMLName = start.Name
// Extract IQ attributes
for _, attr := range start.Attr {
if attr.Name.Local == "id" {
iq.Id = attr.Value
}
if attr.Name.Local == "to" {
iq.To = attr.Value
}
if attr.Name.Local == "from" {
iq.From = attr.Value
}
if attr.Name.Local == "lang" {
iq.Lang = attr.Value
}
}
// decode inner elements
for {
t, err := d.Token()
if err != nil {
return err
}
var p IQPayload
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Space + " " + tt.Name.Local {
case "urn:ietf:params:xml:ns:xmpp-bind bind":
p = new(bindBind)
case "urn:xmpp:iot:control set":
p = new(iot.ControlSet)
// TODO: Add a default Type that passes RawXML
}
if p != nil {
err = d.DecodeElement(p, &tt)
if err != nil {
return err
}
iq.Payload = p
p = nil
}
case xml.EndElement:
if tt == start.End() {
return nil
}
}
}
}

View file

@ -154,11 +154,18 @@ func (s *Session) bind(o Options) {
} }
var iq ClientIQ var iq ClientIQ
if s.err = s.decoder.Decode(&iq); s.err != nil || &iq.Bind == nil { if s.err = s.decoder.Decode(&iq); s.err != nil {
s.err = errors.New("iq bind result missing: " + s.err.Error()) s.err = errors.New("error decoding iq bind result: " + s.err.Error())
return return
} }
s.BindJid = iq.Bind.Jid // our local id (with possibly randomly generated resource
switch payload := iq.Payload.(type) {
case *bindBind:
s.BindJid = payload.Jid // our local id (with possibly randomly generated resource
default:
s.err = errors.New("iq bind result missing")
}
return return
} }