GNUGK源码分析
GNUGK是由Jan Willamowius说领导开发,不同于Openh323的开发小组,它采用标准的c++编写,可实现跨平台编译,不过和Openh323不同的是GNUGK大量采用了C++的STL技术,比如模板和向量等等...,所以建议在看GNUGK前好好学习PWlib,Openh323和STL,这样才能为以后的学习打下坚实的基础。
废话不多讲,我们上路吧。
此处我用的是从CVS上Update的最新的GNUGK和Pandora的PWlib和Openh323.和每个基于PWlib的程序一样,首先从PProcess派生出一个GateKeeper类,程序就从GateKeeper::Main()开始。
void Gatekeeper::Main()
{
PArgList & args = GetArguments(); //获得命令行参数
args.Parse(GetArgumentsParseString()); //解析各个参数
#ifdef HAS_SETUSERNAME //设置以特殊用户身份运行
if (args.HasOption('u')) { //默认值是关闭的
const PString username = args.GetOptionString('u');
if ( !SetUserAndGroup(username) ) {
cout << "GNU Gatekeeper could not run as user "
<< username
<< endl;
return;
}
}
#endif
if(!InitLogging(args) || !InitToolkit(args)) //InitLogging对日志和跟踪(Trace)进行初始化
return; //InitToolkit
if (args.HasOption('h')) { //如果包含命令行参数'h'
PrintOpts(); //显示帮助信息
ExitGK(); //停止Log和Trace,删除Toolkit并退出
}
if (!InitConfig(args) || !InitHandlers(args))//InitConfig读取INI配置文件
ExitGK(); //InitHandlers设置Ctrl+C停止热键
EnableLogFileRotation(); //开始记录日志
PString welcome("OpenH323 Gatekeeper - The GNU Gatekeeper with ID '" + Toolkit::GKName() + "' startedn" + Toolkit::GKVersion());
cout << welcome << 'n';
PTRACE(1, welcome);
if (args.HasOption('i')) //使用自定义的IP地址
Toolkit::Instance()->SetGKHome(args.GetOptionString('i').Lines());
std::vector
PString home(Toolkit::Instance()->GetGKHome(GKHome));//home为本机的所有IP地址
if (GKHome.empty()) {
cerr << "Fatal: Cannot find any interface to run GnuGK!n";
ExitGK();
}
cout << "Listen on " << home << "nn";
// Copyright notice
cout <<
"This program is free software; you can redistribute it and/orn"
"modify it under the terms of the GNU General Public Licensen"
"as published by the Free Software Foundation; either version 2n"
"of the License, or (at your option) any later version.n"
<< endl;
// read capacity from commandline
int GKcapacity; //GK的带宽总容量
if (args.HasOption('b'))
GKcapacity = args.GetOptionString('b').AsInteger();
else
GKcapacity = GkConfig()->GetInteger("TotalBandwidth", -1);
CallTable::Instance()->SetTotalBandwidth(GKcapacity); //限制带宽
if (GKcapacity < 0)
cout << "nDisable Bandwidth Management" << endl;
else
cout << "nAvailable Bandwidth " << GKcapacity << endl;
// read timeToLive from command line
if (args.HasOption('l')) //设置时间超时
SoftPBX::TimeToLive = args.GetOptionString('l').AsInteger();
else
SoftPBX::TimeToLive = GkConfig()->GetInteger("TimeToLive", -1);
PTRACE(2, "GKtTimeToLive for Registrations: " << SoftPBX::TimeToLive);
RasServer *RasSrv = RasServer::Instance(); //RasServer是核心,定义GK各种操作
// read signaling method from commandline
if (args.HasOption('r')) //设置路由模式
RasSrv->SetRoutedMode(true, (args.GetOptionCount('r') > 1 || args.HasOption("h245routed")));
else if (args.HasOption('d'))
RasSrv->SetRoutedMode(false, false);
else
RasSrv->SetRoutedMode();
#if defined(WIN32)
// 1) prevent CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT
// dialog box from being displayed.
// 2) set process shutdown priority - we want as much time as possible
// for tasks, such as unregistering endpoints during the shut down process.
// 0x3ff is a maximimum permitted for windows app
SetProcessShutdownParameters(0x3ff, SHUTDOWN_NORETRY);//设置进程关闭参数
#endif
// let's go
RasSrv->Run(); //好戏正式开始
//HouseKeeping();
// graceful shutdown
cerr << "nShutting down gatekeeper . . . ";
ShutdownHandler();
cerr << "donen";
#ifdef WIN32
// remove control handler/close console
SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinCtrlHandlerProc, FALSE);
FreeConsole();
#endif // WIN32
}
void RasServer::Run()
{
RasMsg::Initialize(); //Ras消息类的初始化
//RasPDU是一个模板类
RasPDU
RasPDU
RasPDU
RegistrationRequestPDU::Creator RRQCreator; //端点登记请求
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
AdmissionRequestPDU::Creator ARQCreator; //呼叫接受请求
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
RasPDU
listeners = new TCPServer; //执行处理所有TCP连接请求
gkClient = new GkClient(this); //处理GK注册请求
neighbors = new NeighborList; //相邻网守列表
authList = new GkAuthenticatorList; //认证用户列表
acctList = new GkAcctLoggerList; //帐户日志列表
vqueue = new VirtualQueue; //用别名呼叫队列
LoadConfig();
callptr nullcall;
acctList->LogAcctEvent(GkAcctLogger::AcctOn,nullcall);//开始记录每个帐号的事件
if (m_socksize > 0) { //m_socksize是socket的数量
CreateJob(this, &RasServer::HouseKeeping, "HouseKeeping");//检查注册和通话是否超时
RegularJob::Run(); //循环执行SocketsReader::Exec()
}
acctList->LogAcctEvent(GkAcctLogger::AcctOff,nullcall);
}
void SocketsReader::Exec()
{
ReadLock cfglock(ConfigReloadMutex); //防止读取配置的P操作
SocketSelectList slist;
if (BuildSelectList(slist)) { //建立select列表
if (SelectSockets(slist)) {
int ss = slist.GetSize();
for (int i = 0; i < ss; ++i)
#ifdef LARGE_FDSET //最大socket数目,作者重新定义了fd_set数据结构
ReadSocket(slist[i]); //接受socket连接
#else
ReadSocket(dynamic_cast
#endif
}
CleanUp();
} else {
CleanUp();
ReadUnlock unlock(ConfigReloadMutex); //防止读取配置的V操作
PTRACE(3, GetName() << " waiting...");
Wait();
}
}
以上只是GNUGK的一个最简单和最主要的执行过程,更多详细情况情参看源代码.
转贴自http://blog.csdn.net/wffy/archive/2004/09/20/111151.aspx










文章评论
共有 位网友发表了评论 查看完整内容