Personal tools
You are here: Home コラム 技術コラム XMPP(Jabberのプロトコル)技術メモ
Document Actions

XMPP(Jabberのプロトコル)技術メモ

XMPPの一般的な説明は、IDGの記事(http://www.idg.co.jp/headline/focus20030425a.html)でも見てください。

技術的には、あのlirisさんがいくつか記事を書いています。
- その1
- じじいになった、その2

rfc3920をざっと眺めてみました。

次のような観点で読んだので、XMPPの全てを網羅しているわけではありません。
- ネットワーク的な動作イメージはどんなものか?
- 構成要素技術はどんなものか?


感想


読んだ第一の感想(驚き)は、「メールと変わらない」です。
「1.セッションを張りっぱなし(注1)で、2.転送メッセージのフォーマットがXML、のメールシステム」をイメージすると、XMPPの動作イメージの70%は掴めていると思います。

もうひとつの感想は、実装先行の泥臭さを感じさせる部分です。
悪く言うと、そんなに美しさを感じさせるアーキテクチャではありません。
しかし、個人的には、概念的な美しさ(複雑さ?)の割に使い物になるか分からないアーキテクチャよりも、XMPPのように実装に裏打ちされた泥臭いアーキテクチャの方が好きです。

この手のアーキテクチャには次の特長があると思います。
- シンプルであること
- 例外(エラー)ケースを過小評価しないこと
少し毒舌を混ぜると、おそらくXMPP v2では、前者がどこかに行ってしまうと思います。


動作イメージ


動作イメージを喚起させるため、最初は、細部の正確さをあえて捨てます。
動作イメージの全体像を掴んでからの方が、細部の要素の意味を理解しやすいと思うからです。

以下、メールアドレスは、暗黙にユーザを示すと同時に、そのユーザが使うXMPP(クライアント)ソフトも意味します。

シナリオ


- "suzuki@foo.com"が"tanaka@foo.com"にメッセージを送るケース
- foo.comドメインのXMPPサーバのホスト名をxmpp-serv.foo.comとします

時系列的な動作


引用:

+ "suzuki@foo.com"がxmpp-serv.foo.comサーバに接続します(この接続セッションをstreamと呼びます)。
+ "suzuki@foo.com"とxmpp-serv.foo.comサーバとの間のやりとりは次のように進みます。

"suzuki@foo.com": stream開始のhandshake処理(一種のログイン処理を含む)
xmpp-serv.foo.com: stream開始のhandshake処理
...
handshake処理終わり
"suzuki@foo.com": streamへのresource bindingを送信(告知のようなもの)
xmpp-serv.foo.com: resource bindingへのack

この時点で、上のstreamが残っている限り、サーバはstreamに対応(=bind)するユーザおよびリソースの状態を保持できます。

+ "tanaka@foo.com"も、xmpp-serv.foo.comと同様にstreamを確立したとします。

+ "suzuki@foo.com"からxmpp-serv.foo.comに向けて、stream上に次のXMLが送信されたとします。
<message from='suzuki@foo.com' to='tanaka@foo.com'>
<body>Hello</body>
</message>

+ xmpp-serv.foo.comはto属性を見ます。自分宛のドメインなので、保持しているstreamから"tanaka@foo.com"の streamを探して、そのstream上にメッセージ(XML)を送信します(streamが無ければ、"suzuki@foo.com"にエラーを返 す)。



ここまで見て、メールそっくりと言った意味が理解できると思います。

to属性の宛先が別(DNS)ドメインの場合、別ドメインにあるXMPPサーバにメッセージを転送します。

ここでの疑問は、「どうやって別ドメインのXMPPサーバを見つけるか」ですが、次のようになります。
- サーバ間にstreamが既にある場合(固定的なトポロジ?)は、そのstreamを使います
- DNSの"xmpp-server"のSRVエントリを引いてサーバホスト名を見つけて、streamを開始(「14.4. Server-to-Server Communications」)

DNSのMXレコードを索く代わりに、DNSのSRVエントリを索くだけの違いと見れば、メールと変わりません。


「メー ルそっくりだ」と繰り返し言っていると、XMPPをおとしめているようにも見えるかもしれませんが、そんなつもりはありません。ただ、ここまでメールそっ くりだと、普通のメールクライアントで、サーバ(SMTP、POP3)とのやりとりの時間間隔を極端に短くしてしまえば、メールとIMの違いは見せ方の違 いだけなのでは?、と言う気分になってきます。この感覚は、XMPPはP2Pの技術と言えるか?(注2)にも関係してきます。


要素技術


上の動作イメージを掴んだ上で、構成要素を整理すると次のようになります。

- ID(名前、アドレッシング(注3))
- 通信プロトコルのフォーマットとスキーマ(何をどうやりとりするか)
-- メッセージの転送(ルーティング)
- セキュリティ
の順で見ていきます。

ID


リソース(ユーザ、サーバを含む)を一意に識別するJID(Jabber ID)が次のように定義されています。

引用:

- jid = [ node "@" ] domain [ "/" resource ]


ユーザ間のメッセージングだけに目を向ければ、node部分にユーザIDが来て、resource部分が省略されれば、メールアドレスそのものになります。


通信プロトコルのフォーマットとスキーマ


XMLフォーマットであることには興味がありませんが、ちょっと面白いと思ったのが、<stream>タグがずっと開きっ放しな部分です。
つまり、セッション中、次のような感じになります(C:クライアント、S:サーバ)。

引用:

S: <stream>
<message>...</message>
C: <stream>
<message>...</message>
S: <message>...</message>
C: <message>...</message>
S: <message>...</message>
C: <message>...</message>
S: </stream>
C: </stream>


上の<message>に、リクエスト/リプライ的な参照関係はありません。全部ばらばらで、独立した<message>要素が開いたままの<stream>要素の中で、双方向にやりとりされます。


XMPPの通信XMLメッセージで、次の用語が定義されています。
- XML stream: 上の例で、<stream>に対応します。XML stanzaを含むXML親要素と言う考え方もできます。現実的には、「2ホスト間のTCPセッション1つにXML stream 1つ」と考えるのが理解しやすいはずです。
- XML stanza: XML stream内の子要素として現われます。上の例で言えば、<message>要素です。以下の標準stanzaを見る方が理解が早いと思います。


標準の3つのXML stanza


- <message/>: push mechanismと説明されています。1対1の1方向の通知です(to属性宛)。
- <presence/>: broadcast or publish-subscribeと説明されています。受け手が複数と言う意味でのマルチキャスト的な1方向の通知です。
- <iq/>: [info/query] request-responseと説明されています(id属性でrequestとresponseの対応をとります。type属性に get/set/result/errorがあります。requestのメソッドタイプのようなものです)。HTTPに馴染みがあれば、最も分かりやすい stanzaかもしれません。メッセージの(対応関係の)状態があるという意味で、上の2つより高度な通信メカニズムです。高度と言っても、状態がある通 信機構の中では、最もシンプルな機構です。

stanzaは追加拡張可能になっていますが、この3つがあれば充分でしょう(注4)。


メッセージの転送(ルーティング)


まず用語の話をすると、routing(ルーティング)はサーバ間(=ドメイン間)メッセージ転送で、delivery(配送)は同一サーバ内(の接続ユーザ)へのメッセージ転送を暗黙に意味しています。この辺はメールと同じです。

面倒なので、ルールベースを箇条書します。
XML stanzaのto属性のJIDを見て、サーバがrouting or deliveryを行います。

- to属性のない<presence/>: 対象リソースの全てのsubscriberにbroadcast(subscribeの仕組みはXMPP-IMのrfc参照)
- to属性のない<iq/>: 処理してresultを返す
- to属性が別(DNS)ドメイン: routing (上述したようにDNSのSRV参照で宛先を決定)
- to属性が"domain/resource": サーバで処理。<iq/>なら結果を返す。
- to属性が"node@domain/resource": リソースがbindされた接続streamに配送。bindされたstreamが無ければ、<service-unavailable/>を返す
- to属性が"node@domain"(=similar to メールアドレス): bindされたstreamへ配送(アプリ依存あり? XMPP-IMのrfc参照)


セキュリティ


ちょっと手抜きの説明です。

- SASLでユーザ認証します(SASLは、チャレンジ、レスポンス型のユーザ認証です。基本的にはパスワード認証です)
- TLS(SSLの標準化版)で通信セッションの暗号化をします。
- Server dialbackでドメイン名の偽造を防ぎます。Server dialbackはDNSの逆索きチェックをする仕組みです。rfc3920では「server dialbackはセキュリティメカニズムでは無い」と書かれています。「weak verification of server identities only(サーバの真実性の弱い確認ができるにすぎない)」と謙遜しての発言のようです。世の中では、DNSの逆索きで相手をチェックするだけで、強力な セキュリティ機構だと喧伝することもあるので、DNS逆索き程度ではセキュリティ機構とは呼べないと主張する心は、技術者の意地か、あるいは皮肉なので しょう。



注1.
ここでの「セッション」はTCPのセッションを想像してください。
XMPPは下位トランスポートにTCPを必ずしも想定しない、と言っていますが(「4.2. Binding to TCP」参照)、クライアントとサーバがずっとつながっているイメージを持つ方が、XMPPの動作をイメージしやすいと思います。


注2.
「XMPPはP2Pプロトコルですか?」と聞かれれば、普通の感覚ではNo.と答えるべきでしょう。
rfc3920の「2.1. Overview」で「XMPPは特定のネットワークアーキテクチャとは結びついていない(ただし、現状では普通クライアント-サーバで実装されている)」と書かれていてもです。

世の中では、IMがP2Pの代表的なアプリだと紹介されることが多々あります。XMPPの説明を見てわかるように、ネットワーク的な動作だけを見ると、メールとの違いが感じられません。XMPPをP2Pと呼ぶなら、メールもP2Pと呼ばないと一貫性が無い気がします。

P2P の古典的な定義に<a href="http://www.openp2p.com/pub/a/p2p/2000/11/24/shirky1-whatisp2p.html">Clay Shirkyの定義</a>があります。ぼくは、この定義を以前から毛嫌いしています。理由は、P2PをDNSのアンチテーゼとしてしか定義 していないように思えるからです。しかし、ひとつだけ今でも興味深いと思っている部分は、「P2P is a class of applications」と言う部分です。ネットワークのアーキテクチャでP2Pを定義するのではなく、アプリケーションの1ジャンルとしてP2Pを定 義している部分です。アプリケーションの1ジャンルとしてP2Pを定義するなら、XMPPという通信プロトコルをP2Pか否か、と判定するのは意味が無い ことになります。アプリケーションの1ジャンルとしての定義を受け入れると、メールとIMはアプリ側の見せ方の違いに過ぎないが、見せ方の違いこそがIM をP2Pアプリにしている、と強弁することもできそうです。

ここまで来ると、小説のジャンルみたいで、ミステリ小説の定義やSF小説の定 義は何か、にも似た不毛さがあります。謎が主題である物語や、科学的興味が主題である物語、と定義したところで、反論や反例はいくらでもできて、結局、残 るのは、ミステリらしさやSFらしさと言った、「らしさ」としか言いようの無い「様式(コード)」です。


注3.
「インターコネクションズ第2版」という本で、次の3つの用語は混乱しやすいと書かれています。
- 名前: ある物が何であるか
- アドレス: どこにあるか
- 経路: どうやってたどり着くか

本では、これらの定義を分かりづらいと喧嘩を売っています(喧嘩を売るシーンが多い本です)。
どんな定義をしているかは興味があれば、本屋で立ち読みでもしてください(第2章です)。いずれ勉強会のネタ本にしようと思っている本なので、いつか話すかもしれません。
ネットワークのアーキテクチャを見る時、上の3つの観点に着目するのは、悪くない手段だと思っています。


注4.
ア リエルフレームワークも、ピア間でセッションを確立した後の通信機構で、同じようにシンプルな基本メソッドを用意しつつ、拡張可能にしています。現状、基 本メソッドさえあれば、事足りています。Web/HTTPを見ても分かるように、リクエスト/リプライ型の通信機構があれば、意外に広い範囲をカバーでき ます。

Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.