天天看點

GLOOX 1.0 API ----架構

改定履曆:

2011-08-19-------------------建立文本文檔

2011-08-25--------------------增加XMPP官網連結

2011-09-02-------------------新增對GLOOX1.0API文檔Main Page頁翻譯

        個人研究XMPP已經有大約一個星期的時間了,基本過程是先看了三天的RFC,包括RFC3290,RFC3291兩個主要協定,然後就是研究GLOOX1.0了。XMPP除了這兩個核心協定之外還有很多的XEP擴充協定。另外比較成熟的XMPP協定棧是GLOOX1.0版。前文已經貼出了RFC文檔,從這篇文章開始詳細介紹GLOOX,由于本人也是邊學邊記錄,有高手飄過時請不吝賜教。

        先貼出一下XMPP一些相關資源:

XMPP官網

gloox官方網站---這裡可以了解gloox的官方資訊,開發文檔等

gloox1.0API文檔---個人将官方的API文檔整站下載下傳下來打包,友善本地檢視,強烈建議大家詳細看一下文檔的Main Page頁,以對整個gloox的設計有一個大的層面上的了解

RFC3920------XMPP核心協定

RFC3921------即時消息和出席資訊

xmpp協定PPT----XMPP PPT文檔

        先這些吧,以後随時補充

---------------------------------------------------------------------------------------------------------------------

GLOOX協定棧是基于所謂“觀察者”設計模式設計的,如果你熟悉“觀察者”設計模式或者不熟悉但是在去深入了解GLOOX之前能去看一下“觀察者”模式會對學習GLOOX很有好處。其主要思想就是将觀察者“注冊”到“被觀察者”那裡,“被觀察者”有什麼風吹草動,觀察者都會知道,而進一步的處理就是在你的程式裡實作“觀察者”的若幹虛函數。

環境搭建的話,本人用的是vs2008,下載下傳下來gloox1.0,建立一個工程把gloox下src目錄裡所有的.h和.cpp全部加載,再添加一個工程用于對gloox進行測試,将兩個工程的生成目錄及依賴設定好即可。

----------------------------------------------------------------------------------------------------------------------

補充:部落客近日學習GLOOX,重讀了API Main Page頁,覺得Main Page頁對于新手從較高層面上把握GLOOX有很大幫助,且這裡往往是新手容易忽略的最直接的一手資料資訊來源,于是決定花時間翻譯出來。限于本人英文水準,大家可參照原英文文檔檢視:

Introduction:

GLOOX的設計遵循了所謂的觀察者設計模式,含義是一切都是基于事件驅動的。使用GLOOX不如Jabber/XMPP網絡有兩種方式------做為用戶端或元件。C++ XMPP伺服器庫請參考<http://camaya.net/glooxd>.

Note:

XMPP詳細規格說明書(RFC 3290)的11.5小節要求,線路上交換的資料隻能是UTF-8編碼方式,由于GLOOX不知道輸入的資料是哪種編碼,是以GLOOX要求輸入資料必須是有效的UTF-8編碼。

Event Handlers:

GLOOX裡最重要的工具就是事件處理器(event hanbdlers),目前,除了有為RFC中定義的基本協定服務的4種事件處理器,還有為XEP實作裡的事件和附加功能服務的其它許多事件處理器。另外,一個日志處理器、一個一般标簽處理器和一個連接配接事件處理器都是有效的。

通常這些處理器都是虛接口,你可以繼承它們派生出一個類,并且實作一些這些虛函數。然後你可以注冊這樣的一個子類對象到各自的協定實作裡。下面是一個簡單的例子:

[cpp]  view plain copy

  1. class MyClass : public PresenceHandler 
  2.    public: 
  3.      // reimplemented from PresenceHandler 
  4.      virtual void handlePresence(const Presence& presence ); 
  5.    [...] 
  6. }; 
  7. void MyClass::handlePresence( const Presence& presence ) 
  8.    // extract further information from the Presence object 

在某個地方你可以像下面這樣做: [cpp]  view plain copy

  1. OtherClass::doSomething() 
  2.   Client* client = new Client( ... ); 
  3.   [...] 
  4.   MyClass* handler = new MyClass( ... ); 
  5.   client->registerPresenceHandler( handler ); 

然後你可以使用Stanza類提供的衆多getters(即get字首的成員函數)進一步提取節中的資料

現在,每次接收到一個presence節(非subscription節)時,handlePresence都會被調用,參數是目前節。然後你可以使用Stanza類提供的衆多getters(一般來講是get字首的方法,此處了解為擷取stanza各資料的方法)進一步提取節中的資料以進一步處理。

幾乎是以的事件處理器的工作方式都是與這個例子相似的,接下來以使用連接配接事件處理器(class ConnectionListener)為例,再舉一例:

[cpp]  view plain copy

  1. class MyClass : public ConnectionListener 
  2.    public: 
  3.      virtual void onConnect(); 
  4.      virtual bool onTLSConnect( ... ); 
  5. }; 
  6. void MyClass::onConnect() 
  7.    // do something when the connection is established 
  8. bool MyClass::onTLSConnect( const CertInfo& info ) 
  9.    // decide whether you trust the certificate, examine the CertInfo structure 
  10.    return true; // if you trust it, otherwise return false 

Note:

ConnectionListener是一個比較奇特的接口。你必須重新實作ConnectionListener::onTLSConnect()這個接口,如果你想成功連接配接一個啟用了TLS/SSL伺服器的話。盡管GLOOX試圖檢查伺服器的證書,但不會自動的信任該伺服器。必須由用戶端程式員或使用者來決定是否信任此伺服器。是否信任就由onTLSConnect()的傳回值來表示,FLASE意味着你不信任該伺服器,結果就是與伺服器的連接配接中斷。

先去吃飯了,回來待續……

Components

Jabber/XMPP網絡中的一個元件是加載到伺服器上的,它運作在實際的服務軟體之外,但它有相似的權限,元件使用XEP-0114中描述的協定去連接配接和驗證一個伺服器.類Component 支援該協定并且可以用于建立一個新的Jabber component.簡單的例子如下:

[cpp]  view plain copy

  1. Component* comp = new Component( ... ); 
  2. comp->connect(); 

Clients

一個用戶端可以是終端使用者的聊天用戶端,一個機器人或者是一個沒有和特殊伺服器綁定在一起的簡單實體。類Client實作了連接配接一個XMPP 伺服器所需要的功能。一個例子如下:

[cpp]  view plain copy

  1. class MyClass : public ConnectionListener, PresenceHandler 
  2. public: 
  3.      void doSomething(); 
  4.      virtual void handlePresence( ... ); 
  5.      virtual void onConnect(); 
  6.      virtual bool onTLSConnect( const CertInfo& info ); 
  7. }; 
  8. void MyClass::doSomething() 
  9.    JID jid( "[email protected]/resource" ); 
  10.    Client* client = new Client( jid, "password" ); 
  11.    client->registerConnectionListener( this ); 
  12.    client->registerPresenceHandler( this ); 
  13.    client->connect(); 
  14. void MyClass::onConnect() 
  15.    // connection established, auth done (see API docs for exceptions) 
  16. bool MyClass::onTLSConnect( const CertInfo& info ) 
  17.    // examine certificate info 
  18. void MyClass::handlePresence( Presence* presence ) 
  19.    // presence info 

Note

GLOOX官方并不支援5223上的連接配接方式。例如:在XML串先于SSL加密之前被發送,因為這是曆史遺留的方法況且不符合标準的XMPP協定。然而,GLOOX提供了一個ConnectionTlS類,做為附加功能,允許你去綁定一個這樣的連接配接。

預設情況下,Client::connect()是阻塞的,直到連接配接終止(Client::disconnect()被調用,或者伺服器終止連接配接)。

阻塞和非阻塞連接配接

對于某些種類的機器人來說阻塞式的連接配接(預設的行為)是非常理想的方式。幾乎所有的機器人都是對來自于伺服器的事件做出響應。然而,對某些終端使用者或帶有GUI應用的用戶端來說就不那麼完美了。

這些情況下就需要用到非阻塞式的連接配接了。如果調用ClinetBase::connect(false),函數将會在綁定連接配接後立即傳回。接下來程式員就有責任初始化一些從SOCKET接收到的資料。

一種最簡單的方法是以一個逾時值(微秒)做為參數周期性的調用ClientBase::recv(),預設值-1意味着調用是阻塞的,直到有資料到達,對資料的解析也是自動的。

作為周期性地輪詢一種替換辦法,你可以擷取連接配接的原始檔案描述符。你可以在該檔案描述符上使用select()并且當select上的資料有效時使用ClientBase::recv()。你可能直接從檔案描述符得不到任何資料,也沒有辦法為解析器提供資料。

為了得到檔案描述符,你必須手動設定一個連接配接類(ConnectionTCPClient),就像這樣:

[cpp]  view plain copy

  1. Client* client = new Client( ... ); 
  2. ConnectionTCPClient* conn = new ConnectionTCPClient( client, client->logInstance(), server, port ); 
  3. client->setConnectionImpl( conn ); 
  4. client->connect( false ); 
  5. int sock = conn->socket(); 
  6. [...] 

有可能像下面這樣擷取檔案描述符: [cpp]  view plain copy

  1. Client* client = new Client( ... ); 
  2. client->connect( false ); 
  3. int sock = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket(); 
  4. [...] 

顯然,隻要你沒有使用setConnectionImpl()設定一個不同的連接配接類型就會工作。

Note

在0.9以後的版本裡這已經發生了改變,ClientBase::fileDescriptor()不在可用了。

Roster Management

RFC3921定義了如何管理一個人的聯系清單(花名冊)。在GLOOX中,類RosterManager實作了這個功能。一組簡單函數有效地實作了訂閱和取消訂閱實體的出席。也可以在沒有實際訂閱此聯系人出席的情況,把他加入到自己的花名冊中。另外,接口RosterListener對應于各種花名冊相關的事件提供了一組回調函數。

如果你依上所述建立了一個用戶端對象,那麼你可以擷取一個RosterManager對象。Client::rosterManager()傳回一個該類對象的指針。

Privacy Lists

同樣地,“隐私清單”也定義在RFC3921中,一個隐秘清單可以明确地禁止或允許 從聯系人接收或發給聯系人資料節,區分不同的聯系人。你可以自己定義基于JID,節類型等的規則。類PrivacyManager 和類PrivacyListHandler虛接口在隐私清單的處理上比較靈活。

[cpp]  view plain copy

  1. PrivacyManager* p = new PrivacyManager( ... ); 
  2. [...] 
  3. PrivacyListHandler::PrivacyList list; 
  4. PrivacyItem item( PrivacyItem::TypeJid, PrivacyItem::ActionDeny, 
  5.                   PrivacyItem::PacketMessage, "[email protected]" ); 
  6. list.push_back( item ); 
  7. PrivacyItem item2( PrivacyItem::TypeJid, PrivacyItem::ActionAllow, 
  8.                    PrivacyItem::PacketIq, "[email protected]" ); 
  9. list.push_back( item2 ); 
  10. p->store( "myList", list ); 

Authentication

GLOOX支援XEP-0078定義的舊樣式的基于IQ節的鑒權機制,也支援若幹SASL機制。可以參考Client類文檔說明以擷取更多資訊。

Sending and Receiving of Chat Messages

對于消息傳輸推薦使用MessageSession接口。它處理消息的發送和接收,也處理包括消息事件和聊天狀态(例如“打字中……”)等。檢視MessageSession類文檔以擷取更多細節。

Protocol Extensions (XEPs)

XMPP标準基金會釋出了許多核心協定的擴充,稱為XMPP Extension Protocols(XEPs)(XMPP擴充協定)。一些擴充協定已經在GLOOX中得到實作:

XEP-0004 Data Forms 

XEP-0012 Last Activity 

XEP-0013 Flexible Offline Message Retrieval 

XEP-0022 Message Events (see MessageSession for examples) 

XEP-0027 Current Jabber OpenPGP Usage (see GPGSigned and GPGEncrypted ) 

XEP-0030 Service Discovery 

XEP-0045 Multi-User Chat 

XEP-0047 Used with File Transfer 

XEP-0048 Bookmark Storage 

XEP-0049 Private XML Storage 

XEP-0050 Ad-hoc Commands 

XEP-0054 vcard-temp 

XEP-0060 Publish-Subscribe 

XEP-0065 SOCKS5 Bytestreams , used with File Transfer and HTTP and SOCKS5 Proxy support

XEP-0066 Out of Band Data , also used with File Transfer 

XEP-0077 In-Band Registration 

XEP-0078 Non-SASL Authentication (automatically used if the server does not support SASL)

XEP-0079 Advanced Message Processing 

XEP-0083 Nested Roster Groups (automatically used if supported by the server. see RosterManager )

XEP-0085 Chat State Notifications (see MessageSession for examples) 

XEP-0091 Delayed Delivery (old spec) 

XEP-0092 Software Version (integrated into Service Discovery ) 

XEP-0095 Stream Initiation , used with File Transfer 

XEP-0096 File Transfer 

XEP-0106 JID Escaping 

XEP-0114 Jabber Component Protocol 

XEP-0115 Entity Capabilities (used automatically internally) 

XEP-0124 Bidirectional-streams Over Synchronous HTTP (BOSH) 

XEP-0131 Stanza Headers and Internet Metadata 

XEP-0138 Stream Compression (used automatically if gloox is compiled with zlib and if the server supports it)

XEP-0145 Annotations 

XEP-0153 vCard-based Avatars 

XEP-0172 User Nickname 

XEP-0184 Message Receipts 

XEP-0199 XMPP Ping 

XEP-0203 Delayed Delivery (new spec) 

XEP-0206 see BOSH 

XEP-0224 Attention 

XEP-0256 Last Activity in Presence

更進一步的擴充可以用類StanzaExtensions很容易的實作。

File Transfer

對于檔案傳輸,GLOOX實作了XEP-0095(流初始化協定)和XEP-0096(檔案傳輸)協定的信号機制;為傳輸實作了XEP-0065(SOCKS5 Bytestreams 流位元組)和XEP-0047(帶内位元組流)。參考 SIProfileFT類

HTTP and SOCKS5 Proxy support

gloox 有能力穿過http及SOCKS5代理,即便是連鎖代理。參考ConnectionHTTPProxy類 和 ConnectionSocks5Proxy類.

分享到: 

繼續閱讀