libjingle源碼解析(2)–libjingle是怎麼運作的?

來源:互聯網
上載者:User

本文主要總結至libjingle源碼和官方文章:http://code.google.com/apis/talk/libjingle/libjingle_applications.html

ligjingle的總體架構如:

1.Application模組

Ligjingle的應用程式首先調用XMPP Messaging Component的XmppClient對象進行登入,然後做一些message,iq,presence等request/respond操作。

其次,每個application可能包含一個或多個session client用來做P2P操作,比如遠程協助,視頻會議,音頻串連,檔案分享權限設定等等。

2.XMPP Messaging Component.模組

此模組主要由三個部分組成:XmppClient,LoginHandler和Xmpp Helper Task.此模組主要做相當於一個peer的防火牆的功能,串連伺服器和用戶端,負責發送所有本地的stanza請求(即XMPP協議內容),並負責接收伺服器的stanza請求,並分發到各個Helper Task裡。

  • XmppClient主要是代理登入,發送stanza,接收stanza。之所以說是代理,是因為真正發送,接收的訊息都是通過XmppEngine來實現的。
  • XmppEngine能註冊多個XmppStanzaHandler回調,然後所有從伺服器接收的Stanza都轉寄到已綁定的XmppStanzaHandler進行過濾,而實際上是回調XmppTask對象。
  • XmppStanzaHandler類定義如下:

//! Callback to deliver stanzas to an Xmpp application module.//! Register via XmppEngine.SetDefaultSessionHandler or via//! XmppEngine.AddSessionHAndler.  class XmppStanzaHandler {public:  virtual ~XmppStanzaHandler() {}  //! Process the given stanza.  //! The handler must return true if it has handled the stanza.  //! A false return value causes the stanza to be passed on to  //! the next registered handler.  virtual bool HandleStanza(const XmlElement * stanza) = 0;};

  • XmppTask是所有XmppHelperTask的基類,並繼承自XmppStanzaHandler,主要有監聽,過濾XmppEngine對象轉寄過來的Stanza訊息。XmppTask有多種類型,當取類型為HL_PEEK時,只有監聽功能,無法做到過濾;而其他類型可以做到過濾。過濾是有HandlerStanza函數來完成,當返回為true時,過濾,否則XmppEngine枚舉下一個綁定的XmppTask繼續嘗試分發、過濾。
  • 所有XmppHelperTask都要繼承XmppTask並要重載HandlerStanza函數和ProcessStart函數。
    • HandlerStanza是用來過濾,相當於windows訊息處理的GetMessage()
    • 而ProcessStart是用來處理HandlerStanza過濾的訊息。
    • 比如在原始碼example/call/presencepushtask.h裡:

class PresencePushTask : public XmppTask { public:  PresencePushTask(XmppTaskParentInterface* parent, CallClient* client)    : XmppTask(parent, XmppEngine::HL_TYPE),      client_(client) {}  virtual int ProcessStart();  sigslot::signal1<const Status&> SignalStatusUpdate;  sigslot::signal1<const Jid&> SignalMucJoined;  sigslot::signal2<const Jid&, int> SignalMucLeft;  sigslot::signal2<const Jid&, const MucStatus&> SignalMucStatusUpdate; protected:  virtual bool HandleStanza(const XmlElement * stanza);  void HandlePresence(const Jid& from, const XmlElement * stanza);  void HandleMucPresence(buzz::Muc* muc,                         const Jid& from, const XmlElement * stanza);  static void FillStatus(const Jid& from, const XmlElement * stanza,                         Status* status);  static void FillMucStatus(const Jid& from, const XmlElement * stanza,                            MucStatus* status); private:  CallClient* client_;};

    • 這裡PresencePushTask類,通過HandleStanza過濾所有presence相關的stanza並在ProcessStart裡處理所有來自伺服器的使用者狀態更新訊息。
  • LoginHandler部分是由XmppPump來負責的。主要調用XmppClient的connect和disconnect方法建立、中斷連線,監聽SignalStateChange事件來擷取串連資訊,類型為STATE_OPENED的事件表示串連成功。
3.Session Logic and management commponent模組。

所有p2p session邏輯相關的部分都放在了這個模組。可以session可能是處理檔案傳輸的串連,或者可能是視頻會話,或者音頻會話等等。

  • 我們需要繼承SessionClient來處理每個Session相關具體任務,比如檔案傳輸Session:當接收對端用戶端建立一個檔案傳輸session的時候,如果此Session是新建立的,SessionManager對象會回調所有註冊的SessionClient的OnSessionCreate的介面,並以SessionManger建立的Session對象為參數穿進去;如果是已有的Session則會調用Session的OnIncomingMessage方法。
  • Session對象則抽象了兩個peer之間的資料轉送介面。當收到OnSessionCreate回調時,SessionClient可以通過Session的方法Accept來接受建立,Reject來拒絕。
  • 那怎麼讀寫p2p資料呢?
    • 首先需要調用session的CreateChannel方法擷取TransportChannel對象指標,然後監聽TransportChannel的事件SignalReadPacket來接收資料,通過SendPacket方法來發送資料。

class TransportChannel: public sigslot::has_slots<> { public://......  // Attempts to send the given packet.  The return value is < 0 on failure.  virtual int SendPacket(const char *data, size_t len) = 0;  // Signalled each time a packet is received on this channel.  sigslot::signal3<TransportChannel*, const char*, size_t> SignalReadPacket;//......};

4.Peer to peer Component模組。

此模組才是libjingle核心,libjingle項目的初衷也是能夠把模組設計得完美,使得所有需要通過P2P傳輸資料的應用程式層調用libjingle時,不用擔心資料轉送的穩定性,可靠性,高效性。

  • 剛才上面提到,當伺服器發送stanza時XmppEngine把Stanza發送到XmppTask過濾,在這個模組,SessionManagerTask代理SessionManager過濾session相關的stanza,並轉寄到SessionManager對象,如下:

class SessionManagerTask : public buzz::XmppTask { public:  ......  virtual int ProcessStart() {    const buzz::XmlElement *stanza = NextStanza();    if (stanza == NULL)      return STATE_BLOCKED;    session_manager_->OnIncomingMessage(stanza);    return STATE_START;  } protected:  virtual bool HandleStanza(const buzz::XmlElement *stanza) {    if (!session_manager_->IsSessionMessage(stanza))      return false;    QueueStanza(stanza);    return true;  }}  // namespace cricket

  • SessionManager類在這裡起到串連上述3個模組的橋樑作用。
  • 當上層調用SessionManager建立的Session對象的CreateChannel時,實際上是調用P2PTransport的CreateChannel方法。
  • 上層通過P2PTransport建立P2pTransportChannel的類的。
  • P2pTransportChannel繼承自TransportChannel,並建立多個不同的Connection,每個Connection代表一個TCP或者UDP或者SSL串連。上層傳輸資料最終是調到P2pTransportChannel的相關方法,當發送,接收資料時,P2pTransportChannel選擇表現最好的Connection進行傳輸。
5.其他

LigJingle提供了很多介面供我們繼承,用於特定的個人化Session,同時也提供了不少執行個體(如pcp,login,call)讓調用者更容易的理解架構思路。當需要著手研究libjingle時,如果能夠充分的利用已成的執行個體,對於縮短熟悉時間,很有協助。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.