go-xmpp v0.5.0
A new version of the go-xmpp library, which can be used to write XMPP clients or components in Go, has been released. It’s available on GitHub.
You can find the full changelog here : CHANGELOG
This version essentially adds support for Stream Management (XEP-0198), and post-connect/post-reconnect hooks for XMPP clients. Read more below !
Support for Stream Management (XEP-0198)
Acking
“Acking” is the tracking of stanzas at the client level, meaning at higher levels than TCP for instance.
The receiving entity keeps a counter of successfully processed stanzas for a given session, and can communicate this counter to the other entity.
In go-xmpp, if Client.Config.StreamManagementEnable is set to “true”, all sent stanzas will be both sent and put into a queue.
If an ack request is made to the server, depending on the response, some stanzas will be discarded, because the server already handled them, or resent because the server never got them.
Here’s how one would ask for acks :
r := stanza.SMRequest{}
client.Send(r)
Resumption
Stream resume capabilities were also added in this release.
Stream resumption allows to resume a session with the server without going through the entire ceremony of the protocol; it essentially skips some steps.
When a client is created using go-xmpp, one can specify a handler for the client’s event manager. Basically, every time the client changes states (connected -> disconnected for instance), the handler is executed.
Here’s we would use the handler to resume an interrupted stream :
// Create a client. Skipped for brevity
// Create a handler for that client. Triggered when changing state
handler := func(e Event) error {
switch e.State.state {
// Some states are skipped.
// See "StreamManager" in the lib for a more thorough example)
case StateDisconnected:
// Reconnect on disconnection
return client.Resume()
case StatePermanentError:
// Do not attempt to reconnect
}
return nil
}
// Add the handler to the client
client.SetHandler(handler)
Now a disconnection because of network outage would trigger a stream resumption.
Post-(re)connect hooks
To help with designing clients, two post connection hooks were added to Client :
- PostConnectHook
Will be triggered when calling Client.Connect(). Can be used to retrieve the roster for instance. - PostResumeHook
Will be triggered when using Client.Resume(). Do different operations when reconnecting, and skipping roster if we already have it for example.
One would just assign them as follows :
config := Config{
TransportConfiguration: TransportConfiguration{
Address: testServerAddress,
},
Jid: "test@localhost",
Credential: Password("test"),
Insecure: true}
var client *Client
var err error
router := NewRouter()
// client default handler omitted for brevity
if client, err = NewClient(&config, router, clientDefaultErrorHandler); err != nil {
log.Fatalf("connect create XMPP client: %s", err)
}
// Assign hooks to the client
client.PostConnectHook = func() error {
go func() {
// ask server for roster, omitted here
}()
return nil
}
client.PostResumeHook = func() error {
go func() {
// do something else when we try to resume. We already have the roster if this gets triggered
}()
return nil
}
And that’s it ! Hooks will be triggered automatically when relevant.