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