在Vovida的基础上实现自己的SIP协议栈①( 六 )


主程序部分主要是根据CFG文件中的定义建立本地的呼叫和等待接收进程 。
main( int argc, char* argv[] )
{
… …
//是否把当前的UA设置为守护进程 。由CFG文件确定 。
if ( UaCommandLine::instance()->getBoolOpt( "daemon" ) )
{
// TODO set cpLog to use syslog
assert( Daemon() >= 0 );
}
… …
if (UaCommandLine::instance( ) -> getIntOpt( "retransmit" ))
{
SipTransceiver::reTransOn();
}
else
{
SipTransceiver::reTransOff();
}
if (UaCommandLine::instance()->getIntOpt("retransinitial") != 500
UaCommandLine::instance()->getIntOpt("retransmax") != 4000 )
{
SipTransceiver::setRetransTime(
UaCommandLine::instance()->getIntOpt("retransinitial"),
UaCommandLine::instance()->getIntOpt("retransmax")
);
}
//这里是打开配置文件 , 我们在这里使用的配置文件暂时定为Ua1001.cfg(以下均相同)
const string cfgStr = UaCommandLine::instance()->getStringOpt( "cfgfile" );
FILE *cfgFile = fopen( cfgStr.c_str(), "r");
if ( cfgFile == 0 )
{
cerrheartbeatThread
= new HeartbeatTxThread(sipPort,
500,
(const char*)"226.2.2.5",
6000);
heartbeatThread->run();
heartbeatThread->join();
#endif
}
#else
cpLog( LOG_ERR, "UA is NOT compiled to run as voicemail front end" );
#endif
}
//加入UA端到本地的运行队列里面
ua.join();
return 0;
} // ua main()
看完了UA的主程序 , 我们可以看到 , 目前在UA端的部分的主要工作就是创建一个User Agent的实体UserAgent然后调用Run方法让它运行 , 那么我们看一下UserAgent这个要害类的一些基本情况:

2.2 创建一个User Agent的实体:
在创建一个User Agent的实体的同时还有一个非常重要的实体HeartLesProxy , 用于处理SIP的各种消息 , 并且开启后台工作线程;它的创建过程我们稍后做具体介绍 。
UserAgent::UserAgent( Sptr uaBuilder, unsigned short sipPort, Data appName )
: HeartLessProxy( uaBuilder, sipPort, appName )
{
const char* useDevice = "NULL"; // default to NULL_HARDWARE
… …
//用什么声音设备?在这里我们暂时定为Sound Card好了 , 假如要是用Quicknet来集成
//各种压缩算法当然更好 , 不过价格也高了一些 , 下面都以Sound Card作为标准介绍 。
if( UaCommandLine::instance()->getBoolOpt( "soundcard" ) )
{
useDevice = "SOUNDCARD";
}
//LOAD GENERATION是一个检测线程 , 可以在屏幕上打印各种命令的往复消息 , 以及系统的各//种统的状态 。
if(! UaConfiguration::instance()->getLoadGenOn())
{
// Create devices only if load gen is turned OFF.
//设备实例化 , 并且向带入设备名称以及所要处理的消息队列 , 在实例化的过程中会//打开一个声卡设备 , 并且将这个声卡设备绑定两个输入的命令 , 输出命令的FIFO
//队列当中 , (inputQ , 和outputQ)具体可以参看SoundCardDevice的建构函数 , 它//阐述了如何绑定这两个队列inputQ,outputQ,并且初始化ResGwDevice(所有的声音//设备的父类) 。
UaDevice::instance( useDevice, myCallProcessingQueue );
if( ! (strcmp(useDevice, "NONE") == 0) )
{
cpLog( LOG_DEBUG, "Create RTP Thread" );
//创建一个RTP包处理线程用于对RTP Packet的处理
rtpThread = new RtpThread( UaDevice::instance() );
assert( rtpThread != 0 );
}
//这里调用了sound Card的设备消息处理线程的创立 , 用于处理与声卡设备相关的各种消//息.
deviceThread = new DeviceThread( UaDevice::instance() );
assert( deviceThread != 0 );
cpLog( LOG_DEBUG, "Create SubscribeManager" );

推荐阅读