Ejabberd analysis (5) + subscription/Add friends

Source: Internet
Author: User

In the ejabberd_c2s module, the status is session_established2.

The user sends an IQ Set message to the server.

<IQ id = "M8QF3-52" type = "set"> <query xmlns = "jabber: IQ: roster "> <item jid =" 1555215557 @ kinglong "name =" 1555215557 "> <group> friends </group> </item> </query> </IQ>

The server matches

Case name of <br/> ...... <br/> to = xml: get_attr_s ("to", attrs), <br/> tojid = case to of <br/> ""-> <br/> jlib: make_jid (user, server, ""); <br/>_-> <br/> jlib: string_to_jid (to) <br/> end, <br/> ...... <br/> "IQ"-> <br/> case jlib: iq_query_info (newel) of <br/> # IQ {xmlns = xmlns} = IQ <br/> .... <br/> _-> <br/> ejabberd_hooks: Run (<br/> user_send_packet, <br/> server, <br/> [fromjid, tojid, newel]), <br/> check_privacy_route (fromjid, statedata, fromjid, tojid, newel ),

The above sectionCodeNote the tojid parsing. messages sent to the server do not include the to attribute by default. In this case, the to attribute is automatically added (This is related to the packet routing).

Ejabberd_hooks: Run (user_send_packet records the logs of messages sent by the user.

Check_privacy_route verifies the permissions and then calls ejabberd_router: Route (fromroute, to, packet) for routing.

Call do_route/3 in ejabberd_router: route:

Ejabberd_hooks: run_fold (filter_packet,First, use the package filtering module to filter and then find the PID of the module to which the route is routed in the routing table:

Case mnesia: dirty_read (route, ldstdomain) of <br/>

Note: ldstdomain = to # jid. lserver will be used here to go to the router table to check whether it is processed locally or by another server.

Use ejabberd_router: register_route (host, {apply ,? Module, route}) registers the current domain, so it routes to this module and calls the corresponding route function.

Mnesia: Write (# route {domain = ldomain, <br/> pid = PID, <br/> local_hint = localhint}) </P> <p> {apply, module, function}-> <br/> module: function (from, to, packet );Call do_route (from, to, packet) in ejabberd_local: route/3 ).

The IQ message sent by the client is initially null, but the system has automatically completed the tojid (see the previous instructions), and the resource is also empty IQ, so it will be routed to ejabberd_sm: route/3

If <br/> to # jid. luser/= ""-> <br/> ejabberd_sm: Route (from, to, packet );

That is to say, all messages sent after session_established will be routed by ejabberd_sm.

In ejabberd_sm, do_route/3 processes:

Do_route (from, to, packet) -> <br/> case lresource of <br/> ""-> <br/> case name of <br/> ...... <br/> "IQ"-> <br/> process_iq (from, to, packet );In ejabberd_sm, a message in sm_iqtable records the messages in each namespace and is finally processed by that module.

Ejabberd_sm is a gen_server that inserts records into sm_iqtable when the register_iq_handler interface is called.

The registration of these namespace processing modules is carried out by add_iq_handler/6 of the gen_iq_handler module.

-Module (gen_iq_handler) </P> <p> add_iq_handler (component, host, NS, module, function, type) -> <br/> case type of <br/> no_queue-> <br/> component: register_iq_handler (host, NS, module, function, no_queue );Jabber: IQ: the macro defined by roster is ns_roster. In the source code directory, we can find out which module calls the namespace for registration:

The following code is available in mod_roster: Start/2:

Gen_iq_handler: add_iq_handler (ejabberd_sm, host ,? Ns_roster, <br/>? Module, process_iq, iqdisc ).
The mod_roster module registers its process_iq function in ejabberd_sm as a processing method for the jabber: IQ: roster namespace.

Process_local_iq/3:

Process_local_iq (from, to, # IQ {type = type} = IQ)-> <br/> case type of <br/> set-> <br/> process_iq_set (from, to, IQ); <br/> Get-> <br/> process_iq_get (from, to, IQ) <br/> end.
The type for IQ is processed differently here. What we track currently is<IQ id = "M8QF3-52" type = "set">

<textarea readonly name="code" class="java">Process_iq_set (from, to, # IQ {sub_el = subel} = IQ)-> <br/> {xmlelement, _ name, _ attrs, Els} = subel, <br/> lists: foreach (fun (EL)-> process_item_set (from, to, El) End, ELS), <br/> IQ # IQ {type = result, sub_el = []}.</textarea> In process_iq_set, each item is traversed and process_item_set/3 is called for processing:
Process_item_set (from, to, {xmlelement, _ name, attrs, Els})-> <br/> jid1 = jlib: string_to_jid (XML: get_attr_s ("jid ", attrs), <br/> # jid {user = user, luser = luser, lserver = lserver} = from, <br/> case jid1 of <br/> error-> <br/> OK; <br/> _-> <br/> jid = {jid1 # jid. user, jid1 # jid. server, jid1 # jid. resource },< br/> ljid = jlib: jid_tolower (jid1), <br/> F = fun ()-> <br/> res = mnesia: Read ({roster, {luser, lserver, ljid}), <br/> item = case res of <br/> []-> <br/> # roster {usj = {luser, lserver, ljid}, <br/> US = {luser, lserver}, <br/> jid = jid }; <br/> [I]-> <br/> I # roster {jid = jid, <br/> name = "", <br/> groups = [], <br/> xs = []} <br/> end, <br/> Item1 = process_item_attrs (item, attrs), <br/> item2 = process_item_els (Item1, ELS), </P> <p> case item2 # roster. subpartition of <PRE name = "code" class = "Java" >%% Delete </PRE> <p>Remove-> mnesia: delete ({roster, {luser, lserver, ljid }});
% Otherwise add
_-> Mnesia: Write (item2) end,
% If the item exist in shared roster, take the % subscribe information from there:
Item3 = ejabberd_hooks: run_fold (roster_process_item, lserver, item2, [lserver]),
Case roster_version_on_db (lserver)
Oftrue-> mnesia: Write (# roster_version {US = {luser, lserver}, version = Sha: SHA (term_to_binary (now ()))});
False-> okend, {item, item3} end,
Case mnesia: transaction (f)
Of {atomic, {olditem, item }}-> push_item (user, lserver, to, item ),
Case item # roster. subtasks
Ofremove-> send_unsubscribing_presence (from, olditem ),
OK; _-> OK end;
E->? Debug ("roster: roster item set error :~ P ~ N ", [e]), OK end;

 
 

 
 

The above is the path through which an IQ message for adding/subscribing to a friend is received and eventually written to the database in ejabberd.

 
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.