forked from jshiffer/go-xmpp
Compare commits
5 Commits
v0.5.0
...
stanza-bui
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c76c9c0a0 | ||
|
|
0b0c0fa5ab | ||
|
|
6872ed8d1b | ||
|
|
0e3101c2be | ||
|
|
026e5e6fe1 |
@@ -99,26 +99,9 @@ func discoInfo(c xmpp.Sender, p stanza.Packet, opts xmpp.ComponentOptions) {
|
||||
}
|
||||
|
||||
func discoInfoRoot(iqResp *stanza.IQ, opts xmpp.ComponentOptions) {
|
||||
// Higher level discovery
|
||||
identity := stanza.Identity{
|
||||
Name: opts.Name,
|
||||
Category: opts.Category,
|
||||
Type: opts.Type,
|
||||
}
|
||||
payload := stanza.DiscoInfo{
|
||||
XMLName: xml.Name{
|
||||
Space: stanza.NSDiscoInfo,
|
||||
Local: "query",
|
||||
},
|
||||
Identity: []stanza.Identity{identity},
|
||||
Features: []stanza.Feature{
|
||||
{Var: stanza.NSDiscoInfo},
|
||||
{Var: stanza.NSDiscoItems},
|
||||
{Var: "jabber:iq:version"},
|
||||
{Var: "urn:xmpp:delegation:1"},
|
||||
},
|
||||
}
|
||||
iqResp.Payload = &payload
|
||||
disco := iqResp.DiscoInfo()
|
||||
disco.AddIdentity(opts.Name, opts.Category, opts.Type)
|
||||
disco.AddFeatures(stanza.NSDiscoInfo, stanza.NSDiscoItems, "jabber:iq:version", "urn:xmpp:delegation:1")
|
||||
}
|
||||
|
||||
func discoInfoPubSub(iqResp *stanza.IQ) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
@@ -61,25 +60,9 @@ func discoInfo(c xmpp.Sender, p stanza.Packet, opts xmpp.ComponentOptions) {
|
||||
}
|
||||
|
||||
iqResp := stanza.NewIQ(stanza.Attrs{Type: "result", From: iq.To, To: iq.From, Id: iq.Id, Lang: "en"})
|
||||
identity := stanza.Identity{
|
||||
Name: opts.Name,
|
||||
Category: opts.Category,
|
||||
Type: opts.Type,
|
||||
}
|
||||
payload := stanza.DiscoInfo{
|
||||
XMLName: xml.Name{
|
||||
Space: stanza.NSDiscoInfo,
|
||||
Local: "query",
|
||||
},
|
||||
Identity: []stanza.Identity{identity},
|
||||
Features: []stanza.Feature{
|
||||
{Var: stanza.NSDiscoInfo},
|
||||
{Var: stanza.NSDiscoItems},
|
||||
{Var: "jabber:iq:version"},
|
||||
{Var: "urn:xmpp:delegation:1"},
|
||||
},
|
||||
}
|
||||
iqResp.Payload = &payload
|
||||
disco := iqResp.DiscoInfo()
|
||||
disco.AddIdentity(opts.Name, opts.Category, opts.Type)
|
||||
disco.AddFeatures(stanza.NSDiscoInfo, stanza.NSDiscoItems, "jabber:iq:version", "urn:xmpp:delegation:1")
|
||||
_ = c.Send(iqResp)
|
||||
}
|
||||
|
||||
@@ -97,16 +80,11 @@ func discoItems(c xmpp.Sender, p stanza.Packet) {
|
||||
}
|
||||
|
||||
iqResp := stanza.NewIQ(stanza.Attrs{Type: "result", From: iq.To, To: iq.From, Id: iq.Id, Lang: "en"})
|
||||
items := iqResp.DiscoItems()
|
||||
|
||||
var payload stanza.DiscoItems
|
||||
if discoItems.Node == "" {
|
||||
payload = stanza.DiscoItems{
|
||||
Items: []stanza.DiscoItem{
|
||||
{Name: "test node", JID: "service.localhost", Node: "node1"},
|
||||
},
|
||||
}
|
||||
items.AddItem("service.localhost", "node1", "test node")
|
||||
}
|
||||
iqResp.Payload = &payload
|
||||
_ = c.Send(iqResp)
|
||||
}
|
||||
|
||||
@@ -118,9 +96,6 @@ func handleVersion(c xmpp.Sender, p stanza.Packet) {
|
||||
}
|
||||
|
||||
iqResp := stanza.NewIQ(stanza.Attrs{Type: "result", From: iq.To, To: iq.From, Id: iq.Id, Lang: "en"})
|
||||
var payload stanza.Version
|
||||
payload.Name = "Fluux XMPP Component"
|
||||
payload.Version = "0.0.1"
|
||||
iq.Payload = &payload
|
||||
iqResp.Version().SetInfo("Fluux XMPP Component", "0.0.1", "")
|
||||
_ = c.Send(iqResp)
|
||||
}
|
||||
|
||||
@@ -56,8 +56,9 @@ func (d *DiscoInfo) AddFeatures(namespace ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DiscoInfo) SetNode(node string) {
|
||||
func (d *DiscoInfo) SetNode(node string) *DiscoInfo {
|
||||
d.Node = node
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DiscoInfo) SetIdentities(ident ...Identity) *DiscoInfo {
|
||||
@@ -66,6 +67,7 @@ func (d *DiscoInfo) SetIdentities(ident ...Identity) *DiscoInfo {
|
||||
}
|
||||
|
||||
func (d *DiscoInfo) SetFeatures(namespace ...string) *DiscoInfo {
|
||||
d.Features = []Feature{}
|
||||
for _, ns := range namespace {
|
||||
d.Features = append(d.Features, Feature{Var: ns})
|
||||
}
|
||||
@@ -104,11 +106,38 @@ func (d *DiscoItems) Namespace() string {
|
||||
return d.XMLName.Space
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// Builder helpers
|
||||
|
||||
// DiscoItems builds a default DiscoItems payload
|
||||
func (iq *IQ) DiscoItems() *DiscoItems {
|
||||
d := DiscoItems{
|
||||
XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#items", Local: "query"},
|
||||
}
|
||||
iq.Payload = &d
|
||||
return &d
|
||||
}
|
||||
|
||||
func (d *DiscoItems) SetNode(node string) *DiscoItems {
|
||||
d.Node = node
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DiscoItems) AddItem(jid, node, name string) *DiscoItems {
|
||||
item := DiscoItem{
|
||||
JID: jid,
|
||||
Node: node,
|
||||
Name: name,
|
||||
}
|
||||
d.Items = append(d.Items, item)
|
||||
return d
|
||||
}
|
||||
|
||||
type DiscoItem struct {
|
||||
XMLName xml.Name `xml:"item"`
|
||||
Name string `xml:"name,attr,omitempty"`
|
||||
JID string `xml:"jid,attr,omitempty"`
|
||||
Node string `xml:"node,attr,omitempty"`
|
||||
Name string `xml:"name,attr,omitempty"`
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -7,29 +7,22 @@ import (
|
||||
"gosrc.io/xmpp/stanza"
|
||||
)
|
||||
|
||||
func TestDiscoInfoBuilder(t *testing.T) {
|
||||
// Test DiscoInfo Builder with several features
|
||||
func TestDiscoInfo_Builder(t *testing.T) {
|
||||
iq := stanza.NewIQ(stanza.Attrs{Type: "get", To: "service.localhost", Id: "disco-get-1"})
|
||||
disco := iq.DiscoInfo()
|
||||
disco.AddIdentity("Test Component", "gateway", "service")
|
||||
disco.AddFeatures(stanza.NSDiscoInfo, stanza.NSDiscoItems, "jabber:iq:version", "urn:xmpp:delegation:1")
|
||||
|
||||
// Marshall
|
||||
data, err := xml.Marshal(iq)
|
||||
parsedIQ, err := checkMarshalling(t, iq)
|
||||
if err != nil {
|
||||
t.Errorf("cannot marshal xml structure: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshall
|
||||
var parsedIQ stanza.IQ
|
||||
if err = xml.Unmarshal(data, &parsedIQ); err != nil {
|
||||
t.Errorf("Unmarshal(%s) returned error: %s", data, err)
|
||||
}
|
||||
|
||||
// Check result
|
||||
pp, ok := parsedIQ.Payload.(*stanza.DiscoInfo)
|
||||
if !ok {
|
||||
t.Errorf("Parsed stanza does not contain an IQ payload")
|
||||
t.Errorf("Parsed stanza does not contain correct IQ payload")
|
||||
}
|
||||
|
||||
// Check features
|
||||
@@ -53,3 +46,45 @@ func TestDiscoInfoBuilder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implements XEP-0030 example 17
|
||||
// https://xmpp.org/extensions/xep-0030.html#example-17
|
||||
func TestDiscoItems_Builder(t *testing.T) {
|
||||
iq := stanza.NewIQ(stanza.Attrs{Type: "result", From: "catalog.shakespeare.lit",
|
||||
To: "romeo@montague.net/orchard", Id: "items-2"})
|
||||
iq.DiscoItems().
|
||||
AddItem("catalog.shakespeare.lit", "books", "Books by and about Shakespeare").
|
||||
AddItem("catalog.shakespeare.lit", "clothing", "Wear your literary taste with pride").
|
||||
AddItem("catalog.shakespeare.lit", "music", "Music from the time of Shakespeare")
|
||||
|
||||
parsedIQ, err := checkMarshalling(t, iq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check result
|
||||
pp, ok := parsedIQ.Payload.(*stanza.DiscoItems)
|
||||
if !ok {
|
||||
t.Errorf("Parsed stanza does not contain correct IQ payload")
|
||||
}
|
||||
|
||||
// Check items
|
||||
items := []stanza.DiscoItem{{xml.Name{}, "catalog.shakespeare.lit", "books", "Books by and about Shakespeare"},
|
||||
{xml.Name{}, "catalog.shakespeare.lit", "clothing", "Wear your literary taste with pride"},
|
||||
{xml.Name{}, "catalog.shakespeare.lit", "music", "Music from the time of Shakespeare"}}
|
||||
if len(pp.Items) != len(items) {
|
||||
t.Errorf("Items length mismatch: %#v", pp.Items)
|
||||
} else {
|
||||
for i, item := range pp.Items {
|
||||
if item.JID != items[i].JID {
|
||||
t.Errorf("JID Mismatch (expected: %s): %s", items[i].JID, item.JID)
|
||||
}
|
||||
if item.Node != items[i].Node {
|
||||
t.Errorf("Node Mismatch (expected: %s): %s", items[i].JID, item.JID)
|
||||
}
|
||||
if item.Name != items[i].Name {
|
||||
t.Errorf("Name Mismatch (expected: %s): %s", items[i].JID, item.JID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,26 @@ func (v *Version) Namespace() string {
|
||||
return v.XMLName.Space
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// Builder helpers
|
||||
|
||||
// Version builds a default software version payload
|
||||
func (iq *IQ) Version() *Version {
|
||||
d := Version{
|
||||
XMLName: xml.Name{Space: "jabber:iq:version", Local: "query"},
|
||||
}
|
||||
iq.Payload = &d
|
||||
return &d
|
||||
}
|
||||
|
||||
// Set all software version info
|
||||
func (v *Version) SetInfo(name, version, os string) *Version {
|
||||
v.Name = name
|
||||
v.Version = version
|
||||
v.OS = os
|
||||
return v
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Registry init
|
||||
|
||||
|
||||
40
stanza/iq_version_test.go
Normal file
40
stanza/iq_version_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package stanza_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gosrc.io/xmpp/stanza"
|
||||
)
|
||||
|
||||
// Build a Software Version reply
|
||||
// https://xmpp.org/extensions/xep-0092.html#example-2
|
||||
func TestVersion_Builder(t *testing.T) {
|
||||
name := "Exodus"
|
||||
version := "0.7.0.4"
|
||||
os := "Windows-XP 5.01.2600"
|
||||
iq := stanza.NewIQ(stanza.Attrs{Type: "result", From: "romeo@montague.net/orchard",
|
||||
To: "juliet@capulet.com/balcony", Id: "version_1"})
|
||||
iq.Version().SetInfo(name, version, os)
|
||||
|
||||
parsedIQ, err := checkMarshalling(t, iq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check result
|
||||
pp, ok := parsedIQ.Payload.(*stanza.Version)
|
||||
if !ok {
|
||||
t.Errorf("Parsed stanza does not contain correct IQ payload")
|
||||
}
|
||||
|
||||
// Check version info
|
||||
if pp.Name != name {
|
||||
t.Errorf("Name Mismatch (expected: %s): %s", name, pp.Name)
|
||||
}
|
||||
if pp.Version != version {
|
||||
t.Errorf("Version Mismatch (expected: %s): %s", version, pp.Version)
|
||||
}
|
||||
if pp.OS != os {
|
||||
t.Errorf("OS Mismatch (expected: %s): %s", os, pp.OS)
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,35 @@ package stanza_test
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"gosrc.io/xmpp/stanza"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// Marshaller / unmarshaller test
|
||||
|
||||
func checkMarshalling(t *testing.T, iq stanza.IQ) (*stanza.IQ, error) {
|
||||
// Marshall
|
||||
data, err := xml.Marshal(iq)
|
||||
if err != nil {
|
||||
t.Errorf("cannot marshal iq: %s\n%#v", err, iq)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshall
|
||||
var parsedIQ stanza.IQ
|
||||
err = xml.Unmarshal(data, &parsedIQ)
|
||||
if err != nil {
|
||||
t.Errorf("Unmarshal returned error: %s\n%s", err, data)
|
||||
}
|
||||
return &parsedIQ, err
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// XML structs comparison
|
||||
|
||||
// Compare iq structure but ignore empty namespace as they are set properly on
|
||||
// marshal / unmarshal. There is no need to manage them on the manually
|
||||
// crafted structure.
|
||||
|
||||
Reference in New Issue
Block a user