Step 1 of moving to interface Stanza and embedded struct Header.
--- a/roster.go Sun Dec 16 22:17:49 2012 -0700
+++ b/roster.go Sun Dec 16 22:36:53 2012 -0700
@@ -48,7 +48,7 @@
func fetchRoster(client *Client) error {
rosterUpdate := rosterClients[client.Uid].rosterUpdate
- iq := &Iq{Stanza: Stanza{From: client.Jid.String(), Type: "get",
+ iq := &Iq{Header: Header{From: client.Jid.String(), Type: "get",
Id: <-Id, Nested: []interface{}{RosterQuery{}}}}
ch := make(chan error)
f := func(v interface{}) bool {
@@ -128,7 +128,7 @@
rosterUpdate <- item
}
// Send a reply.
- reply := &Iq{Stanza: Stanza{To: iq.From, Id: iq.Id,
+ reply := &Iq{Header: Header{To: iq.From, Id: iq.Id,
Type: "result"}}
client.Out <- reply
}
--- a/roster_test.go Sun Dec 16 22:17:49 2012 -0700
+++ b/roster_test.go Sun Dec 16 22:36:53 2012 -0700
@@ -13,7 +13,7 @@
// This is mostly just tests of the roster data structures.
func TestRosterIqMarshal(t *testing.T) {
- iq := &Iq{Stanza: Stanza{From: "from", Lang: "en",
+ iq := &Iq{Header: Header{From: "from", Lang: "en",
Nested: []interface{}{RosterQuery{}}}}
exp := `<iq from="from" xml:lang="en"><query xmlns="` +
NsRoster + `"></query></iq>`
@@ -26,7 +26,7 @@
iq := Iq{}
xml.Unmarshal([]byte(str), &iq)
m := map[string]func(*xml.Name) interface{}{NsRoster: newRosterQuery}
- err := parseExtended(&iq.Stanza, m)
+ err := parseExtended(&iq.Header, m)
if err != nil {
t.Fatalf("parseExtended: %v", err)
}
--- a/stream.go Sun Dec 16 22:17:49 2012 -0700
+++ b/stream.go Sun Dec 16 22:36:53 2012 -0700
@@ -148,8 +148,8 @@
// If it's a Stanza, we try to unmarshal its innerxml
// into objects of the appropriate respective
// types. This is specified by our extensions.
- if st := getStanza(obj) ; st != nil {
- err = parseExtended(st, extStanza)
+ if st, ok := obj.(Stanzer) ; ok {
+ err = parseExtended(st.GetHeader(), extStanza)
if err != nil {
Warn.Logf("ext unmarshal: %s", err)
break Loop
@@ -161,7 +161,7 @@
}
}
-func parseExtended(st *Stanza, extStanza map[string]func(*xml.Name) interface{}) error {
+func parseExtended(st *Header, extStanza map[string]func(*xml.Name) interface{}) error {
// Now parse the stanza's innerxml to find the string that we
// can unmarshal this nested element from.
reader := strings.NewReader(st.Innerxml)
@@ -238,7 +238,7 @@
if !ok {
break Loop
}
- var st *Stanza
+ var st *Header
switch obj := x.(type) {
case *stream:
handleStream(obj)
@@ -250,8 +250,8 @@
cl.handleTls(obj)
case *auth:
cl.handleSasl(obj)
- case *Iq, *Message, *Presence:
- st = getStanza(obj)
+ case Stanzer:
+ st = obj.GetHeader()
default:
Warn.Logf("Unhandled non-stanza: %T %#v", x, x)
}
@@ -596,7 +596,7 @@
if res != "" {
bindReq.Resource = &res
}
- msg := &Iq{Stanza: Stanza{Type: "set", Id: <-Id,
+ msg := &Iq{Header: Header{Type: "set", Id: <-Id,
Nested: []interface{}{bindReq}}}
f := func(st interface{}) bool {
iq, ok := st.(*Iq)
--- a/structs.go Sun Dec 16 22:17:49 2012 -0700
+++ b/structs.go Sun Dec 16 22:36:53 2012 -0700
@@ -77,9 +77,13 @@
Any *Generic
}
+type Stanzer interface {
+ GetHeader() *Header
+}
+
// One of the three core XMPP stanza types: iq, message, presence. See
// RFC3920, section 9.
-type Stanza struct {
+type Header struct {
To string `xml:"to,attr,omitempty"`
From string `xml:"from,attr,omitempty"`
Id string `xml:"id,attr,omitempty"`
@@ -93,26 +97,29 @@
// message stanza
type Message struct {
XMLName xml.Name `xml:"message"`
- Stanza
+ Header
Subject *Generic `xml:"subject"`
Body *Generic `xml:"body"`
Thread *Generic `xml:"thread"`
}
+var _ Stanzer = &Message{}
// presence stanza
type Presence struct {
XMLName xml.Name `xml:"presence"`
- Stanza
+ Header
Show *Generic `xml:"show"`
Status *Generic `xml:"status"`
Priority *Generic `xml:"priority"`
}
+var _ Stanzer = &Presence{}
// iq stanza
type Iq struct {
XMLName xml.Name `xml:"iq"`
- Stanza
+ Header
}
+var _ Stanzer = &Iq{}
// Describes an XMPP stanza error. See RFC 3920, Section 9.3.
type Error struct {
@@ -222,6 +229,18 @@
return s, nil
}
+func (iq *Iq) GetHeader() *Header {
+ return &iq.Header
+}
+
+func (m *Message) GetHeader() *Header {
+ return &m.Header
+}
+
+func (p *Presence) GetHeader() *Header {
+ return &p.Header
+}
+
func (u *Generic) String() string {
if u == nil {
return "nil"
@@ -250,15 +269,3 @@
func newBind(name *xml.Name) interface{} {
return &bindIq{}
}
-
-func getStanza(v interface{}) *Stanza {
- switch s := v.(type) {
- case *Iq:
- return &s.Stanza
- case *Message:
- return &s.Stanza
- case *Presence:
- return &s.Stanza
- }
- return nil
-}
--- a/structs_test.go Sun Dec 16 22:17:49 2012 -0700
+++ b/structs_test.go Sun Dec 16 22:36:53 2012 -0700
@@ -89,7 +89,7 @@
}
func TestIqMarshal(t *testing.T) {
- iq := &Iq{Stanza: Stanza{Type: "set", Id: "3",
+ iq := &Iq{Header: Header{Type: "set", Id: "3",
Nested: []interface{}{Generic{XMLName: xml.Name{Space: NsBind,
Local: "bind"}}}}}
exp := `<iq id="3" type="set"><bind xmlns="` + NsBind +
--- a/xmpp.go Sun Dec 16 22:17:49 2012 -0700
+++ b/xmpp.go Sun Dec 16 22:36:53 2012 -0700
@@ -268,7 +268,7 @@
// Presence struct. See RFC 3921, Section 3.
func (cl *Client) StartSession(getRoster bool, pr *Presence) error {
id := <-Id
- iq := &Iq{Stanza: Stanza{To: cl.Jid.Domain, Id: id, Type: "set",
+ iq := &Iq{Header: Header{To: cl.Jid.Domain, Id: id, Type: "set",
Nested: []interface{}{Generic{XMLName:
xml.Name{Space: NsSession, Local: "session"}}}}}
ch := make(chan error)