mirror of
				https://github.com/FluuxIO/go-xmpp.git
				synced 2025-11-03 16:53:44 -08:00 
			
		
		
		
	Refactor IQ handling and merge payload iq struct fields for supported XEPs
This commit is contained in:
		@@ -66,8 +66,11 @@ type saslFailure struct {
 | 
			
		||||
 | 
			
		||||
type bindBind struct {
 | 
			
		||||
	XMLName  xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
 | 
			
		||||
	Resource string
 | 
			
		||||
	Jid      string
 | 
			
		||||
	Resource string   `xml:"resource,omitempty"`
 | 
			
		||||
	Jid      string   `xml:"jid,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*bindBind) IsIQPayload() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Session is obsolete in RFC 6121.
 | 
			
		||||
 
 | 
			
		||||
@@ -2,16 +2,24 @@ package iot
 | 
			
		||||
 | 
			
		||||
import "encoding/xml"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
type Control struct {
 | 
			
		||||
	ControlSet     ControlSet     `xml:",omitempty"`
 | 
			
		||||
	ControlGetForm ControlGetForm `xml:",omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Control) IQPayload() {
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
type ControlSet struct {
 | 
			
		||||
	XMLName xml.Name       `xml:"urn:xmpp:iot:control set"`
 | 
			
		||||
	Fields  []ControlField `xml:",any"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ControlSet) IsIQPayload() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ControlGetForm struct {
 | 
			
		||||
	XMLName xml.Name `xml:"urn:xmpp:iot:control getForm"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								xmpp/iq.go
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								xmpp/iq.go
									
									
									
									
									
								
							@@ -10,9 +10,66 @@ import (
 | 
			
		||||
type ClientIQ struct {
 | 
			
		||||
	XMLName xml.Name `xml:"jabber:client iq"`
 | 
			
		||||
	Packet
 | 
			
		||||
	Bind bindBind `xml:",omitempty"`
 | 
			
		||||
	iot.Control
 | 
			
		||||
	RawXML string `xml:",innerxml"`
 | 
			
		||||
	Payload IQPayload `xml:",omitempty"`
 | 
			
		||||
	RawXML  string    `xml:",innerxml"`
 | 
			
		||||
	// TODO We need to support detecting the IQ namespace / Query packet
 | 
			
		||||
	// 	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
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -154,11 +154,18 @@ func (s *Session) bind(o Options) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var iq ClientIQ
 | 
			
		||||
	if s.err = s.decoder.Decode(&iq); s.err != nil || &iq.Bind == nil {
 | 
			
		||||
		s.err = errors.New("iq bind result missing: " + s.err.Error())
 | 
			
		||||
	if s.err = s.decoder.Decode(&iq); s.err != nil {
 | 
			
		||||
		s.err = errors.New("error decoding iq bind result: " + s.err.Error())
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user