Add support for delegation namespace packet parsing
Refactor and clean up pubsub & pep files
This commit is contained in:
parent
cc2fa7307f
commit
c6f0d03f60
34
component.go
34
component.go
|
@ -216,6 +216,40 @@ func (handshakeDecoder) decode(p *xml.Decoder, se xml.StartElement) (Handshake,
|
|||
return packet, err
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Component delegation
|
||||
// XEP-0355
|
||||
|
||||
// Delegation can be used both on message (for delegated) and IQ (for Forwarded),
|
||||
// depending on the context.
|
||||
type Delegation struct {
|
||||
MsgExtension
|
||||
XMLName xml.Name `xml:"urn:xmpp:delegation:1 delegation"`
|
||||
Forwarded Forwarded // This is used in iq to wrap delegated iqs
|
||||
Delegated Delegated // This is used in a message to confirm delegated namespace
|
||||
}
|
||||
|
||||
func (d *Delegation) Namespace() string {
|
||||
return d.XMLName.Space
|
||||
}
|
||||
|
||||
type Forwarded struct {
|
||||
XMLName xml.Name `xml:"urn:xmpp:forward:0 forwarded"`
|
||||
IQ IQ
|
||||
Message Message
|
||||
Presence Presence
|
||||
}
|
||||
|
||||
type Delegated struct {
|
||||
XMLName xml.Name `xml:"delegated"`
|
||||
Namespace string `xml:"namespace,attr,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
TypeRegistry.MapExtension(PKTMessage, xml.Name{"urn:xmpp:delegation:1", "delegation"}, Delegation{})
|
||||
TypeRegistry.MapExtension(PKTIQ, xml.Name{"urn:xmpp:delegation:1", "delegation"}, Delegation{})
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Add support for discovery management directly in component
|
||||
TODO: Support multiple identities on disco info
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package xmpp // import "gosrc.io/xmpp"
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"encoding/xml"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHandshake(t *testing.T) {
|
||||
opts := ComponentOptions{
|
||||
|
@ -21,3 +24,72 @@ func TestHandshake(t *testing.T) {
|
|||
func TestGenerateHandshake(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// We should be able to properly parse delegation confirmation messages
|
||||
func TestParsingDelegationMessage(t *testing.T) {
|
||||
packetStr := `<message to='service.localhost' from='localhost'>
|
||||
<delegation xmlns='urn:xmpp:delegation:1'>
|
||||
<delegated namespace='http://jabber.org/protocol/pubsub'/>
|
||||
</delegation>
|
||||
</message>`
|
||||
var msg Message
|
||||
data := []byte(packetStr)
|
||||
if err := xml.Unmarshal(data, &msg); err != nil {
|
||||
t.Errorf("Unmarshal(%s) returned error", data)
|
||||
}
|
||||
|
||||
// Check that we have extracted the delegation info as MsgExtension
|
||||
var nsDelegated string
|
||||
for _, ext := range msg.Extensions {
|
||||
if delegation, ok := ext.(*Delegation); ok {
|
||||
nsDelegated = delegation.Delegated.Namespace
|
||||
}
|
||||
}
|
||||
if nsDelegated != "http://jabber.org/protocol/pubsub" {
|
||||
t.Errorf("Could not find delegated namespace in delegation: %#v\n", msg)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we can parse a delegation IQ.
|
||||
// The most important thing is to be able to
|
||||
func TestParsingDelegationIQ(t *testing.T) {
|
||||
packetStr := `<iq to='service.localhost' from='localhost' type='set' id='1'>
|
||||
<delegation xmlns='urn:xmpp:delegation:1'>
|
||||
<forwarded xmlns='urn:xmpp:forward:0'>
|
||||
<iq xml:lang='en' to='test1@localhost' from='test1@localhost/mremond-mbp' type='set' id='aaf3a' xmlns='jabber:client'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<publish node='http://jabber.org/protocol/mood'>
|
||||
<item id='current'>
|
||||
<mood xmlns='http://jabber.org/protocol/mood'>
|
||||
<excited/>
|
||||
</mood>
|
||||
</item>
|
||||
</publish>
|
||||
</pubsub>
|
||||
</iq>
|
||||
</forwarded>
|
||||
</delegation>
|
||||
</iq>`
|
||||
var iq IQ
|
||||
data := []byte(packetStr)
|
||||
if err := xml.Unmarshal(data, &iq); err != nil {
|
||||
t.Errorf("Unmarshal(%s) returned error", data)
|
||||
}
|
||||
|
||||
// Check that we have extracted the delegation info as IQPayload
|
||||
var node string
|
||||
for _, ext := range iq.Payload {
|
||||
if delegation, ok := ext.(*Delegation); ok {
|
||||
payload := delegation.Forwarded.IQ.Payload
|
||||
if len(payload) > 0 {
|
||||
payload := delegation.Forwarded.IQ.Payload[0]
|
||||
if pubsub, ok := payload.(*PubSub); ok {
|
||||
node = pubsub.Publish.Node
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if node != "http://jabber.org/protocol/mood" {
|
||||
t.Errorf("Could not find mood node name on delegated publish: %#v\n", iq)
|
||||
}
|
||||
}
|
||||
|
|
72
pep.go
72
pep.go
|
@ -1,25 +1,11 @@
|
|||
package xmpp // import "gosrc.io/xmpp"
|
||||
|
||||
// TODO: Move to a pubsub file
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
type PubSub struct {
|
||||
XMLName xml.Name `xml:"http://jabber.org/protocol/pubsub pubsub"`
|
||||
Publish Publish
|
||||
}
|
||||
|
||||
type Publish struct {
|
||||
XMLName xml.Name `xml:"publish"`
|
||||
Node string `xml:"node,attr"`
|
||||
Item Item
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
XMLName xml.Name `xml:"item"`
|
||||
Tune Tune
|
||||
}
|
||||
|
||||
type Tune struct {
|
||||
XMLName xml.Name `xml:"http://jabber.org/protocol/tune tune"`
|
||||
Artist string `xml:"artist,omitempty"`
|
||||
|
@ -31,53 +17,9 @@ type Tune struct {
|
|||
Uri string `xml:"uri,omitempty"`
|
||||
}
|
||||
|
||||
/*
|
||||
type PubsubPublish struct {
|
||||
XMLName xml.Name `xml:"publish"`
|
||||
node string `xml:"node,attr"`
|
||||
item PubSubItem
|
||||
type Mood struct {
|
||||
XMLName xml.Name `xml:"http://jabber.org/protocol/mood mood"`
|
||||
// TODO: Custom parsing to extract mood type from tag name
|
||||
// Mood type
|
||||
Text string `xml:"text,omitempty"`
|
||||
}
|
||||
|
||||
type PubSubItem struct {
|
||||
xmlName xml.Name `xml:"item"`
|
||||
}
|
||||
|
||||
type Thing2 struct {
|
||||
XMLName xml.Name `xml:"publish"`
|
||||
node string `xml:"node,attr"`
|
||||
tune string `xml:"http://jabber.org/protocol/tune item>tune"`
|
||||
}
|
||||
|
||||
type Tune struct {
|
||||
artist string
|
||||
length int
|
||||
rating int
|
||||
source string
|
||||
title string
|
||||
track string
|
||||
uri string
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func (*Tune) XMPPFormat() string {
|
||||
return fmt.Sprintf(
|
||||
`<iq type='set' id='%s'>
|
||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||
<publish node='http://jabber.org/protocol/tune'>
|
||||
<item>
|
||||
<tune xmlns='http://jabber.org/protocol/tune'>
|
||||
<artist>%s</artist>
|
||||
<length>%i</length>
|
||||
<rating>%i</rating>
|
||||
<source>%s</source>
|
||||
<title>%s</title>
|
||||
<track>%s</track>
|
||||
<uri>%s</uri>
|
||||
</tune>
|
||||
</item>
|
||||
</publish>
|
||||
</pubsub>
|
||||
</iq>`)
|
||||
}
|
||||
*/
|
||||
|
|
39
pubsub.go
Normal file
39
pubsub.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package xmpp // import "gosrc.io/xmpp"
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
type PubSub struct {
|
||||
XMLName xml.Name `xml:"http://jabber.org/protocol/pubsub pubsub"`
|
||||
Publish Publish
|
||||
Retract Retract
|
||||
// TODO <configure/>
|
||||
}
|
||||
|
||||
func (p *PubSub) Namespace() string {
|
||||
return p.XMLName.Space
|
||||
}
|
||||
|
||||
type Publish struct {
|
||||
XMLName xml.Name `xml:"publish"`
|
||||
Node string `xml:"node,attr"`
|
||||
Item Item
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
XMLName xml.Name `xml:"item"`
|
||||
Id string `xml:"id,attr,omitempty"`
|
||||
Tune Tune
|
||||
}
|
||||
|
||||
type Retract struct {
|
||||
XMLName xml.Name `xml:"retract"`
|
||||
Node string `xml:"node,attr"`
|
||||
Notify string `xml:"notify,attr"`
|
||||
Item Item
|
||||
}
|
||||
|
||||
func init() {
|
||||
TypeRegistry.MapExtension(PKTIQ, xml.Name{"http://jabber.org/protocol/pubsub", "pubsub"}, PubSub{})
|
||||
}
|
|
@ -8,6 +8,11 @@ import (
|
|||
The XMPP router helps client and component developers select which XMPP they would like to process,
|
||||
and associate processing code depending on the router configuration.
|
||||
|
||||
Here are important rules to keep in mind while setting your routes and matchers:
|
||||
- Routes are evaluated in the order they are set.
|
||||
- When a route matches, it is executed and all others routes are ignored. For each packet, only a single
|
||||
route is executed.
|
||||
|
||||
TODO: Automatically reply to IQ that do not match any route, to comply to XMPP standard.
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in a new issue