XMPP Connection
Find the source at https://gitlab.com/navlost.eu/xmpp/libraries/racket/xmpp.
(require xmpp/transport) | package: XMPP |
This package implements functions to connect and authenticate with an XMPP server.
Example:
(require xmpp/transport) (define jid (string->jid "user@example.net")) (define pass "s3cret!") (define conn (xmpp-connect-client jid pass)) (xmpp-send conn '(presence ()))
After connecting, the library assigns a unique JID resource automatically:
> (jid->string (xmpp-connection-jid conn))
1 Creating and managing connections
procedure
(xmpp-connect-client jid passwd [host port]) → (xmpp-connection?)
jid : jid? passwd : string? host : string? = (jid-domainpart jid) port : port-number? = XMPP-C2S-PORT
Creates a xmpp-connection object;
connects to the server, either host if provided or else (jid-domainpart jid), either on the default XMPP port (5222) or on port;
upgrades the connection to TLS;
authenticates the user with the provided jid and passwd;
randomises the jid-resourcepart and binds it; and
returns the xmpp-connection object, which is used by every other function needing to interact with the server.
procedure
(xmpp-connect-component host port domain secret) → (xmpp-connection?) host : string? port : port-number? domain : string? secret : string?
host is the hostname of the XMPP server to connect to
port is the port number to connect to, according to the server configuration (there is no standard port number or range for components).
domain is the domain name for the component itself. Technically, this is a JID without either a local part or a resource part.
secret is the shared secret between the XMPP server and the component, used during the handshake.
procedure
(xmpp-stop! conn) → (any)
conn : xmpp-connection?
2 Sending data
procedure
conn : xmpp-connection? stanza : xexpr/c
Example:
> (xmpp-send conn '(presence))
3 Receiving data
There are a number of approaches to receiving data. Incoming stanzas may be processed synchronously (either blocking the execution thread or not) or via callbacks. Callbacks may be one-off or repeating.
procedure
(xmpp-receive conn) → (or/c xexpr/c #f)
conn : xmpp-connection?
Returns #f if no stanzas are available.
Example:
> (xmpp-receive conn)
procedure
(xmpp-receive-blocking conn) → (xexpr/c)
conn : xmpp-connection?
Example:
> (xmpp-receive-blocking conn)
4 Asynchronous operation
A common way to interact with XMPP is by registering callbacks. These must conform to the contract xmpp-handler/c and get called whenever a stanza arrives.
procedure
(xmpp-set-handler conn [handler]) → (any)
conn : xmpp-connection? handler : xmpp-handler/c = default-handler
If called with no arguments, the default handler is installed, which is required when using the functions in the Callbacks section.
Otherwise, the argument must be a function taking a stanza (xexpr/c) and a (struct connnection) as arguments. The return value is ignored.
Only one handler may be set per connection. However, it is possible to have arbitrarily many callbacks.
Example:
> (xmpp-set-handler conn (λ (stanza conn) (displayln (~a "Received a new stanza of type " (car stanza)))))
procedure
(xmpp-stop-handler conn) → (any)
conn : xmpp-connection?
procedure
(xmpp-handler conn) → (or/c xmpp-handler/c #f)
conn : xmpp-connection?
5 Callbacks
For the procedures in this section to operate as intended, the default handler must be installed on the target connection, via (xmpp-set-handler conn).
procedure
(xmpp-set-callback conn callback) → (any)
conn : xmpp-connection? callback : xmpp-callback/c
procedure
(xmpp-set-callback/once conn callback) → (any)
conn : xmpp-connection? callback : xmpp-callback/once/c
Example: Remember to install the default handler.
> (xmpp-set-handler conn) ; Callback that matches any IQ stanzas of ; type "result", prints a message and returns #t. (define (iq-result-handler-once stanza conn) (match stanza ( (list 'iq (list-no-order '(type "result") _ ...) _ ...) (displayln "An IQ of type result has been seen.") #t) (_ (void)))) (xmpp-set-callback conn iq-result-handler-once) ; Two pings are sent, but only the first response to arrive ; will cause the callback to run. (xmpp-send conn `(iq ((from ,(jid->string (xmpp-connection-jid conn))) (to ,(jid-domainpart (xmpp-connection-jid conn))) (id ,(xmpp-id))) (ping ((xmlns "urn:xmpp:ping"))))) (xmpp-send conn `(iq ((from ,(jid->string (xmpp-connection-jid conn))) (to ,(jid-domainpart (xmpp-connection-jid conn))) (id ,(xmpp-id))) (ping ((xmlns "urn:xmpp:ping")))))
procedure
(xmpp-unset-callback conn callback) → (any)
conn : xmpp-connection? callback : xmpp-callback/c
procedure
(xmpp-callbacks conn) → (listof xmpp-callback/c)
conn : xmpp-connection?
6 Responding to remote interactions
procedure
(xmpp-send/callback conn stanza callback) → (any)
conn : xmpp-connection? stanza : xexpr/c callback : xmpp-callback/c
A response is defined as an incoming stanza of the same type and with the same id.
This is implemented by wrapping callback with the right logic to detect responses and registering the new function via xmpp-callback/once.
Example:
> (define ping `(iq ((from ,(jid->string (xmpp-connection-jid conn))) (to ,(jid-domainpart (xmpp-connection-jid conn))) (id ,(xmpp-id))) (ping ((xmlns "urn:xmpp:ping"))))) (xmpp-send/callback conn ping (λ (response conn) (displayln "PONG!")))
procedure
(xmpp-send/await conn stanza callback) → (any)
conn : xmpp-connection? stanza : xexpr/c callback : xmpp-callback/c
This is similar to xmpp-send/callback except that the call will block until callback returns.
7 Contracts
👉🏽 Contracts in The Racket Guide introduces contracts.
The return value of xmpp-receive (but not xmpp-receive-blocking which always returns an xexpr/c).
contract
xmpp-handler/c : contract?
A procedure suitable for xmpp-set-handler.
contract
A procedure suitable for xmpp-set-callback.
contract
A procedure suitable for xmpp-set-callback/once.