[微程式-技術研討會]xmpp(rfc-3920) 導讀

XMPP協定導讀


一. 什麼是jabber? 什麼是xmpp?

The Extensible Messaging and Presence Protocol (XMPP) is an open Extensible Markup Language XML [XML] protocol for near-real-time messaging, presence, and request-response services. The basic syntax and semantics were developed originally within the Jabber open-source community, mainly in 1999. In 2002, the XMPP WG was chartered with developing an adaptation of the Jabber protocol that would be suitable as an IETF instant messaging (IM) and presence technology. As a result of work by the XMPP WG, the current memo defines the core features of XMPP 1.0; the extensions required to provide the instant messaging and presence functionality defined in RFC 2779 [IMP REQS] are specified in Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence [XMPP IM].


二. Socket/XMPP 程式需注意的幾個重點

1.架構(select poll epoll AIO kqueue IOCP / Thread / Process / LWP)

2.setsockopt比較值得討論的參數
setsockopt( $listen,SOL_SOCKET,SO_REUSEADDR,1); 伺服端
setsockopt( $sockfd,SOL_SOCKET,SO_KEEPALIVE,pack("l",$SO_KEEPALIVE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPIDLE,pack( "l", $TCP_KEEPIDLE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPCNT,pack( "l", $TCP_KEEPCNT ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPINTVL,pack( "l", $TCP_KEEPINTVL ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_NODELAY,pack( "l", 1 ) );
setsockopt( $listen, SOL_SOCKET, SO_RCVBUF, 8192 );
setsockopt( $listen, SOL_SOCKET, SO_SNDBUF, 8192 );

3.flow(read/sysread/write/syswrite buffer)

4.XML Stream (SAX/DOM)


三. XMPP (RFC-3920 導讀)

1. XMPP 協定

Rfc-3920
Rfc-3921
Rfc-3922
Rfc-3923
Rfc-4622
可參考網站
http://www.xmpp.org/rfcs/
http://www.xmpp.org/extensions/
http://wiki.jabbercn.org/space/start
http://hi.baidu.com/jabber/blog/category/Jep


2. XML STREAM

<stream>
<presence>
<show/>
</presence>
<message to='foo'>
<body/>
</message>
<iq to='bar'>
<query/>
</iq>

</stream>


3. xmpp 的主要xml 標籤

訊息傳遞:<message/>
線上資訊:<presence/>
查詢與回應:<iq/>
目前實做的功能
<query xmlns=‘http://jabber.org/protocol/disco#info’>
<identity category='server' name='MJS' type='im'/>
<feature var='http://jabber.org/protocol/disco#info'/>
<feature var='http://jabber.org/protocol/disco#items'/>
<feature var='jabber:iq:private'/>
<feature var='jabber:iq:roster'/>
<feature var='jabber:iq:time'/>
<feature var='msgoffline'/>
</query>


4. 交易

以下定義
C->S 為CLIENT 傳送資料到 SERVER,
S->C 定義為伺服器傳遞資料給CLIENT,
Cn 代表第n個client

C1->S (Part1)
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>

S->C1 (Part2)
<?xml version='1.0'?>
<stream:stream
from='127.0.0.1’
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>

.認證與BINDING過程…(文件稍後會解釋交易過程) ,目前server不支援tls 的交易

C1->S
<message from='luke_shei@127.0.0.1/Resource1'
to=' admin@127.0.0.1/Resource2'
xml:lang='zh-tw' id=’R1-2’><body><測試訊息></body></message>

C1->S->C2(C1傳遞資訊給SERVER ,再經由JID 的資訊傳送給C2)

C2->S
<message from=' admin@127.0.0.1/Resource2'
to=' luke_shei@127.0.0.1/Resource1'
xml:lang='zh-tw' id=’R1-2’>
<body>回應訊息</body>
</message>

C2->S->C1(C2傳遞資訊給SERVER ,再經由JID 的資訊傳送給C1)

C1->S
</stream:stream>
S->C1
</stream:stream>

4.1 from/to 屬性:

a.C->S
b.S->C
Att /Action initiating to receiving receiving to initiating
to hostname of receiver silently ignored
From silently ignored hostname of receiver
id silently ignored session key
xml:lang default language default language
version signals XMPP 1.0 support signals XMPP 1.0 support

4.2 jid(Jabber Identifier) 形式:

a.node@domain/resource
b.node@domain
ps:事實上node 指的是用後帳號,目前;我們不支援將a,b 視為同一帳號的兩個不同的資
源binding,因此; node@domain/resource1 與node@domain/resource2 再目前的
系統是視為同一帳號的登入,而目前不支援同一帳號重覆登入


5. XMPP 需注意的事項

A. 內容替換

#x22 (")
#x26 (&)
#x27 (')
#x2F (/)
#x3A (:)
#x3C (<)
#x3E (>)
#x40 (@)

B. XML為case sensitive, 包括:認證所使用的UID
C.屬性皆以 ‘ 做為分隔
D.屬性是沒有順序性的
E.文件字集應該使用UTF-8
F.同一帳號應該以登入一次為限
G. 不應該預期交易的過程是否有斷行
I.Client 要斷線前,應保持良好習慣先傳遞
<presence type="unavailable"/></stream:stream> 再執行斷線


6. 認證交易(SASL RFC-2831)

(前略) 參考前述Part1 Part2

<Server 告知Client , 目前支援的認證型態>
S->C
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Ps:目前規劃使用的是 DIGEST-MD5 , PLAIN是為了讓SPARK(Jabber Client可以進行測試),而jabber::component 目前使用的是另一種handshark的機制


<Client 選擇一個認證機制>
C->S
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechani
sm='DIGEST-MD5'/>

Server 傳送challenge code
S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOX
RFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmL
TgsYWxnb3JpdGhtPW1kNS1zZXNzCg==</challenge>
中間這字串解開base 64 後的資訊為
realm="somerealm",nonce="OA6MG9tEQGm2hh",qop="auth",
charset=utf-8,algorithm=md5-sess


Client 傳送challenge code 給server
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlY
WxtIixub25jZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0i
T0E2TUhYaDZWcVRyUmsiLG5jPTAwMDAwMDAxLHFv
cD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5j
b20iLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwY
TE1MjMyMWYyMTQzYWY3LGNoYXJzZXQ9dXRmLTgK
</response>
中間字串的base64解碼為
username="somenode",realm="somerealm",nonce="
OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",
nc=00000001,qop=auth,digest-uri="xmpp/example.com"
,response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
<如驗證失敗 伺服器回應認證失敗>
S->C
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
隨即斷線


<伺服器傳送驗證碼>

S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cn
NwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJh
YmNkZmZmZAo=</challenge>
中間字串BASE64解碼為
rspauth=ea40f60335c427b5527b84dbabcdfffd


<CLIENT 回應驗證碼正確性>
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>


<伺服器回應認證成功>
S->C
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>


<認證成功後 Client 重新初始化 xml stream>
C->S
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>


<伺服器回應所支援的feature>
S->C
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</stream:features>


<Client 請求Binding>
C->S
<iq id="jcl_8" type="set"><bind xmlns="urn:ietf:
params:xml:ns:xmpp-bind"><resource>Exodus<
/resource>
</bind></iq>


<伺服器回應Bind 的資源>
S->C
<iq type='result' id='jcl_8'><bind xmlns='urn:ietf:params
:xml:ns:xmpp-bind'><jid>admin@127.0.0.1/Exodus<
/jid><
/bind></iq>


<Client 請求session 交易>
C->S
<iq id="jcl_9" type="set"><session xmlns="urn:ietf:params:
xml:ns:xmpp-session"/></iq>


<Server 回應 session 交易>
S->C
<iq type='result' id='jcl_9'><session xmlns='urn:ietf:params:xml:
ns:xmpp-session'></session></iq>


5.認證演算過程

A. Server 傳送challenge code
S->C
BASE64(realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",
qop="auth", algorithm=md5-sess,charset=utf-8)

B. Client 傳送challenge code 給server
以下定義
開頭為$者為變數
開頭為 $$realm_xyz 代表該變數來自於realm 的屬性,而範例的值為xyz
以下範例 chris 為一個帳號名稱
+ 代表字串相加
‘ 代表固定字串內的值
MD5 代表其內字串使用MD5做簽章但不轉成HEX CODE
MD5_HEX 代表其內字串使用MD5做簽章且轉成HEX CODE

C->S
$PASSWORD 為該USER 的密碼
$A1=(MD5(‘chris’ + ‘:’ + $$realm_elwood.innosoft.com + ‘:’ + $PASSWORD) + ‘:’ + $$nonce _OA6MG9tEQGm2hh + ‘:’ + $$conce_OA6MHXh6VqTrRk)
$A2=’AUTHENTICATE’ + ‘:’ + $$realm_jabber/elwood.innosoft.com

$response=MD5_HEX(MD5_HEX($A1)+’:’+ $$nonce_OA6MG9tEQGm2hh +’:’+ $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk+’:’+ $$qop_auth +’:’ + MD5_HEX($A2))

Base64(charset=utf-8,username="chris",realm="elwood.innosoft.com", nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", digest-uri="jabber/elwood.innosoft.com",response=$response,qop=auth)

Server 隨即驗證 $response 如失敗則回傳失敗,否則進行下一個動作

C: 伺服器傳送驗證碼
rspauth=MD5_HEX(MD5_HEX($A1) + ‘:’ + $$nonce_OA6MG9tEQGm2hh + ’:’ + $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk + ’:’ + $$qop_auth+MD5_HEX(‘:’ + $$digest-uri _jabber/elwood.innosoft.com))

Client 應該檢驗 rspauth


七.相關資源

Jabber Client下載位置

Exodus ( http://www.jabberstudio.org/projects/exodus/releases/ )
Pandion( http://www.pandion.be/download/ )
Spaek( http://www.igniterealtime.org/downloads/download-landing.jsp?file=spark/spark_2_5_2.exe )

C 所常用的 XML parser library
http://expat.sourceforge.net/

msxml sax相關資源
http://www.perfectxml.com/msxmlSAX.asp
張貼留言