subManager = new SubscribeManager( mySipStack );
if ( UaConfiguration::instance()->getSubscribeOn() )
{
cpLog( LOG_DEBUG, "Create Feature Thread" );
//這里建立一個(gè)向FS發(fā)送消息的線程,關(guān)于這個(gè)部分的內(nèi)容在Feature //Server的部分再做詳細(xì)介紹.
featureThread = new FeatureThread( subManager );
assert( featureThread != 0 );
uaBuilder->setSubscribeManager( subManager );
}
}
else
{
… …
}
// 是否打開(kāi)重傳機(jī)制?
if (UaCommandLine::instance( ) -> getBoolOpt( "retransmit" ) )
{
SipTransceiver::reTransOn();
}
else
{
SipTransceiver::reTransOff();
}
// 定義接收代理服務(wù)器(Proxy)發(fā)出的消息所儲(chǔ)存的容器
myCallContainer = new UaCallContainer;
assert( myCallContainer != 0 );
//綁定容器到用戶端
uaBuilder->setCallContainer( myCallContainer );
//設(shè)置SIP的消息堆棧
uaBuilder->setSipStack( mySipStack );
//開(kāi)始向注冊(cè)服務(wù)器發(fā)送注冊(cè)(Register)消息。
uaBuilder->startRegistration();
}
2.3 HeartLessProxy的創(chuàng)建:
HeartLessProxy
(
const Sptr < Builder > builder,
unsigned short defaultSipPort,
Data applName,
bool filterOn,
bool nat,
SipAppContext aContext
)
{
myCallContainer = new CallContainer;
myBuilder = builder;
myBuilder->setCallContainer(myCallContainer);
//這里創(chuàng)建了一個(gè)消息的輸出隊(duì)列,在前面的創(chuàng)建一個(gè)UserAgent的實(shí)體的過(guò)程中已經(jīng)
//闡述過(guò)會(huì)把它綁定到相關(guān)的設(shè)備上去
myCallProcessingQueue = new Fifo < Sptr < SipProxyEvent > >;
//這里創(chuàng)建一個(gè)WorkThread線程在該線程中的myBuilder->process(nextEvent)
//檢查消息隊(duì)列myFifo中的返回消息(調(diào)用Uabuilder->process進(jìn)行檢查),從而
//得到返回的消息。
//很明顯,這里新創(chuàng)建了一個(gè) myWorkerThread工作線程,我們等一下就會(huì)看到如何把它Run
//起來(lái)
myWorkerThread = new WorkerThread(myCallProcessingQueue, myBuilder);
//創(chuàng)建一個(gè)SIP消息收發(fā)器的實(shí)體,在這個(gè)實(shí)體的構(gòu)建里主要是把收發(fā)SIP消息的TCP/UDP
//的收發(fā)通道創(chuàng)建(SipUdpConnection和SipUdpConnection)。同時(shí)會(huì)構(gòu)造一個(gè)SNMP的
//SipAgent.他的主要作用是向SNMP網(wǎng)關(guān)發(fā)送SNMP消息,描述網(wǎng)絡(luò)的運(yùn)行狀態(tài)
if ( filterOn == true )
{
mySipStack = new SipTransceiverFilter(applName, defaultSipPort, nat, aContext);
}
else
{
mySipStack = new SipTransceiver(applName, defaultSipPort, nat, aContext);
}
myBuilder->setSipStack(mySipStack);
//創(chuàng)建一個(gè)SIP消息的解析線程 。
mySipThread = new SipThread(mySipStack, myCallProcessingQueue);
… …
}
2.4 讓User Agent Run起來(lái):
構(gòu)建User Agent的工作已經(jīng)完畢,現(xiàn)在應(yīng)該讓調(diào)用它的Run方法了;從下面的程序可以看到,Run方法的調(diào)用,讓整個(gè)程序進(jìn)入一種"Idle"的狀態(tài),等待命令輸入和狀態(tài)的產(chǎn)生,這個(gè)過(guò)程我們可以看到在Ua.CXX的Main程序中調(diào)用(ua.run())。
Void UserAgent::run()
{
//調(diào)用HeartLessProxy的Run方法,稍后做詳細(xì)的介紹
HeartLessProxy::run();
… …
deviceThread->run(); //調(diào)用SoundcardDevice::hardwareMain(0)
… …
rtpThread->run();//調(diào)用SoundCardDevice::processRTP()進(jìn)行RTP流的處理
… …
//在這里向FS發(fā)送隊(duì)列(myQ = new Fifo < Sptr < SubscribeMsg > >)中的各種消息,不
//過(guò)在Ua1001.cfg中,參數(shù)Subscribe_on設(shè)置為OFF所以,本章我們對(duì)FS暫不予以分析,
//在最后一章詳細(xì)分析FS的時(shí)候回著重分析它.
featureThread->run();//調(diào)用subscribeManager::subscribeMain()
… …
//后臺(tái)監(jiān)測(cè)線程開(kāi)啟.
loadGenThread->run();//調(diào)用LoadGenMonitor::lgMain()
// User TimerEvent to kick start the load generator
… …
} // UserAgent::run
(未完待續(xù))
作者供稿 CTI論壇編輯
作者聯(lián)系方法:lu_zheng@21cn.com
在Vovida的基礎(chǔ)上實(shí)現(xiàn)自己的SIP協(xié)議棧(二)