Libjingle的代码分析

Libjingle的代码分析 收藏

Libjingle的代码分析

Libjingle的工作流程主要分为以下几个步骤:
  1. Libjingle的代码分析
  2. 登录Jabber服务器
  3. 发送自身的状态和获取好友的状态信息
  4. 设置会话管理
  5. 发送文件请求、或连接某个用户
  6. 确定接收和通信,(指定文件路径)
  7. libjingle使用方法:
  8. libjingle使用的是标准xmpp协议,但是对里面一些内容进行了扩展:

登录Jabber服务器

talk_base::InitializeSSL();初始化SSL链路,如果需要加密的话

XmppPump类;封装了XmppClient并用XmppClient 来登陆到服务器上,它主要的函数和消息通知:
pump.client()->SignalStateChange.connect(&object, &msg_function);   //接收通知消息
        STATE_START
        STATE_OPENING
        STATE_OPEN     //登陆成功后;发送自身的状态
        STATE_CLOSED
pump.DoLogin(xcs, new XmppSocket(true), NULL);   //登陆服务器
pump.DoDisconnect();  //断开服务器

批注 :如何将来配合UC客户端使用的话,这个环节就刨去不考虑了。

发送自身的状态和获取好友的状态信息

在登陆Jabber Server后,客户端需要将自身的状态发送给服务器,同时服务器会将好友的信息反馈回来;
状态信息包括:Jid,available,invisible,show,priority,know_capabilities,phone_capability,is_google_client,version

//1. 接收服务器发送过来的状态

buzz :: PresencePushTask *presence_push_ = new buzz :: PresencePushTask (xmpp_client_);

presence_push_->SignalStatusUpdate.connect(this, &FileShareClient::OnStatusUpdate);

presence_push_->Start();

 

//2. 设置自身的状态

buzz :: Status my_status;

my_status.set_.......

my_status.set_show(buzz::Status::SHOW_ONLINE);

 

//3 发送自身的状态

buzz :: PresenceOutTask * presence_out_ = new buzz :: PresenceOutTask (xmpp_client_);

presence_out_->Send(my_status);

presence_out_->Start();

 

//4------------- 收到好友状态,从服务器传递过来的、(在当前程序中可不用)

void OnStatusUpdate( const buzz :: Status & status) 

{

   if (status.available() && status.fileshare_capability())  // 可以进行文件传输

   if (status.available() && status.phone_capability())      // 可以进行 Call 通信

}



批注 :如果将来配合UC客户端的话,这个环节就刨去不考虑了。

设置会话管理

在登录服务器且获得了好友的状态信息后,你需要设置会话管理管道,用来监视进来的连接请求和响应出去的连接请求。设置会话的步骤:

 

1. 实例化您的 NetWorkManager , PortAllocator 子类, SessionManager 对象;(注意: Libjingle 的文件传输程序是采用传输完一个 Session 就结束程序,所以它采用的是单线程也是就是使用的主线程来运行 Session ;而 Call 通信过程就采用了多线程的模式,防止主线程被阻塞。这里的主线程也就是处理信息的线程,也叫做信号线程)

talk_base::NetworkManager network_manager_ ;

talk_base::scoped_ptr port_allocator_ ;

talk_base::scoped_ptr session_manager_ ;

port_allocator_ .reset( new cricket :: HttpPortAllocator (& network_manager_ , "pcp"));

session_manager_ .reset( new cricket :: SessionManager ( port_allocator_ .get(), NULL)); // 使用单线程!对于我来说用什么?

or

worker_thread_ = new talk_base :: Thread ();// 这个是语言通信的会话管理

session_manager_ = new cricket :: SessionManager (port_allocator_, worker_thread_);

session_manager_->SignalRequestSignaling.connect(this, &CallClient::OnRequestSignaling);

session_manager_->OnSignalingReady();

worker_thread_->Start();

 

2. 创建一个用来发送和接受 Session 请求; xmpp_client_ (能否手工初始化,而不是从服务中获取?)

cricket :: SessionManagerTask *session_manager_task = new cricket :: SessionManagerTask (xmpp_client_, session_manager_);

session_manager_task->EnableOutgoingMessages();

session_manager_task->Start();

 

3. 查询 stun relay server 。这是异步调用在 OnJingleInfo 中接受服务器反馈的信息

buzz :: JingleInfoTask *jingle_info_task = new buzz :: JingleInfoTask (xmpp_client_);

jingle_info_task->RefreshJingleInfoNow();

jingle_info_task->SignalJingleInfo.connect(this, &FileShareClient::OnJingleInfo);

jingle_info_task->Start();

 

4. 文件传输 Session 开始;有点类似开始侦听

file_share_session_client_.reset( new cricket :: FileShareSessionClient (session_manager_.get(), xmpp_client_->jid(), "pcp"));

file_share_session_client_->SignalFileShareSessionCreate.connect(this, & FileShareClient ::OnFileShareSessionCreate);

session_manager_->AddClient(NS_GOOGLE_SHARE, file_share_session_client_.get());

or

phone_client_ = new cricket :: PhoneSessionClient (xmpp_client_->jid(),session_manager_);

phone_client_->SignalCallCreate.connect(this, & CallClient ::OnCallCreate);

worker_thread_->Start();

 

// 接收服务器发来的 stun server relay server 的信息

void OnJingleInfo( const std :: string & relay_token, const std :: vector < std :: string > &relay_addresses, const std :: vector < talk_base :: SocketAddress > &stun_addresses) {

    port_allocator_->SetStunHosts(stun_addresses);

    port_allocator_->SetRelayHosts(relay_addresses);

    port_allocator_->SetRelayToken(relay_token);

}

 

批注:

1. 从第三步我们可以看出: stun server relay server 的配置信息在 Jabber 服务器上,而且不是一个;

     公司的 Jabber 是否有这些信息?是否支持这种命令?

     如果这三个信息不从服务器获得, relay_token 又是什么东西?

2.NS_GOOGLE_SHARE="http://www.google.com/session/share";

    session_manager_->AddClient(str, xmppclient) 是注册一个客户端,其实就是将他们存入 map 中;而 NS_GOOGLE_SHARE key , 这有什么用呢?

     文件传输只需要创建一个 file_share_session_client_ ,每次传输文件是创建一个 FileShareSession 对象,有这个对象发送文件请求。

     那么 session_manager_ 为什么要将用 map 来存储 file_share_session_client_ 呢?

 

 


发送文件请求、或连接某个用户

cricket::FileShareSession* share = file_share_session_client_->CreateFileShareSession();
share->Share(remote_jid, manifest_);

批注:
1.例子中remote_jid是从服务器反馈的,如果我们用手工创建(username/region/passwd),这些信息是否够用?
2.从这句话中我们可以看出,协商链路和打洞都被封装起来了;
    在这个打洞的流程中,Jabber服务器究竟启动什么作用?他都处理了那些命令?
    在打洞的时候,究竟是Jabber还是relay起到了协助作用?


收到文件请求或连接回报出来
void OnSessionState (cricket::FileShareState state){
    case cricket::FS_OFFER:        //收到对方发来的文件信息;上报文件信息
    case cricket::FS_TRANSFER:     //开始传输
    case cricket::FS_COMPLETE:     //传输完毕
    case cricket::FS_LOCAL_CANCEL: //本地取消
    case cricket::FS_REMOTE_CANCEL://远程取消
    case cricket::FS_FAILURE:      //传输失败
}

void OnUpdateProgress (cricket::FileShareSession *sess) {
    注:session_->GetProgress()是整体的进度;而不是单个文件的进度!
}

FileShareSession,就是用来收发一个文件(应该说是文件列表)
session_->Share(remote_jid, manifest_); //发送文件信息
session_->manifest()           //得到文件清单
session_->GetTotalSize         //得到总大小
session_->GetCurrentItemName() //得到当前文件名
session_->GetProgress()        //得到当前文件的进度
session_->jid()                //得到发送者的JID
session_->is_sender()          //是否是发送者
session_->Accept();            //接收文件
session_->Cancel();            //取消文件
session_->SetLocalFolder();    //设置本地路径,这样相当于另存为么?
session_->disconnect_all();    //断开所有连接


void OnFileShareSessionCreate(cricket::FileShareSession *sess) { //在创建一个FileShareSession对象后,管理的消息处理函数
    session_ = sess;
    sess->SignalState.connect(this, &FileShareClient::OnSessionState );
    sess->SignalNextFile.connect(this, &FileShareClient::OnUpdateProgress );
    sess->SignalUpdateProgress.connect(this, &FileShareClient::OnUpdateProgress );
    sess->SignalResampleImage.connect(this, &FileShareClient::OnResampleImage );//
    sess->SetLocalFolder(root_dir_);
}

确定接收和通信,(指定文件路径)

void  OnSessionState (cricket::FileShareState state)函数中将文件信息显示出来;
用户单独调用接受accept(), Cancel(), Deline()



文件发送完毕后;结束连接通道

delete file_share_session_;
talk_base::Thread *thread = talk_base::ThreadManager::CurrentThread();
thread->Stop();

libjingle使用方法:

1.线程处理:线程对象: thread 类(从MessageQueue中继承)
  重写run函数做处理函数;调用start运行调用stop停止!
  线程互斥锁CriticalSection;使用方法 CritScope cs(&CriticalSection) ;
2.范围指针 scoped_ptr
  使用reset切换指针的地址;使用get获得原始的指针;很适合在类中使用
3.消息处理类 MessageHandler
  该类必须重写OnMessage()函数;
  通过thread的post方法可以给消息处理函数发送消息!


将来的Demo界面:
对方JID、文件名称、大小、进度、速度、状态、注释
.......、Session信息、总体大小、进度(传输过来的/总大小)、速度(当前速度)、状态(总状态)、注释信息
       、真正的文件名、...........................
       、真正的文件名、...........................
       、真正的文件名、...........................
       、真正的文件名、...........................
       、真正的文件名、...........................


封装成一个类;
1.设置会话管理:实例化三个对象、查询stun/relay、文件开始侦听、启动主线程
2.发生文件请求
  发送端创建一个FileShareSession
3.收到文件请求后,也要对应一个对象
  服务端创建一个FileShareSession



libjingle使用的是标准xmpp协议,但是对里面一些内容进行了扩展:

下表列出了谷歌Talk中使用的非标准XMPP协议的扩展;除此之外都是标准的xmpp协议:

Extension Description
User Settings Enables a client to make and query client settings handled by the server.
Off the Record Chats Enables a client to turn off server-side logging for individual conversations, and alert clients to turn off client-side logging as well.
Jingle Server Discovery Returns a list of servers that a client can use to connect a Jingle session.
返回stun server、relay server信息清单(公司的Jabber需要扩展这条命令)
Gmail Notifications Enables a client to request notifications when their Gmail account receives a new email, or to query for unread emails.
Shared Status Messages Enables multiple client instances to share a central list of status messages.
Extended Contact Attributes Sets or retrieves additional information about roster members.
JID Domain Discovery Enables a client to sign into the Google server using either the gmail.com or googlemail.com domain.
Voicemail Enables a client to send voicemail messages to other chat clients.

但是对于文件传输和语音通信来说:Jingle Server Discovery是需要的!

你可能感兴趣的:(Libjingle的代码分析)