ejabberd Stanza Routing

Message Routing

In case of a message sent from User A to User B, both of whom are served by the same domain, the flow of the message through the system is as follows:

  1. User A's ejabberd_receiver receives the stanza and passes it to ejabberd_c2s.
  2. After some consistency check, user_send_packet is called if the stanza is correct.
  3. The stanza is matched against any privacy lists in use and, in case of being allowed, routed by ejabberd_router:route/3.
  4. ejabberd_router:route/3 runs the filter_packet hook. filter_packet hook can drop of modify the stanza.
  5. ejabberd_router will then consult the routing table to know what do to next. It is easier to understand by looking at an example of actual routing table content:
   (ejabberd@localhost)2> ets:tab2list(route).

In that case, user is local so we need to route to same domain (in our case localhost). We then can see that we have to call ejabberd_local:route to route the message to local user. As both user are local (no server-to-server involved), it matches our expectations.

  1. ejabberd_local routes the stanza to ejabberd_sm given it's got at least a bare JID as the recipient.

  2. ejabberd_sm determines the available resources of User B, takes into account their session priorities and whether the message is addressed to a particular resource or a bare JID and appropriately replicates (or not) the message and sends it to the recipient's ejabberd_c2s process(es).

In case no resources are available for delivery (hence no ejabberd_c2s processes to pass the message to), offline_message_hook is run to delegate offline message storage.

  1. ejabberd_c2s verifies the stanza against any relevant privacy lists and sends it on the user socket if it does exist. In the case of ejabberd Business Edition and ejabberd Saas, session can be detached and push notifications can be used as a fallback. user_receive_packet hook is run to notify the rest of the system about stanza delivery to User B.

Here is a broader diagram, including server-to-server routing: