`
aako
  • 浏览: 5352 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Libjingle的代码分析

 
阅读更多
Libjingle的工作流程主要分为以下几个步骤:
Libjingle的代码分析
登录Jabber服务器
发送自身的状态和获取好友的状态信息
设置会话管理
发送文件请求、或连接某个用户
确定接收和通信,(指定文件路径)
libjingle使用方法:
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是需要的!
分享到:
评论
1 楼 liaojun116 2012-07-26  
请问楼主有没有这部分的源码?我想用libjingle做一个客户端,能文件传输,并带有NAT穿透和中转。我邮箱liaojunjj@163.com,楼主V5!

相关推荐

Global site tag (gtag.js) - Google Analytics