I tried to inherit gk from PServiceProcess, but
getting some linker ,compilation errors.Please can anyone help me in this
regard.
Thanx a lot in advance.
________________
Engr. Rafat Subhan Software Developer Advanced Communications mail: rafat@xxxxxxxxxxxxxxx MSN: qudrat2210@xxxxxxxxxxx http://www.beyondphone.com |
////////////////////////////////////////////////////////////////// // // gk.cxx for OpenH323 Gatekeeper - GNU Gatekeeper // // This work is published under the GNU Public License (GPL) // see file COPYING for details. // We also explicitely grant the right to link this code // with the OpenH323 library. // // History: // 990500 initial version (Xiang Ping Chen, Rajat Todi, Joe Metzger) // 990600 ported to OpenH323 V. 1.08 (Jan Willamowius) // 990702 code cleanup (Jan Willamowius) // 990924 clean shutdown (Jan Willamowius) // 991016 clean shutdown (Jan Willamowius) // ////////////////////////////////////////////////////////////////// #if (_MSC_VER >= 1200) #pragma warning( disable : 4800 ) // one performance warning off #pragma warning( disable : 4786 ) // warning about too long debug symbol off #endif #ifndef WIN32 #define HAS_SETUSERNAME #include <signal.h> #endif #include <ptlib.h> #include <h225.h> #include "h323util.h" #include "Toolkit.h" #include "stl_supp.h" #include "RasSrv.h" #include "RasTbl.h" #include "SoftPBX.h" #include "gk.h" #if PTRACING PTextFile *logfile = 0; PString logfilename; void ReopenLogFile() { if (!logfilename) { PTRACE_IF(1, logfile, "GK\tLogging closed."); PTrace::SetStream(&cerr); // redirect to cerr delete logfile; PTime now; PFilePath fileName; logfile = new PTextFile(logfilename, PFile::WriteOnly, PFile::MustExist); if (logfile->IsOpen()) { // Backup of log file fileName = logfile->GetFilePath(); fileName.Replace(".", "." + now.AsString("yyyyMMdd_hhmmss") + "."); logfile->Move(logfile->GetFilePath(),fileName); } delete logfile; logfile = new PTextFile( logfilename, PFile::WriteOnly, PFile::Create); if (!logfile->IsOpen()) { cerr << "Warning: could not open trace output file \"" << fileName << '"' << endl; delete logfile; logfile = 0; return; } logfile->SetPosition(logfile->GetLength()); PTrace::SetStream(logfile); // redirect to logfile } PTRACE(1, "GK\tTrace logging restarted."); } #endif /* * many things here should be members of Gatkeeper. */ PReadWriteMutex ConfigReloadMutex; namespace { // keep the global objects private PMutex ShutdownMutex; PMutex ReloadMutex; #ifndef WIN32 PString pidfile("/var/run/gnugk.pid"); #endif void ShutdownHandler() { // delete singleton objects PTRACE(3, "GK\tDeleting global reference tables"); Job::StopAll(); delete CallTable::Instance(); delete RegistrationTable::Instance(); delete RasServer::Instance(); delete Toolkit::Instance(); PTRACE(3, "GK\tdelete ok"); #if PTRACING PTrace::SetStream(&cerr); // redirect to cerr delete logfile; #endif } bool CheckSectionName(PConfig *cfg) { bool result = true; PStringList sections = cfg->GetSections(); for (PINDEX i = 0; i < sections.GetSize(); ++i) { PString sec = sections[i]; if (sec.Find("RasSvr") == 0) { cerr << "The section " << sec << " should be "; sec.Replace("RasSvr", "RasSrv"); cerr << sec << '\n'; result = false; } } if (!result) cerr << endl; return result; } // due to some unknown reason (PWLib bug?), // we have to delete Toolkit::Instance first, // or we get core dump void ExitGK() { delete Toolkit::Instance(); #if PTRACING PTrace::SetStream(&cerr); // redirect to cerr delete logfile; #endif exit(0); } } // end of anonymous namespace void ReloadHandler() { // only one thread must do this if (ReloadMutex.WillBlock()) return; /* ** Enter critical Section */ PWaitAndSignal reload(ReloadMutex); ConfigReloadMutex.StartWrite(); /* ** Force reloading config */ InstanceOf<Toolkit>()->ReloadConfig(); SoftPBX::TimeToLive = GkConfig()->GetInteger("TimeToLive", SoftPBX::TimeToLive); /* ** Update all gateway prefixes */ CallTable::Instance()->LoadConfig(); RegistrationTable::Instance()->LoadConfig(); // don't put this in LoadConfig() RasServer::Instance()->SetRoutedMode(); RasServer::Instance()->LoadConfig(); ConfigReloadMutex.EndWrite(); /* ** Don't disengage current calls! */ PTRACE(3, "GK\tCarry on current calls."); /* ** Leave critical Section */ // give other threads the chance to pass by this handler PProcess::Sleep(500); } #ifdef WIN32 BOOL WINAPI WinCtrlHandlerProc(DWORD dwCtrlType) { PString eventName = "CTRL_UNKNOWN_EVENT"; if( dwCtrlType == CTRL_LOGOFF_EVENT ) { eventName = "CTRL_LOGOFF_EVENT"; #if PTRACING PTRACE(2,"GK\tGatekeeper received " <<eventName); #endif // prevent shut down return FALSE; } if( dwCtrlType == CTRL_C_EVENT ) eventName = "CTRL_C_EVENT"; else if( dwCtrlType == CTRL_BREAK_EVENT ) eventName = "CTRL_BREAK_EVENT"; else if( dwCtrlType == CTRL_CLOSE_EVENT ) eventName = "CTRL_CLOSE_EVENT"; else if( dwCtrlType == CTRL_SHUTDOWN_EVENT ) eventName = "CTRL_SHUTDOWN_EVENT"; #if PTRACING PTRACE(1,"GK\tGatekeeper shutdown due to "<<eventName); #endif PWaitAndSignal shutdown(ShutdownMutex); RasServer::Instance()->Stop(); // CTRL_CLOSE_EVENT: // this case needs special treatment as Windows would // immidiately call ExitProcess() upon returning TRUE, // and the GK has no chance to clean-up. The call to // WaitForSingleObject() results in around 5 sec's of // clean-up time - This may at times not be sufficient // for the GK to shut down in an organized fashion. The // only safe way to handle this, is to remove the // 'Close' menu item from the System menu and we will // never have to deal with this event again. if( dwCtrlType == CTRL_CLOSE_EVENT ) WaitForSingleObject(GetCurrentProcess(), 15000); // proceed with shut down return TRUE; } bool Gatekeeper::SetUserAndGroup(const PString& /*username*/) { return false; } #else # include <pwd.h> bool Gatekeeper::SetUserAndGroup(const PString &username) { #if defined(P_PTHREADS) && !defined(P_THREAD_SAFE_CLIB) static const size_t MAX_PASSWORD_BUFSIZE = 1024; struct passwd userdata; struct passwd *userptr; char buffer[MAX_PASSWORD_BUFSIZE]; #if defined (P_LINUX) || defined (P_AIX) || defined(P_IRIX) || (__GNUC__>=3 && defined(P_SOLARIS)) || defined(P_RTEMS) ::getpwnam_r(username,&userdata,buffer,sizeof(buffer),&userptr); #else userptr = ::getpwnam_r(username, &userdata, buffer, sizeof(buffer)); #endif #else struct passwd *userptr = ::getpwnam(username); #endif return userptr && userptr->pw_name && (::setgid(userptr->pw_gid) == 0) && (::setuid(userptr->pw_uid) == 0); } void UnixShutdownHandler(int sig) { if (ShutdownMutex.WillBlock() || !RasServer::Instance()->IsRunning()) return; PWaitAndSignal shutdown(ShutdownMutex); PTRACE(1, "GK\tReceived signal " << sig); PFile::Remove(pidfile); RasServer::Instance()->Stop(); } void UnixReloadHandler(int sig) // For HUP Signal { PTRACE(1, "GK\tGatekeeper Hangup (signal " << sig << ")"); #if PTRACING ReopenLogFile(); #endif ReloadHandler(); } void DumbHandler(int sig) { PTRACE(1, "Warning: signal " << sig << " received and ignored!"); } #endif // WIN32 // default params for overwriting Gatekeeper::Gatekeeper(const char * manuf, const char * name, WORD majorVersion, WORD minorVersion, CodeStatus status, WORD buildNumber) : PServiceProcess(manuf, name, majorVersion, minorVersion, status, buildNumber) { } const PString Gatekeeper::GetArgumentsParseString() const { return PString ("r-routed." "-h245routed." "d-direct." "i-interface:" "l-timetolive:" "b-bandwidth:" #ifdef HAS_SETUSERNAME "u-user:" #endif #if PTRACING "t-trace." "o-output:" #endif "c-config:" "s-section:" "-pid:" "h-help:" ); } BOOL Gatekeeper::InitHandlers(const PArgList& args) { #ifdef WIN32 SetConsoleCtrlHandler(WinCtrlHandlerProc, TRUE); #else signal(SIGTERM, UnixShutdownHandler); signal(SIGINT, UnixShutdownHandler); signal(SIGQUIT, UnixShutdownHandler); signal(SIGUSR1, UnixShutdownHandler); // ignore these signals signal(SIGPIPE, DumbHandler); signal(SIGABRT, DumbHandler); struct sigaction sa; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); // ignore while in handler sa.sa_flags = 0; sa.sa_handler = UnixReloadHandler; sigaction(SIGHUP, &sa, NULL); if (args.HasOption("pid")) pidfile = args.GetOptionString("pid"); PTextFile pid(pidfile, PFile::WriteOnly); pid.WriteLine(PString(PString::Unsigned, getpid())); #endif return TRUE; } BOOL Gatekeeper::InitLogging(const PArgList &args) { #if PTRACING // PTrace::SetOptions(PTrace::Timestamp | PTrace::Thread); // PTrace::SetOptions(PTrace::Timestamp); //PTrace::SetOptions(PTrace::DateAndTime | PTrace::TraceLevel | PTrace::Thread); PTrace::SetOptions(PTrace::DateAndTime | PTrace::TraceLevel); PTrace::SetLevel(args.GetOptionCount('t')); if (args.HasOption('o')) { logfilename = args.GetOptionString('o'); ReopenLogFile(); } #endif return TRUE; } BOOL Gatekeeper::InitToolkit(const PArgList& /*args*/) { InstanceOf<Toolkit>(); // force using the right Toolkit constructor return TRUE; } BOOL Gatekeeper::InitConfig(const PArgList &args) { // get the name of the config file PFilePath fp("gatekeeper.ini"); PString section("Gatekeeper::Main"); if (args.HasOption('c')) fp = PFilePath(args.GetOptionString('c')); if (args.HasOption('s')) section = args.GetOptionString('s'); InstanceOf<Toolkit>()->SetConfig(fp, section); if( (GkConfig()->GetInteger("Fourtytwo") ) != 42) { cerr << "WARNING: No config file found!\n" << "- Does the config file exist? The default (~/.pwlib_config/Gatekeeper.ini or gatekeeper.ini in current directory) or the one given with -c?\n" << "- Did you specify they the right 'Main' section with -s?\n" << "- Is the line 'Fourtytwo=42' present in this 'Main' section?"<<endl; } return CheckSectionName(GkConfig()); } void Gatekeeper::PrintOpts(void) { cout << "Options:\n" " -r --routed : Use gatekeeper routed call signaling\n" " -rr --h245routed : Use H.245 control channel routed\n" " -d --direct : Use direct endpoint call signaling\n" " -i --interface IP : The IP that the gatekeeper listen to\n" " -l --timetolive n : Time to live for client registration\n" " -b --bandwidth n : Specify the total bandwidth\n" #ifdef HAS_SETUSERNAME " -u --user name : Run as this user\n" #endif #if PTRACING " -t --trace : Set trace verbosity\n" " -o --output file : Write trace to this file\n" #endif " -c --config file : Specify which config file to use\n" " -s --section sec : Specify which main section to use in the config file\n" " --pid file : Specify the pid file\n" " -h --help : Show this message\n" << endl; } BOOL Gatekeeper::OnStart() { PArgList & args = GetArguments(); args.Parse(GetArgumentsParseString()); /*if(!InitLogging(args) || !InitToolkit(args)) return;*/ if (args.HasOption('h')) { PrintOpts(); ExitGK(); } if (!InitConfig(args) || !InitHandlers(args)) ExitGK(); 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')) Toolkit::Instance()->SetGKHome(args.GetOptionString('i').Lines()); std::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 int GKcapacity; 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); RasSrv = RasServer::Instance(); // 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) && !defined(_DEBUG) // 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 return PServiceProcess::OnStart(); } void Gatekeeper::OnStop() { // PWaitAndSignal shutdown(ShutdownMutex); // ExitFlag = true; ShutdownHandler(); } BOOL Gatekeeper::OnPause() { return TRUE; } void Gatekeeper::OnControl() { } void Gatekeeper::OnConfigChanged() { PTRACE(2,"CallBackSvc::OnConfigChanged()"); } void Gatekeeper::Main() { // 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 }
////////////////////////////////////////////////////////////////// // // gk.h gatekeeper process // // This work is published under the GNU Public License (GPL) // see file COPYING for details. // We also explicitely grant the right to link this code // with the OpenH323 library. // // History: // 990500 initial version (Xiang Ping Chen, Rajat Todi, Joe Metzger) // 990600 ported to OpenH323 V. 1.08 (Jan Willamowius) // 990702 code cleanup (Jan Willamowius) // 990710 working again with OpenH323 V. 1.08 (Jan Willamowius) // ////////////////////////////////////////////////////////////////// #ifndef GK_H #define GK_H "@(#) $Id: gk.h,v 1.22 2004/04/17 11:43:42 zvision Exp $" #include "version.h" #include <ptlib/svcproc.h> #if PTRACING void ReopenLogFile(); #endif class Gatekeeper : public PServiceProcess { PCLASSINFO(Gatekeeper, PServiceProcess) public: Gatekeeper (const char * manuf = "Advanced Communication", const char * name = "Gatekeeper", WORD majorVersion = GNUGK_MAJOR_VERSION, WORD minorVersion = GNUGK_MINOR_VERSION, CodeStatus status = GNUGK_BUILD_TYPE, WORD buildNumber = GNUGK_BUILD_NUMBER); BOOL OnStart(); void OnStop(); BOOL OnPause(); void OnControl(); void OnConfigChanged(); BOOL Initialise(const char * initMsg); virtual void Main(); protected: /** returns the template string for which the cmommand line is parsed */ virtual const PString GetArgumentsParseString() const; /**@name Initialization * A sequence of virtual initialization methods is called from #Main# * before the fun starts. * Each one takes the already parsed command line arguments (so you can * depend the behavior on them). Later -- after #InitConfig# -- you can * also use #Toolkit::Config()# to decide different things. * Every method may return #FALSE# to abort #Main# and end the program. */ //@{ /** installs the signal handlers; First called init method. */ virtual BOOL InitHandlers(const PArgList &args); /** factory for the static toolkit; Called after #InitHandlers#. */ virtual BOOL InitToolkit(const PArgList &args); /** factory for the static Config in Toolkit; Called after #InitToolkit# */ virtual BOOL InitConfig(const PArgList &args); /** initiates logging and tracing; Called after #InitConfig# */ virtual BOOL InitLogging(const PArgList &args); /** print the available command-line-options **/ void PrintOpts(void); /** Set a new user and group (ownership) for the GK process. The group that will be set is the user's default group. */ virtual bool SetUserAndGroup(const PString &username); //@} }; #endif // GK_H