Events
Prosody is powered by events. From events to notify about the state of the server (startup, shutdown, etc.) to events about incoming connectections, stanzas, and other data.
An event is a notification that something has happened, or is about to happen. In Prosody each event has a unique name, which is how events are identified.
If you want to do something when a certain event occurs, for example send a message to a user when they log in, then you want to "hook" that event. This involves attaching a handler function which will be called each time the event occurs. There are functions in the module API to help you do this.
This page serves as a list of the different events that Prosody may generate internally that modules may be interested in.
Server status
Prosody goes through several stages during startup and shutdown. An event is fired for each transition. The table below lists each event and its meaning. All of these events are global (see module:hook_global()).
server-starting | The server is starting. Plugin modules may not catch this event because they will not have been loaded yet. |
server-started | All server initialisation is complete and all modules loaded. May not be accepting client connections yet though. |
server-stopping | The server is preparing to shut down. |
server-stopped | All shutdown preparation is complete, the server process is about to quit. This is always the last core event. |
config-reloaded | The server's configuration reloaded |
None of these events receive any data, except config-reloaded. This receives an event object with the parameters 'filename', 'format' and 'config' (the parsed config). This event is also used to reopen log files.
User sessions
Among the first things a client must do when connecting is authenticate. Once that is completed, prosody fires:
authentication-success
Or, if the authentication attempt failed:
authentication-failure
After authentication a client binds a resource, which is a unique identifier for that connection. This is the best way to know when a user has logged in or out (but they won't have sent presence or anything else yet).
On allocating a resource to a new session, Prosody fires:
resource-bind
and when a session disconnects (gracefully or not):
resource-unbind
The session will be destroyed shortly after.
All of these events receive an event object with a 'session' field containing the session in question. Additionally, resource-unbind's event object has an 'error' field (that may be nil), with a human-readable message describing why the user is disconnecting, and authentication-failure has 'condition' containing the error code and 'text' with a human-readable message.
Stanzas
Stanza events are composed of the name and the destination JID type. For example "message/bare". Names may be one of "message", "presence", "iq" - JID type may be "bare", "full", "host", or "self".
All of them receive an event object with two fields, 'origin' and 'stanza'. The origin is the session object that the stanza originated from (either the local user session, an s2s session, or a local host or component). The stanza is a stanza object.
To reply to a stanza you can use module:send(), or event.origin.send(). There are two helpers in util.stanza for building responses, util.stanza.reply() and util.stanza.error_reply().
Pre-routing
To handle messages received from local clients, whether they are destined for a local or remote JID, use the pre-routing family of events. They are of the form:
pre-NAME/DEST
Where NAME is one of 'message', 'presence' or 'iq'. DEST is the type of the destination JID, and may be 'full' (destination JID has a resource), 'bare' (destination JID has no resource) or 'host' (destination JID is a host, such as "example.com").
Return true from your handler to block the outgoing stanza.
Post-routing
For stanzas that have been routed, these events are fired before delivery to the local entity (client, component or host) they are addressed to. The event is fired on the host in the JID it is addressed to. The event is simply of the form:
NAME/DEST
Again, NAME may be 'message', 'presence' or 'iq', and DEST one of 'full', 'bare' or 'host'. Return true from your handler to prevent delivery of the stanza.
iq stanzas
If NAME is iq and DEST is one of 'bare' or 'host', there are also some additional events fired if nothing handled the above generic one:
iq/DEST/XMLNS:TAG
If still not handled then TYPE is set to the 'type' attribute of the stanza. This may be 'get'/'set' or 'result'/'error'. If either 'get' or 'set', this event is fired:
iq-TYPE/DEST/XMLNS:TAG
If the iq is of TYPE 'result' or 'error' then the ID is fetched from the 'id' attribute, and this event is fired:
iq-TYPE/DEST/ID
Priorities
To ensure that modules handle stanzas in the correct order, some guidance is provided below on what priorities should be used for post-routing event handlers.
Priority range
Purpose
-1
Delivery to the session only
0
"Read-only" stanza interception, for stanzas that are going to be delivered, e.g. for archiving. Do not modify or drop the stanza in priority 0 handlers.
1 - 999
For general processing modules that may modify or drop stanzas
1000+
Pre-processing filters, typically used to drop stanzas before they are seen by most modules.
Self-addressed
XMPP has certain self-addressed stanzas, either the 'to' JID is the user's own bare JID or there is no 'to' on the stanza at all (they are equivalent). Prosody removes the 'to' attribute from these stanzas for consistency, and then fires a /self event:
NAME/self
The NAME is one of the stanza types, and /self remains constant. Because these events never fire for stanzas from other users, they may be used to implement private per-user functionality such as account management.
If the stanza is an 'iq' stanza, the iq-specific events described above are also fired (with DEST 'self').
Initial presence
When a client changes its presence, 'presence/bare' (and 'presence/self') are fired. If the session was unavailable (seen as offline) before sending a normal available presence, a special event is fired:
presence/initial
This normally happens when the client is done with the login, resource binding and other startup things.
Other stanzas and stream elements
These are stanzas which either come on unauthenticated connections, or are not actually stanzas (not under the jabber:client namespace), such as stream feature negotiations.
Stanzas for remote hosts
route/remote
Stanzas addressed to remote servers are passed through this event.
Unauthenticated IQ stanzas
IQ stanzas received from connections that have not yet authenticated fire:
stanza/iq/XMLNS:TAG
Here XMLNS is the namespace of the iq's child element, and TAG is the name of that element.
Other unauthenticated stanzas
stanza/KIND
Where KIND may be 'message' or 'presence'.
Non-stanzas
Technically anything other than 'message', 'presence' or 'iq' is not a stanza. However these other elements fire an event prefixed with 'stanza/' for consistency:
stanza/XMLNS:TAG
Where XMLNS is the namespace and TAG is the name of the element. These elements are typically stream feature negotiations such as TLS, SASL or compression.
Components
These events are fired by mod_component for external components, and can be used for tracking whether a component is online/offline. They are fired on the component's host, so you need to load your module explicitly onto that host to receive these events.
Event name | Fields | Description |
component-authenticated | session | Fired on a component host when an external component has successfully authenticated (and therefore assumed control of its domain). |
component-disconnected | session, err | A component has disconnected. |