跳到主要內容

[微程式-技術研討會]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

留言

這個網誌中的熱門文章

怎麼在網路上註冊成為youbike 會員?

新版官網請參考  怎麼在網路上註冊成為youbike 會員?   http://rd-program.blogspot.tw/2014/04/youbike.html 網路的申請步驟類似,下面將以網路申請來說明申請步驟:申請的時候需要準備悠遊卡、或晶片信用卡,以及手機門號。 1. 請先登入ubike網址: http://www.youbike.com.tw/ ,登入後選擇【正體中文】,要選英文也可以啦! 2. 在螢幕的右上角選擇【註冊】。 3.點擊【開始註冊】。 4. 點擊【同意】。(沒有其他選擇?) 5. 輸入您的【手機號碼】以及【認證碼】,然後按【送出】。這時候手機會收到ubike傳來的簡訊,通之驗證碼,有四個阿拉伯數字。 6. 輸入帳號(手機號碼)、驗證碼(ubike傳到手機的簡訊)、密碼,然後按【下一步】。 7. 還沒完成喔!這裡告訴你如何租車及還車的步驟。把螢幕拉到最下面,記得勾選【我已清楚瞭解租還車步驟】,然後按【下一步】。 8. 選擇悠遊卡或是晶片信用卡,然後輸入卡片號碼,卡片號碼請參卡畫面又下方的提示位置,請注意有些卡號可能已經模糊不清,可能無法輸入。每隻手機不只可以輸入一個卡號。 9. 填寫個人姓名及Email帳號,如果不想收到相關訊息就把前面的打勾取消。按【確認】按鈕。 10. 恭喜您註冊成功,可已開始使用YouBike了。

Youbike 線上註冊會員

Youbike 線上註冊會員 https://www.youbike.com.tw/cht/f61.html youbike sitemap   網站內容快速連結  場站地圖 場站列表 服務中心資訊 預計設站地點 媒體報導 活動情報 緊急通知 營運資訊 營運成果 關於YouBike 大事記 設備介紹 租還方式 費率說明 安全騎乘 分類列表 失物招領 YouBike協尋 加入會員 會員資料管理 YouBike電子報 騎乘記錄查詢 合作夥伴 友站連結 一般文件 APP 隱私權政策 連絡我們