ejabberd的工程主要通过ejabberd.app 组织起来

ejabberd.erl :

application:start(ejabberd).

ejabberd_app.erl:

Mod:start(normal, _Args);  该函数中启动ejabberd_listener:start_listeners()

ejabberd_listener.erl

通过 conf 得到<!---->ejabberd_c2s,

开始listen

如果有连接,accpet之后

<!---->ejabberd_socket:start(Module, gen_tcp, Socket, Opts)

Receiver=ejabberd_receiver:start(

Socket,SockMod,none,MaxStanzaSize),

ejabberd_receiver.erl 

ejabberd_receiver是一个gen_server进程(behaviour),

receiver 收到数据(handle_info)发送到xml_stream.

xml_stream解析数据后发送到c2s状态机.

ejabber_c2s.erl

是一个gen_fsm(有限状态机),维护一系列client和server之间的状态。gen_fsm的状态改变是由gen_fsm:send_event(FsmRef,Event)触发的。在ejabberd里,ejabberd_receiver通过xml_stream把事件和xml发送至ejabber_c2s改变其状态。
  ejabber_c2s有限状态机的初始状态是wait_for_stream,其余的状态有:
wait_for_auth,wait_for_feature_request,wait_for_sasl_response,wait_for_bind,wait_for_session,session_established

ejabberd官方文档中提到的那些关于xmpp收到的事件的hook,就是在c2s中实现的。

c2s中调用ejabberd_hooks:run_fold()来运行相应的hook。

1.Presence消息流程

用户登陆过程中:

在c2s的waitforsession中调用

{Fs, Ts} = ejabberd_hooks:run_fold(

roster_get_subscription_lists,

StateData#state.server,

{[], []},

[U, StateData#state.server]),

获取from、to好友列表,分别置入state. pres_f和state. pres_t中。

客户端登陆成功后,给服务器发送

<presence id="B0DjG-12">

<status>在线</status>

<priority>1</priority>

</presence>

该presence没有目的地址(to)。

服务端收到该消息在c2s的session_established2中处理

调用presence_update(FromJID, PresenceEl,StateData)

èpresence_broadcast_first(From, NewStateData, Packet);

(1) 给state.pres_t中每个成员发送probe;

(2)给state.pres_f中每个成员发送presence

2.添加好友流程

以Lihengz 添加 admin 好友为例

下列状态值中第一项为“订阅(subscription)”,第二项为“挂起(ask)”

Lihengz的状态变化为 :out_state_change(none,none, subscribe)    -> {none, out};

Admin的状态变化为:in_state_change(none,none, subscribe)    -> {none, in};

Admin接受请求后,状态变化:out_state_change(none,in,   subscribed)   -> {from, none};

Lihengz状态变化:in_state_change(none,out,  subscribed)   -> {to, none};

如果admin也加lihengz为好友:

admin状态变化:out_state_change(from,none, subscribe)    -> {from, out};

lihengz状态变化: in_state_change(to,   none, subscribe)    -> {to, in};

lihengz接受请求后,状态变化:out_state_change(to,   in,  subscribed)   -> {both, none};

admin状态变化:in_state_change(from,out,  subscribed)   -> {both, none};

3,在服务器上添加通讯录

在服务器上为mine添加mine1为好友(mine1未设置自动添加好友)

mine客户端会收到如下消息:

<iq id="push3140513066"to="mine@xmppserver/Spark 2.6.3" from="mine@xmppserver"type="set">

<query xmlns="jabber:iq:roster">

<item jid="mine1@xmppserver" subscription="none"ask="subscribe"/>

</query>

</iq>

如果mine1拒绝请求,mine客户端就收不到后续消息了。Roster表中一直维持挂起状态。

如果mine1设置为自动添加好友,mine客户端会收到:

<iq id="push3548743800"to="mine@xmppserver/Spark 2.6.3" from="mine@xmppserver"type="set">

<query xmlns="jabber:iq:roster">

<item jid="mine1@xmppserver" subscription="both"/>

</query>

</iq>

from: http://www.cnblogs.com/unqiang/p/4402418.html

ejabberd源码流程梳理的更多相关文章

  1. Eureka服务端源码流程梳理

    一.简述 spring cloud三步走,一导包,二依赖,三配置为我们简化了太多东西,以至于很多东西知其然不知其所以然,了解底层实现之后对于一些问题我们也可以快速的定位问题所在. spring clo ...

  2. Eureka客户端源码流程梳理

    前面梳理了Eureka服务端的流程,现在整理下客户端的流程. 1.在这个包(spring-cloud-netflix-eureka-client)里面寻找客户端启动入口相关配置,关键配置文件sprin ...

  3. ClickHouse源码笔记5:聚合函数的源码再梳理

    笔者在源码笔记1之中分析过ClickHouse的聚合函数的实现,但是对于各个接口函数的实际如何共同工作的源码,回头看并没有那么明晰,主要原因是没有结合Aggregator的类来一起分析聚合函数的是如果 ...

  4. Flask 源码流程,上下文管理

    源码流程 创建对象 from flask import Flask """ 1 实例化对象 app """ app = Flask(__na ...

  5. ES6.3.2 index操作源码流程

    ES 6.3.2 index 操作源码流程 client 发送请求 TransportBulkAction#doExecute(Task,BulkRequest,listener) 解析请求,是否要自 ...

  6. django-admin的源码流程

    一.admin的源码流程 首先可以确定的是:路由关系一定对应一个视图函数 a.当点击运行的时候,会先找到每一个app中的admin.py文件,并执行 b.执行urls.py admin.site是什么 ...

  7. Django session 源码流程

    流程 Django session源码流程 首先执行的是SessionMiddleware的init方法 import_module(settings.SESSION_ENGINE) 导入了一个 dj ...

  8. rest_framework解析器组件源码流程

    rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...

  9. 【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解

    原文地址:http://blog.csdn.net/a396901990/article/details/36475213 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量—— ...

随机推荐

  1. Oracle查看用户所在表空间

    查看当前用户所在表空间 select username,default_tablespace from user_users; 修改用户默认表空间 alter user 用户名 default tab ...

  2. C语言标记化结构初始化语法

    C语言标记化结构初始化语法 (designated initializer),而且还是一个ISO标准. #include <stdio.h> #include <stdlib.h&g ...

  3. 兼容IE,Firefox,Opera等浏览器的添加到收藏夹js代码实现

    function AddToFavorites() { var title = document.title; var url = location.href; if (window.sidebar) ...

  4. Oracle和Redhat下载地址

    Oracle RedHat 用户名:zhangwei900808@126.com 密码:@XxxxxXxxxxxx 有网友想要的,请在留言板给我留言,我会把用户名和密码发给你!

  5. sentos 上安装vnc图形界面

    一.安装gnome图形化桌面   CentOS 6.3 64位 #yum groupinstall -y "X Window System" #yum groupinstall - ...

  6. XCode6.1中的ios7.1适配

    在xcode6.1中新创建的项目,运行在我的ios7.1的ipod touch上时(与5s的一样的尺寸, Retina屏幕), 上下出现了黑边,由于没有下载7.1的模拟器,不知道模拟器上有无问题, 查 ...

  7. BZOJ3404: [Usaco2009 Open]Cow Digit Game又见数字游戏

    3404: [Usaco2009 Open]Cow Digit Game又见数字游戏 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 47  Solved ...

  8. Recommender Systems 基于知识的推荐

    前两章的协同过滤和就内容的推荐都建立在“大量数据”的基础上,运用概率方法来进行计算和预测.不过,在现实生活中,有些物品,如:汽车.房屋.计算机,用户不会频繁的消费.如何在这种情况下对用户进行推荐? 这 ...

  9. easyui DateTimeBox 取值

    $('#dt').datetimebox('getValue')

  10. python参考手册--第4、5、6、7章

    1.zip zip(s,t):将序列组合为一个元组序列[(s[0],t[0]), (s[1],t[1]), (s[2],t[2]), (s[3],t[3]),...] >>> s = ...