As Service

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [SIP]     [Open H.323]     [Gnu Gatekeeper]     [Asterisk PBX]     [ISDN Cause Codes]     [Yosemite News]

  Powered by Linux