早期自己研究的Gnugk的源代码情景分析


/*************************************************************************************************************
                                                   分析Gatekeeper Main
*************************************************************************************************************/
void Gatekeeper::Main()
{
  /**Get the programme arguments. Programme arguments are a set of strings
      provided to the programme in a platform dependent manner.
   
      @return
      argument handling class instance.
    */
 //  PArgList & GetArguments();
  PArgList & args = GetArguments(); //
  
  //分析参数 返回PString
  args.Parse(GetArgumentsParseString());
  //

//如果定义的开发环境是Linux 执行如下代码
#ifdef P_LINUX
  // set the core file size
  if (args.HasOption("core")) {
    struct rlimit rlim;
    if (getrlimit(RLIMIT_CORE, &rlim) != 0)
      cout << "Could not get current core file size : error = " << errno << endl;
    else {
      cout << "Current core dump size limits - soft: " << rlim.rlim_cur
        << ", hard: " << rlim.rlim_max << endl;
      int uid = geteuid();
      seteuid(getuid()); // Switch back to starting uid for next call
      const PCaselessString s = args.GetOptionString("core");
      rlim_t v = (s == "unlimited" ? RLIM_INFINITY : (rlim_t)s.AsInteger());
      rlim.rlim_cur = v;
      if (setrlimit(RLIMIT_CORE, &rlim) != 0)
        cout << "Could not set current core file size to " << v << " : error = " << errno << endl;
      else {
        getrlimit(RLIMIT_CORE, &rlim);
        cout << "New core dump size limits - soft: " << rlim.rlim_cur
          << ", hard: " << rlim.rlim_max << endl;
      }
      seteuid(uid);
    }
  }
#endif
///////////////////结束Linux代码
//如果定义了GK用户,设定用户
#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
  //InitLogging设定日志为PTrace::DateAndTime 和 PTrace::TraceLevel
  //如果存在参数 -o 则设定日志文件 函数为 SetLogFilename Gk.cxx line 797 注意要使用锁PWaitAndSignal,避免同时操作文件
  //InitToolkit调用InstanceOf<Toolkit>(),即使用Toolkit的构造函数
  /*********************************
  template<class T> T *InstanceOf()
  {
    if (Singleton<T>::m_Instance == 0) {
      PWaitAndSignal lock(Singleton<T>::m_CreationLock);
      // We have to check it again after we got the lock
      if (Singleton<T>::m_Instance == 0)
        Singleton<T>::m_Instance = new T;
    }
    return Singleton<T>::m_Instance;
  }
  *********************************/
  //Create ToolKit(1)
  if(!InitLogging(args) || !InitToolkit(args))
    return;
  //如果参数存在 -h 选项,则输出选项,并退出GK
  if (args.HasOption('h')) {
    PrintOpts();
    ExitGK();
  }
  //InitConfig从文件Gatekeeper.ini中读出配置文件信息,如果没有标志 42 则输出错误配置文件报告
  //InitHandlers函数 如果定义了Win32环境,执行SetConsoleCtrlHandler,该函数选择WinCtrlHandlerProc作为第一个参数
  //也是一个执行函数,用来处理CTRL + C表示用户强行退出
  //这里InitConfig(args)调用InstanceOf<Toolkit>()->SetConfig(fp, section),SetConfig()调用ReloadConfig(),ReloadConfig()
  //调用 InitTable(),InitTable()再调用 CreateTable(),然后继续InitTable()的剩下的部分,输出network..........等等信息
  //继续ReloadConfig(),调用ProxyCriterion.LoadConfig(),输出日志GK/tH.323 Proxy disabled
  //继续ReloadConfig(),调用m_GWRewrite.LoadConfig(m_Config),LoadConfig()调用PrintData();输出GK  Loaded per GW rewrite data
  //继续输出GK  No per GW data loaded
  if (!InitConfig(args) || !InitHandlers(args))
    ExitGK();
  //定义日志文件记录周期
  EnableLogFileRotation();
  //输出欢迎信息 此时 Toolkit已经作为singleton形式创建了
  PString welcome("OpenH323 Gatekeeper - The GNU Gatekeeper with ID '" + Toolkit::GKName() + "' started/n" + Toolkit::GKVersion());
  cout << welcome << '/n';
  PTRACE(1, welcome);
  //如果参数存在 -i选项,则设定GKHome地址为后面参数,这里如果设定的地址不存在GK,会输出Shutting down gatekeeper
  //否则使用Toolkit中函数GetGKHome得到所有的地址,并输出 Listen on home
  if (args.HasOption('i'))
    Toolkit::Instance()->SetGKHome(args.GetOptionString('i').Lines());

  vector<PIPSocket::Address> GKHome;
  PString home(Toolkit::Instance()->GetGKHome(GKHome));
  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
  //设定GK的容量,如果存在参数 -b则从其中读出容量数,否则从全局参数中读出,如果数据 小于 0 ,则输出Disable Bandwidth Management
  //否则设定 Available Bandwidth 为 GKcapacity值
  int GKcapacity;
  if (args.HasOption('b'))
    GKcapacity = args.GetOptionString('b').AsInteger();
  else
    GKcapacity = GkConfig()->GetInteger("TotalBandwidth", -1);
  //创建CallTable instance
  CallTable::Instance()->SetTotalBandwidth(GKcapacity);
  if (GKcapacity < 0)
    cout << "/nDisable Bandwidth Management" << endl;
  else
    cout << "/nAvailable Bandwidth " << GKcapacity << endl;

  // read timeToLive from command line
  //设置TimeToLive选项
  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从类Singleton继承而来,所以调用Singleton的Instance方法,创建RasServer的一个实例。
 //因为设定路由模式定义在类RasServer中,所以这次定义 RasServer(3)的一个实例
  RasServer *RasSrv = RasServer::Instance();

  // read signaling method from commandline
  //设置路由模式
  if (args.HasOption('r'))
    //调用RasServer::SetRoutedMode(),然后对HandlerList调用LoadConfig,HandlerList的LoadConfig()调用
    //PortRange的LoadConfig,然后输出RTPPortRange: 1024-65535
    //HandleList的LoadConfig()调用new ProxyHandler(psprintf("ProxyH(%d)", i)),ProxyHandler从SocketsReader继承过来
    //SocketsReader从RegularJob继承过来,RegularJob从Job继承而来,
    //ProxyHandler的构造函数执行Execute(),这里Execute()调用基类Job的Execute()方法,从而执行Agent::Instance()->Exec(this)
    //创建Agent(4)
    RasSrv->SetRoutedMode(true, (args.GetOptionCount('r') > 1 || args.HasOption("h245routed")));
  else if (args.HasOption('d'))
    RasSrv->SetRoutedMode(false, false);
  else
    RasSrv->SetRoutedMode();
//如果定义环境为WIN32 设定最大的等待退出时间 好允许 GK有充分的时间完成所有的退出操作
#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
}


/*************************************************************************************************************
                                                   分析RasServer Run
*************************************************************************************************************/
void RasServer::Run()
{
  //初始化一些静态变量
  /*
  Kit = Toolkit::Instance(); Toolkit *RasMsg::Kit;
  StatusPort = GkStatus::Instance(); GkStatus *RasMsg::StatusPort;//这里创建Create instance: GkStatus(5)
  EndpointTbl = RegistrationTable::Instance(); RegistrationTable *RasMsg::EndpointTbl;//这里创建Create instance: RegistrationTable(6)
  CallTbl = CallTable::Instance(); CallTable *RasMsg::CallTbl;
  RasSrv = RasServer::Instance(); RasServer *RasMsg::RasSrv;
  */
  
  RasMsg::Initialize();
  
  RasPDU<H225_GatekeeperRequest>::Creator GRQCreator;
  RasPDU<H225_GatekeeperConfirm>::Creator GCFCreator;
  RasPDU<H225_GatekeeperReject>::Creator GRJCreator;
  RegistrationRequestPDU::Creator RRQCreator;
  RasPDU<H225_RegistrationConfirm>::Creator RCFCreator;
  RasPDU<H225_RegistrationReject>::Creator RRJCreator;
  RasPDU<H225_UnregistrationRequest>::Creator URQCreator;
  RasPDU<H225_UnregistrationConfirm>::Creator UCFCreator;
  RasPDU<H225_UnregistrationReject>::Creator URJCreator;
  AdmissionRequestPDU::Creator ARQCreator;
  RasPDU<H225_AdmissionConfirm>::Creator ACFCreator;
  RasPDU<H225_AdmissionReject>::Creator ARJCreator;
  RasPDU<H225_BandwidthRequest>::Creator BRQCreator;
  RasPDU<H225_BandwidthConfirm>::Creator BCFCreator;
  RasPDU<H225_BandwidthReject>::Creator BRJCreator;
  RasPDU<H225_DisengageRequest>::Creator DRQCreator;
  RasPDU<H225_DisengageConfirm>::Creator DCFCreator;
  RasPDU<H225_DisengageReject>::Creator DRJCreator;
  RasPDU<H225_LocationRequest>::Creator LRQCreator;
  RasPDU<H225_LocationConfirm>::Creator LCFCreator;
  RasPDU<H225_LocationReject>::Creator LRJCreator;
  RasPDU<H225_InfoRequest>::Creator IRQCreator;
  RasPDU<H225_InfoRequestResponse>::Creator IRRCreator;
  RasPDU<H225_UnknownMessageResponse>::Creator UMRCreator;
  RasPDU<H225_RequestInProgress>::Creator RIPCreator;
  RasPDU<H225_ResourcesAvailableIndicate>::Creator RAICreator;
  RasPDU<H225_ServiceControlIndication>::Creator SCICreator;
  RasPDU<H225_ServiceControlResponse>::Creator SCRCreator;
  // 创建TCPServer
  listeners = new TCPServer;
  //创建GkClient
  gkClient = new GkClient;
  //创建NeighborList
  neighbors = new NeighborList;
  //创建GkAuthenticatorList
  authList = new GkAuthenticatorList;
  //创建GkAcctLoggerList
  acctList = new GkAcctLoggerList;
  //闯将VirtualQueue
  vqueue = new VirtualQueue;
  //这里调用RasServer的LoadConfig()方法,记录日志GK  Home
  //并且调用GkInterface *gkif = CreateInterface(addr);
      //if (gkif->CreateListeners(this))
      //  interfaces.push_back(gkif);
      //然后CreateListeners(this)调用SetListener(rasPort, m_rasPort, m_rasListener, &GkInterface::CreateRasListener)
      //调用SetListener(multicastPort, m_multicastPort, m_multicastListener, &GkInterface::CreateMulticastListener)
      //调用SetListener(signalPort, m_signalPort, m_callSignalListener, &GkInterface::CreateCallSignalListener)
      //调用SetListener(statusPort, m_statusPort, m_statusListener, &GkInterface::CreateStatusListener)
      //调用GKInterface::CreateRasListener()方法
      //该方法调用return new RasListener(m_address, m_rasPort);
      //然后RasListener调用Listen(addr, 0, pt, PSocket::CanReuseAddress)
      //由于RasListener从UDPSocket继承而来,UDPSocket为typedef YaUDPSocket UDPSocket,
      //即RasListener调用YaUDPSocket的Listen方法,然后YaUDPSocket的Listen方法调用socket()方法,
      //并且调用Bind(addr, pt),Bind()方法如下:
      //这是UDP 1719端口
      /************************************************************************************
      bool YaSocket::Bind(const Address & addr, WORD pt)
      {
        if (IsOpen()) {
          sockaddr_in inaddr;
          memset(&inaddr, 0, sizeof(inaddr));
          inaddr.sin_family = AF_INET;
          inaddr.sin_addr.s_addr = addr;
          inaddr.sin_port = htons(pt);
          if (ConvertOSError(::bind(os_handle, (struct sockaddr *)&inaddr, sizeof(inaddr)))) {
            socklen_t insize = sizeof(inaddr);
            if (::getsockname(os_handle, (struct sockaddr *)&inaddr, &insize) == 0) {
              port = ntohs(inaddr.sin_port);
              return true;
            }
          }
        }
        return false;
      }
      ************************************************************************************/
      //然后SetListener调用ValidateSocket(listener, oport),然后输出Listening to port
      //SetListener(signalPort, m_signalPort, m_callSignalListener, &GkInterface::CreateCallSignalListener)
      //调用GkInterface::CreateCallSignalListener方法,该方法调用
      //return m_rasSrv->IsGKRouted() ? new CallSignalListener(m_address, m_signalPort) : 0,也就是如果系统选择路由模式
      //就new CallSignalListener(m_address, m_signalPort),这里CallSignalListener类从TCPListenSocket继承而来
      //所有它的Listen方法是TCP的Listen,监听端口为1721
      //调用SetListener(statusPort, m_statusPort, m_statusListener, &GkInterface::CreateStatusListener)
      //方法调用GkInterface::CreateStatusListener,该方法调用
      //return new StatusListener(m_address, m_statusPort),这里StatusListener也是从TCPListenSocket继承而来
      //所以Listen方法是TCP的Listen,监听端口是7000
  LoadConfig();

  callptr nullcall;
  //GKACCT Successfully logged event Line 984 GKAcct.cxx
  acctList->LogAcctEvent(GkAcctLogger::AcctOn,nullcall);
  if (m_socksize > 0) {
    //这里调用RasServer函数HouseKeeping(),HouseKeeping下面分析
    CreateJob(this, &RasServer::HouseKeeping, "HouseKeeping");
    //这里是重点哦********************************
    //因为RegularJob是SocketsReader的基类,而SocketsReader又是RasServer的基类
    //所以这里可以调用RegularJob::Run()方法,这里我们来看一下Run方法的实现.
    /*
    void RegularJob::Run()
    {
      OnStart();
  
      while (!m_stop)
        Exec();
    
      // lock to allow a member function that is calling Stop
      // return before OnStop is called and the object is deleted
      PWaitAndSignal lock(m_deletionPreventer);
      OnStop();
    }
    */
    //上面的Run()方法调用了基类的纯虚函数Exec(),SocketsReader从RegularJob继承而来,而在SocketsReader类里面实现了Exec()方法
    /*
    void SocketsReader::Exec()
    {
      ReadLock cfglock(ConfigReloadMutex);
      SocketSelectList slist(GetName());

      if (BuildSelectList(slist)) {
        if (SelectSockets(slist)) {
          int ss = slist.GetSize();
          for (int i = 0; i < ss; ++i)
    #ifdef LARGE_FDSET
            ReadSocket(slist[i]);
    #else
            ReadSocket(dynamic_cast<IPSocket *>(slist[i]));
    #endif
        }
        CleanUp();
      } else {
        CleanUp();
        ConfigReloadMutex.EndRead();
        PTRACE(6, GetName() << " waiting...");
        Wait(SOCKETSREADER_IDLE_TIMEOUT);
        ConfigReloadMutex.StartRead();
      }
    }
    */
    //上面的ReadSocket(slist[i])及ReadSocket(dynamic_cast<IPSocket *>(slist[i])),
    //ReadSocket参考RasSrv.cxx 1254行,然后ReadSocket调用RasListener类的ReadRas()方法
    //然后ReadRas()方法调用GatekeeperMessage类的Read()方法,
    //然后Read()方法如下:
    /*
    bool GatekeeperMessage::Read(RasListener *socket)
    {
      m_socket = socket;
      const int buffersize = 4096;
      BYTE buffer[buffersize];
      if (!socket->Read(buffer, buffersize)) {
        PTRACE(1, "RAS/tRead error " << socket->GetErrorCode(PSocket::LastReadError)
          << '/' << socket->GetErrorNumber(PSocket::LastReadError) << ": "
          << socket->GetErrorText(PSocket::LastReadError)
          );
        return false;
      }
      socket->GetLastReceiveAddress(m_peerAddr, m_peerPort);
      PTRACE(2, "RAS/tRead from " << m_peerAddr << ':' << m_peerPort);
      m_rasPDU = PPER_Stream(buffer, socket->GetLastReadCount());
      bool result = m_recvRAS.Decode(m_rasPDU);
      PTRACE_IF(1, !result, "RAS/tCould not decode message from " << m_peerAddr << ':' << m_peerPort);
      return result;
    }
    */
    RegularJob::Run();
  }
  acctList->LogAcctEvent(GkAcctLogger::AcctOff,nullcall);
}

//******************************************HouseKeeping******************************************//
void RasServer::HouseKeeping()
{
#if PTRACING
 PTime startUp;
#endif
  //IsRunning()调用RegularJob类得IsRunning()方法表示程序仍在运行
  for (unsigned count = 0; IsRunning(); ++count)
    if (!Wait(1000)) {
      if( !IsRunning() )
        break;

      ReadLock lock(ConfigReloadMutex);

      if (!(count % 60)) // one minute
        //每分钟检测一下EndPoints 函数实现如下
        RegistrationTable::Instance()->CheckEndpoints();
      //CallTable检查通话连接,下面讨论
      CallTable::Instance()->CheckCalls(this);

      gkClient->CheckRegistration();

      Toolkit::Instance()->GetTimerManager()->CheckTimers();
    }
}

//**********************************CheckEndPoints****************************************************//
void RegistrationTable::CheckEndpoints()
{
  PTime now;
  WriteLock lock(listLock);

  iterator Iter = EndpointList.begin(), eIter = EndpointList.end();
  while (Iter != eIter) {
    iterator i = Iter++;
    EndpointRec *ep = *i;
    //Gatekeeper 送出一個 InfoRequest (IRQ) 詢問某一端點是否仍存活著。
    //如果該端點仍活著的話,應立即回應一個 InfoRequestResponse (IRR)。
    //这里如果Isupdated返回false或者SendIRQ()返回false
    //
    /*
    bool EndpointRec::SendIRQ()
    {
      if (m_pollCount <= 0 || GetRasAddress().GetTag() != H225_TransportAddress::e_ipAddress)
        return false;
      --m_pollCount;
  
      RasServer *RasSrv = RasServer::Instance();
      H225_RasMessage ras_msg;
      ras_msg.SetTag(H225_RasMessage::e_infoRequest);
      H225_InfoRequest & irq = ras_msg;
      irq.m_requestSeqNum.SetValue(RasSrv->GetRequestSeqNum());
      irq.m_callReferenceValue.SetValue(0); // ask for each call

      PString msg(PString::Printf, "IRQ|%s|%s;/r/n",
          (const unsigned char *) AsDotString(GetRasAddress()),
          (const unsigned char *) GetEndpointIdentifier().GetValue());
           GkStatus::Instance()->SignalStatus(msg, STATUS_TRACE_LEVEL_RAS);
      RasSrv->SendRas(ras_msg, GetRasAddress());

      return true;
    }
    */
    if (!ep->IsUpdated(&now) && !ep->SendIRQ()) {
      /*
      void SoftPBX::DisconnectEndpoint(const endptr &ep)
      {
        if (!ep) {
        PString msg("SoftPBX: no endpoint to disconnect!");
        PTRACE(1, "GK/t" + msg);
        GkStatus::Instance()->SignalStatus(msg + "/r/n");
        return;
        }
        callptr Call;
        // remove all calls of ep
        while (Call = CallTable::Instance()->FindCallRec(ep)) {
          Call->Disconnect();
          CallTable::Instance()->RemoveCall(Call);
        }
      }
      */
      SoftPBX::DisconnectEndpoint(endptr(ep));
      /*
      EndpointRec *EndpointRec::Expired()
      {
        //发送unregistration Request
        SendURQ(H225_UnregRequestReason::e_ttlExpired);
        return this;
      }
      */
      ep->Expired();
      //RemovedList中压入该endpoint
      RemovedList.push_back(ep);
      //EndpointList移出
      EndpointList.erase(i);
      //注册数量减少
      --regSize;
      PTRACE(2, "Endpoint " << ep->GetEndpointIdentifier().GetValue() << " expired.");
    }
  }

  Iter = partition(OuterZoneList.begin(), OuterZoneList.end(),
    bind2nd(mem_fun(&EndpointRec::IsUpdated), &now));
#if PTRACING
  if (ptrdiff_t s = distance(Iter, OuterZoneList.end()))
    PTRACE(2, s << " outerzone endpoint(s) expired.");
#endif
  copy(Iter, OuterZoneList.end(), back_inserter(RemovedList));
  OuterZoneList.erase(Iter, OuterZoneList.end());

  // Cleanup unused EndpointRec in RemovedList
  Iter = partition(RemovedList.begin(), RemovedList.end(), mem_fun(&EndpointRec::IsUsed));
  DeleteObjects(Iter, RemovedList.end());
  RemovedList.erase(Iter, RemovedList.end());
}
//************************************CheckCalls***************************************************//
void CallTable::CheckCalls(
  RasServer* rassrv
  )
{
  std::list<callptr> m_callsToDisconnect;
  std::list<callptr> m_callsToUpdate;
  time_t now;
  
  {  
    WriteLock lock(listLock);
    iterator Iter = CallList.begin(), eIter = CallList.end();
    now = time(0);
    while (Iter != eIter) {
      if ((*Iter)->IsTimeout(now))
        m_callsToDisconnect.push_back(callptr(*Iter));
      else if (m_acctUpdateInterval && (*Iter)->IsConnected()) {
        if((now - (*Iter)->GetLastAcctUpdateTime()) >= m_acctUpdateInterval)
          m_callsToUpdate.push_back(callptr(*Iter));
      }
      Iter++;
    }
    //这里使用STL 算法 partition,是因为它是一个非常快速的算法,可以将满足CallRec::IsUsed函数的对象
    //排到Iter后面.
    Iter = partition(RemovedList.begin(), RemovedList.end(), mem_fun(&CallRec::IsUsed));
    DeleteObjects(Iter, RemovedList.end());
    RemovedList.erase(Iter, RemovedList.end());
  }
  //下面的算法移出所有需要Disconnect的Calls
  std::list<callptr>::iterator call = m_callsToDisconnect.begin();
  while (call != m_callsToDisconnect.end()) {
    (*call)->SetDisconnectCause((*call)->IsConnected()
      ? Q931::ResourceUnavailable : Q931::TemporaryFailure
      );
    (*call)->SetReleaseSource(CallRec::ReleasedByGatekeeper);
    (*call)->Disconnect();
    RemoveCall((*call));
    call++;
  }
  //下面的算法Update所有需要被update的Calls
  call = m_callsToUpdate.begin();
  while (call != m_callsToUpdate.end()) {
    if ((*call)->IsConnected())
      //更新*call
      /*********************************************************************************
      bool GkAcctLoggerList::LogAcctEvent(
        GkAcctLogger::AcctEvent evt, /// the accounting event to be logged
        const callptr& call, /// a call associated with the event (if any)
        time_t now /// "now" timestamp for accounting update events
      )
      {
        // if this is an accounting update, check the interval
        if (evt & GkAcctLogger::AcctUpdate)
          if ((!call) || m_acctUpdateInterval == 0
            || (now - call->GetLastAcctUpdateTime()) < m_acctUpdateInterval)
            return true;
          else
            call->SetLastAcctUpdateTime(now);
      
        bool finalResult = true;
        GkAcctLogger::Status status = GkAcctLogger::Ok;
        std::list<GkAcctLogger*>::const_iterator iter = m_loggers.begin();
  
        while (iter != m_loggers.end()) {
          GkAcctLogger* logger = *iter++;
  
          if ((evt & logger->GetEnabledEvents() & logger->GetSupportedEvents()) == 0)
            continue;
    
          status = logger->Log(evt, call);
          switch (status)
          {
          case GkAcctLogger::Ok:
      #if PTRACING
            if (PTrace::CanTrace(3)) {
              ostream& strm = PTrace::Begin(3,__FILE__,__LINE__);
              strm << "GKACCT/t" << logger->GetName() << " logged event " << evt;
              if (call)
                strm << " for call no. " << call->GetCallNumber();
              PTrace::End(strm);
            }
      #endif
            break;
      
          default:
      #if PTRACING
            if (PTrace::CanTrace(3)) {
              ostream& strm = PTrace::Begin(3, __FILE__, __LINE__);
              strm << "GKACCT/t" << logger->GetName() << " failed to log event "
                << evt;
              if (call)
                strm << " for call no. " << call->GetCallNumber();
              PTrace::End(strm);
            }
      #endif
            // required and sufficient rules always determine
            // status of the request
            if (logger->GetControlFlag() == GkAcctLogger::Required
              || logger->GetControlFlag() == GkAcctLogger::Sufficient)
              finalResult = false;
          }
    
          // sufficient and alternative are terminal rules (on log success)
          if (status == GkAcctLogger::Ok
            && (logger->GetControlFlag() == GkAcctLogger::Sufficient
            || logger->GetControlFlag() == GkAcctLogger::Alternative))
            break;
        }

        // a last rule determine status of the the request
        if (finalResult && status != GkAcctLogger::Ok)
          finalResult = false;
    
      #if PTRACING
        if (PTrace::CanTrace(2)) {
          ostream& strm = PTrace::Begin(2, __FILE__, __LINE__);
          strm << "GKACCT/t" << (finalResult ? "Successfully logged event "
            : "Failed to log event ") << evt;
          if (call)
            strm << " for call no. " << call->GetCallNumber();
          PTrace::End(strm);
        }
      #endif
        return finalResult;
      }
      *********************************************************************************/
      rassrv->LogAcctEvent(GkAcctLogger::AcctUpdate, *call, now);
    call++;
  }
  

你可能感兴趣的:(算法,struct,socket,File,iterator,buffer)