分享
 
 
 

GNUGK源码分析

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

GNUGK是建立在Openh323和PWlib基础上的开源项目,支持OpenSSL,MySQL,OpenLDAP和FreeRADIUS,并且可以穿越防火墙和NAT.实际上GateKeeper已经成为H.323网络的核心部分,整个网络都由它掌控,而GNUGK几乎又是GateKeeper的业界标准,所以研究Openh323的同时了解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() + "' started\n" + Toolkit::GKVersion());

cout << welcome << '\n';

PTRACE(1, welcome);

if (args.HasOption('i')) //使用自定义的IP地址

Toolkit::Instance()->SetGKHome(args.GetOptionString('i').Lines());

std::vector GKHome; //遍历本机所有IP地址

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 << "\n\n";

// Copyright notice

cout <<

"This program is free software; you can redistribute it and/or\n"

"modify it under the terms of the GNU General Public License\n"

"as published by the Free Software Foundation; either version 2\n"

"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, "GK\tTimeToLive 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 << "done\n";

#ifdef WIN32

// remove control handler/close console

SetConsoleCtrlHandler((PHANDLER_ROUTINE)WinCtrlHandlerProc, FALSE);

FreeConsole();

#endif // WIN32

}

void RasServer::Run()

{

RasMsg::Initialize(); //Ras消息类的初始化

//RasPDU是一个模板类

RasPDU::Creator GRQCreator; //网守搜寻请求

RasPDU::Creator GCFCreator; //网守搜寻证实

RasPDU::Creator GRJCreator; //网守搜寻拒绝

RegistrationRequestPDU::Creator RRQCreator; //端点登记请求

RasPDU::Creator RCFCreator; //端点登记证实

RasPDU::Creator RRJCreator; //端点登记拒绝

RasPDU::Creator URQCreator; //登记注销请求

RasPDU::Creator UCFCreator; //登记注销证实

RasPDU::Creator URJCreator; //登记注销拒绝

AdmissionRequestPDU::Creator ARQCreator; //呼叫接受请求

RasPDU::Creator ACFCreator; //呼叫接受证实

RasPDU::Creator ARJCreator; //呼叫接受拒绝

RasPDU::Creator BRQCreator; //带宽管理请求

RasPDU::Creator BCFCreator; //带宽管理证实

RasPDU::Creator BRJCreator; //带宽管理拒绝

RasPDU::Creator DRQCreator; //呼叫退出请求

RasPDU::Creator DCFCreator; //呼叫退出证实

RasPDU::Creator DRJCreator; //呼叫退出拒绝

RasPDU::Creator LRQCreator; //端点定位请求

RasPDU::Creator LCFCreator; //端点定位证实

RasPDU::Creator LRJCreator; //端点定位拒绝

RasPDU::Creator IRQCreator; //状态查询请求

RasPDU::Creator IRRCreator; //状态查询证实

RasPDU::Creator UMRCreator; //未知消息

RasPDU::Creator RIPCreator; //延长对方等待时间

RasPDU::Creator RAICreator; //网关资源指示

RasPDU::Creator SCICreator; //服务控制标识

RasPDU::Creator SCRCreator; //服务控制反应

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(slist[i]));

#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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有