软件工程

本类阅读TOP10

·PHP4 + MYSQL + APACHE 在 WIN 系统下的安装、配置
·Linux 入门常用命令(1)
·Linux 入门常用命令(2)
·使用 DCPROMO/FORCEREMOVAL 命令强制将 Active Directory 域控制器降级
·DirectShow学习(八): CBaseRender类及相应Pin类的源代码分析
·基于ICE方式SIP信令穿透Symmetric NAT技术研究
·Windows 2003网络负载均衡的实现
·一网打尽Win十四种系统故障解决方法
·数百种 Windows 软件的免费替代品列表
·收藏---行百里半九十

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
GNUGK源码分析

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

  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



相关文章

相关软件