From e3c0747cbb3463114aaac77d4915c9f72b5c2942 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Fri, 28 Jun 2019 16:19:09 +0200 Subject: [PATCH] Improves documentation: Explain how to create a custom stanza extension --- _examples/custom_stanza/README.md | 5 +++ _examples/custom_stanza/custom_stanza.go | 49 ++++++++++++++++++++++++ stanza/README.md | 32 ++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 _examples/custom_stanza/README.md create mode 100644 _examples/custom_stanza/custom_stanza.go diff --git a/_examples/custom_stanza/README.md b/_examples/custom_stanza/README.md new file mode 100644 index 0000000..1eb3b28 --- /dev/null +++ b/_examples/custom_stanza/README.md @@ -0,0 +1,5 @@ +# Custom Stanza example + +This module show how to implement a custom extension for your own client, without having to modify or fork Fluux XMPP. + +It help integrating your custom extension in the standard stream parsing, marshalling and unmarshalling workflow. diff --git a/_examples/custom_stanza/custom_stanza.go b/_examples/custom_stanza/custom_stanza.go new file mode 100644 index 0000000..46043f2 --- /dev/null +++ b/_examples/custom_stanza/custom_stanza.go @@ -0,0 +1,49 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "gosrc.io/xmpp/stanza" +) + +func main() { + iq := stanza.NewIQ(stanza.Attrs{Type: stanza.IQTypeGet, To: "service.localhost", Id: "custom-pl-1"}) + payload := CustomPayload{XMLName: xml.Name{Space: "my:custom:payload", Local: "query"}, Node: "test"} + iq.Payload = payload + + data, err := xml.Marshal(iq) + if err != nil { + log.Fatalf("Cannot marshal iq with custom payload: %s", err) + } + + var parsedIQ stanza.IQ + if err = xml.Unmarshal(data, &parsedIQ); err != nil { + log.Fatalf("Cannot unmarshal(%s): %s", data, err) + } + + parsedPayload, ok := parsedIQ.Payload.(*CustomPayload) + if !ok { + log.Fatalf("Incorrect payload type: %#v", parsedIQ.Payload) + } + + fmt.Printf("Parsed Payload: %#v", parsedPayload) + + if parsedPayload.Node != "test" { + log.Fatalf("Incorrect node value: %s", parsedPayload.Node) + } +} + +type CustomPayload struct { + XMLName xml.Name `xml:"my:custom:payload query"` + Node string `xml:"node,attr,omitempty"` +} + +func (c CustomPayload) Namespace() string { + return c.XMLName.Space +} + +func init() { + stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{"my:custom:payload", "query"}, CustomPayload{}) +} diff --git a/stanza/README.md b/stanza/README.md index 466f594..074113d 100644 --- a/stanza/README.md +++ b/stanza/README.md @@ -74,3 +74,35 @@ you may also consider [adding your own custom extensions on stanzas](). Extensions are registered on launch using the `Registry`. It can be used to register you own custom payload. You may want to do so to support extensions we did not yet implement, or to add your own custom extensions to your XMPP stanzas. + +To create an extension you need: +1. to create a struct for that extension. It need to have XMLName for consistency and to tagged at the struct level with +`xml` info. +2. It need to implement one or several extensions interface: stanza.IQPayload, stanza.MsgExtension and / or +stanza.PresExtension +3. Add that custom extension to the stanza.TypeRegistry during the file init. + +Here an example code showing how to create a custom IQPayload. + +```go +package myclient + +import ( + "encoding/xml" + + "gosrc.io/xmpp/stanza" +) + +type CustomPayload struct { + XMLName xml.Name `xml:"my:custom:payload query"` + Node string `xml:"node,attr,omitempty"` +} + +func (c CustomPayload) Namespace() string { + return c.XMLName.Space +} + +func init() { + stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{"my:custom:payload", "query"}, CustomPayload{}) +} +``` \ No newline at end of file