`
vie61vie
  • 浏览: 10097 次
社区版块
存档分类
最新评论

Jabberd2源代码分析:c2s与router SASL验证过程

 
阅读更多

Jabberd2源代码分析:c2s与router SASL验证过程
2011年03月29日
  c2s启动后,主动连接router服务器的消息流程:
  c2s->router: 
  发送完数据后,c2s进入循环状态,在mio_run等待事件
  router->c2s:
  
  当c2s收到router发送的数据后mio_run函数内检测到有数据可读,这时调用:
  c2s_router_mio_callback(mio_action_t = action_READ)
  首先调用ioctl(fd, FIONREAD, &nbytes)得到socket缓冲区中有多少数据可读, 如果有数据可读调用sx_can_read函数。
  在sx_can_read(sx_t s)函数中:
  in = _sx_buffer_new()
  创建in用于保存读到的数据
  read = _sx_event(s, event_READ, in)
  _sx_event会调用函数c2s_router_sx_callback(sx_event_t = event_READ)
  case event_READ: 
  调用recv读取数据,读数据的长度是确定的,因为在c2s_router_mio_callback中action_READ的时候已经通过ioctl函数获取了目前缓冲区中的数据长度
  out = _sx_buffer_new(in->data, in->len, in->notify, in->notify_arg)
  创建一个in的拷贝,用于将out传入到插件函数中
  _sx_chain_io_read(s, out)函数的目的是调用插件函数rio
  插件函数中没有发生错误的话,调用数据解析函数
  _sx_process_read(s, out)
  在_sx_process_read函数中调用了XML_Parse来解析XML数据,expat解析的特点是解析的过程中会调用特定的回调函数。
  还记得么,在sx_client_init函数中,_sx_buffer_new函数中传入了一个回调函数_sx_client_notify_header函数,在该回调函数中又调用了XML_SetElementHandler(s->expat, _sx_client_element_start, _sx_client_element_end)。
  当XML_Parse解析到stream头的时候,调用_sx_client_element_start函数, 解析出stream头,重新设置解析回调函数
  XML_SetElementHandler(s->expat, _sx_element_start, _sx_element_end)
  XML_SetCharacterDataHandler(s->expat, _sx_cdata)
  XML_SetStartNamespaceDeclHandler(s->expat, _sx_namespace_start)
  调用插件函数stream
  插件sasl:
  sasl插件注册了函数stream,这里会调用sasl注册的函数_sx_sasl_stream,此时Gsasl_session指针为空,所以什么也不做,直接返回。
  如果当前状态小于state_STREAM设置状态为state_STREAM,并且调用_sx_event(event_STREAM)。
  router->c2s:
  D IGEST-MD5
  mio检测到有数据可读,经过层层回调到sx_can_read->_sx_process_read, 这次成功解析到,将解析完成后的结果保存在NAD中,并且插入到s->rnadq队列解析完成后,继续在_sx_process_read函数中。
  此时s->state的状态为state_STREAM,从s->rnadq队列中取出一个NAD,对解析的数据做错误检测,如果没有错误发生调用函数:
  sx_chain_nad_read(s, nad),该函数会调用插件函数 rnad
  调用插件函数 process
  sasl
  sasl注册了process插件函数_sx_sasl_process.
  在_sx_sasl_process函数中会判断命名空间,只有urn:ietf:params:xml:ns:xmpp-sasl的命名空间才会处理,其他命名空间的数据包直接返回不处理。
  调用_sx_event(s, event_PACKET, nad), 会调用c2s_router_sx_callback
  s->state = state_STREAM
  调用sx_sasl_auth(c2s->sx_sasl, s, "jabberd-router", "DIGEST-MD5", c2s->router_user, c2s->router_pass)
  如果采用gsasl的话
  初始化一个客户端gsasl session
  ret = gsasl_client_start(ctx->gsasl_ctx, mech, &sd);
  设置验证需要的数据
  gsasl_session_hook_set(sd, (void *) ctx);
  gsasl_property_set(sd, GSASL_AUTHID, user);
  gsasl_property_set(sd, GSASL_PASSWORD, pass);
  gsasl_property_set(sd, GSASL_SERVICE, appname);
  gsasl_property_set(sd, GSASL_HOSTNAME, hostname);
  // 设置插件数据
  s->plugin_data[p->index] = (void *) sd;
  // 构造一个nad
  nad = nad_new();
  ns = nad_add_namespace(nad, uri_SASL, NULL);
  nad_append_elem(nad, ns, "auth", 0);
  nad_append_attr(nad, -1, "mechanism", mech);
  sx_nad_write(s, nad)
  调用插件函数 wnad
  构成生成字符串:  将要发送的数据放入队列s->wbufq中,调用_sx_event(event_WANT_WRITE)
  c2s->router:
  
  router->c2s:
  cmVhbG09Im phYmJlcmQtcm91dGVyIiwgbm9uY2U9Ilo1SU4zSzRQNlVNYzViQ jlEZ0RkdUE9PSIsIHFvcD0iYXV0aCIsIGNoYXJzZXQ9dXRmLTgs IGFsZ29yaXRobT1tZDUtc2Vzcw==
  进过一系列的回调函数,最终执行到_sx_process_read函数
  调用插件函数process
  这次还会调用sasl注册的process函数_sx_sasl_process, 这一次命名空间是一样的。继续处理。
  一切顺利,将会调用_sx_sasl_response生成xml串发送给router
  c2s->router:
  dXNlcm5hbW U9ImphYmJlcmQiLCByZWFsbT0iamFiYmVyZC1yb3V0ZXIiLCBub 25jZT0ibVF3VlRVbjRtUXBweVd0UEoyTmdoQT09IiwgY25vbmNl PSI2UkpSSm53dlZJcnEvOERFaHBqSTV3PT0iLCBuYz0wMDAwMDA wMSwgcW9wPWF1dGgsIGRpZ2VzdC11cmk9ImphYmJlcmQtcm91dG VyL2Vhc3lqYWJiZXJkLmNvbSIsIHJlc3BvbnNlPWM2NGZjYTA3Y jAxMGE4ZmI4NmQ3OWVmZmFmOWY2OTg3LCBjaGFyc2V0PXV0Zi04
  只有router继续发送challenge, c2s处理机制同上,最终router发回:
  router->c2s:
  
  c2s处理机制同上,调用_sx_sasl_process函数,但这次处理不同的分支。收到success后,将当前的sx_t重置,并调用sx_client_init(s, flags, ns, to, from, version) 重新开启一个stream.
  进行第二次stream的时候,处理流程和第一次发送stream的时候有点区别。
  解析到router返回的stream的时候,c2s会调用插件函数stream, sasl注册了stream插件函数, 但第一次的时候判断Gsasl_session指针为空,所以什么也没有执行;但第二次这个指针就不为空了,这次继续往下执行,调用了函数_sx_sasl_open函数,来校验stream是否已经通过sasl验证,最终会执行到:
  _sx_state(s, state_OPEN);
  _sx_event(s, event_OPEN, NULL);
  此时当前通道的状态已经从state_STREAM转变成state_OPEN。 并且触发事件event_OPEN;
  在c2s_router_sx_callback的event_OPEN处理部分,开始一个新的请求:
  c2s->router:
  
分享到:
评论

相关推荐

    安装jabberd2服务端

    不是我写的,不过还不错。 使用配置参数安装jabberd2:

    Jabberd 即时通信服务器C++源代码

    jabber_Jabberd 即时通信服务器C++源代码,做即时通讯的可以参考。

    xmpp服务器jabberd2

    xmpp服务器:jabberd2-master.zip

    cpp-Jabberd2是一个XMPP的服务器端软件

    Jabberd2 是一个 XMPP 的服务器端软件,是新一代的 Jabberd 项目。 Jabberd2 并不是 Jabberd 1.x 的新版本,而是一个新的分支。

    开源XMPP服务器Jabberd2s.zip

    Jabberd2s 是根据开源XMPP服务器项目Jabberd2修改而来.基于Jabberd-2.3.2稳定版源码修改,主要添加以下功能: 1.通过直接修改配置文件动态配置XMPP服务器的离线与上线功能; 2.重新加载配置文件机制,通过SIGUSR1触发...

    jabberd2

    此软件为jabberd2服务器端,其中包含了常用组件.jcr组件很能弄到手啊!!!!!! <br>如果你遇到了安装的问题,可以联系我qq:47393039

    即时聊天服务器 Jabberd.zip

    即时聊天服务器 Jabberd ,Jabberd2 是一个 XMPP 的服务器端软件,是新一代的 Jabberd 项目。 Jabber...

    jabberd-2.2.5.tar.bz2

    jabberd-2.2.5.tar.bz2

    jabberd-2.1svn336-win32.msi

    jabberd-2.1svn336-win32.msi open source jabber server

    jabberd14.6.1.1

    jabberd14.6.1.1稳定版

    jabberd14

    jabberd14服务器端,包含所有常用的插件.

    AnyQ代码

    AnyQ源代码.能和jabberd14服务器通讯的客户端,目前应该是国内开源做的最好的

    Jabberd14 LDAP authentication module-开源

    与大多数LDAP身份验证解决方案不同,此模块使用其模块API(JSM)集成到Jabberd14服务器中。 它由两部分组成-模块本身和XDB帮助器。 该模块支持jabberd的1.4和1.6版本。

    jabberd2.0s8

    C语言源代码,linux平台,基于xmpp协议的即时通信服务器软件。

    [新]exodus代码

    exodus源代码,用delphi开发的,可以和jabberd2通讯..... <br>AnyQ就是在它的基础开发的... <br>想要AnyQ的代码吗? .....马上传给大家哈

    Jabberd14 automatic roster population-开源

    该模块可以指定要自动添加到联系人列表的用户。 模块的配置允许指定所有用户以及一些例外或某些JID。 它是为Jabberd14编写的(支持Jabberd的1.4和1.6)。

    ubuntu安装简单架设Jabber

    ubuntu已被广大计算机爱好者使用,Jabber作为优秀的IM工具,也被很多朋友钟爱。本文介绍了如何在ubuntu linux上安装Jabber服务器。

    cwave:旧的 Google Wave 联合协议实现和工具

    cwave 基于 jabberd2 代码。 此实现是一个 alpha 质量的 wave 联合服务器(协议 0.2)。 C 代码允许与尽可能广泛的硬件和应用程序堆栈集成。 Cwave 扩展了 wave 的极限,例如互联网非线性视频编辑。

    Jabberd1.4 LDAP auth component-开源

    py_xdb_auth是一个小型但健壮的jabber组件,基于twist来针对ldap对jabber用户进行身份验证。 它是为jabberd 1.4编写的,基于twisted和python-ldap。

    软电话+即时通讯[part2]

    这是一个用java写的软电话客户端,还集成了jabberd2的客户端,能和MSN,GTALK等即时通讯系统互通...

Global site tag (gtag.js) - Google Analytics