/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   
* This file was autogenerated by rpcgen, but should be modified by the developer.
* Make sure you don't use the -component_mod flag in future or this file will be overwritten.
* Fri Oct 17 09:37:11 2003
* System Includes
*
*/




#include <stdio.h>
#include <signal.h>


/****************************************************************************************
 * 
 * Local Includes
 * 
 ***************************************************************************************/
#include "CSvcPppcontroller.h"
#include "pppcontroller.h"
#include "../include/standard_unix.h"
#include "../include/standard_service_manager.h"


/****************************************************************************************
 * 
 * File-scope variables
 * 
 ***************************************************************************************/
static CComponentManager<CSPppcontroller> *iComponentManager;
static pid_t iServerProcess;


/*******************************************************************************
 *
 * SIGNAL HANDLER - SIGTERM: We need pppd to start in our process group so that
 * we can send signals to it (to stop it). The problem is that when you try
 * and kill pppd it sends a term signal to everyone in it's process group. So,
 * we should just ignore SIGTERM and if anyone wants to kill us manually they
 * can use SIGINT (or SIGKILL in times of need). The problem with this is that
 * when we fork processes, but before we exec pppd, the child is also ignoring
 * SIGTERM and if we try and kill it before it is exec'd then it won't die 
 * and we wait on the pid forever. We could make wait more intelligent
 * (i.e. timeout and resend the signal) but that is not so nice as waitpid
 * doesn't have a timeout -- means we have to use WNOHANG and poll every
 * X seconds which isn't gret. Instead we record the pid of the main process
 * and check this in the signal handler. If it matches then the signal is
 * ignored -- otherwise the process is terminated.
 *
 ******************************************************************************/
void handle_sigterm( int sig )
{
  pid_t pid, ppid;
  pid = getpid();
  if( pid == iServerProcess ) {
    return;
  } 
  ppid = getppid();
  fprintf( stderr, "INFO: SIGTERM received before exec (pid = %d, ppid = %d).\n", pid, ppid );
  exit( -1 );
}


/****************************************************************************************
 * 
 * Implementation
 * 
 ***************************************************************************************/


/****************************************************************************************
 * 
 * PUBLIC: GetInstanceKeyFromArgs
 * 
 ***************************************************************************************/
int CSvcPppcontroller::GetInstanceKeyFromArgs( int aMethod, void *aArgs )
{
	int rv;
	int *ik_integer;
	switch( aMethod ) {

	// integer instance keys
	case DSTR_REMOVEPPPSESSION:
	case KILLSESSION:
	case STOPSESSION:
	case GETSESSIONINFO:
	case GETPPPLOG:
		ik_integer = (int*)aArgs;
		rv = *ik_integer;
		break;

	// error
	default:
		rv = ERR_INVALID_METHOD;
		break;
	}
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC: SetError
 * 
 ***************************************************************************************/
int CSvcPppcontroller::SetError( int aMethod, void *aArgs, int aError )
{
	int rv = ERR_NONE;
	TResult *rv_result;
	TComponentList *rv_component_list;
	TPppSessionDesc *rv_session_desc;
	TVarData *rv_var_data;

	switch( aMethod ) {

	// TComponentList
	case LIST_DEVICES:
		SET_LIST_ERROR_CODE( TComponentList, rv_component_list );
		break;

	// TPppSessionDesc
	case GETSESSIONINFO:
		SET_ERROR_CODE( TPppSessionDesc, iErrorCode, rv_session_desc );
		break;

	// TVarData
	case GETPPPLOG:
		SET_LIST_ERROR_CODE( TVarData, rv_var_data );
		break;

	// TResult return
	case CSTR_STARTPPPSESSION:
	case DSTR_REMOVEPPPSESSION:
	case KILLSESSION:
	case STOPSESSION:
		SET_ERROR_CODE( TResult, iStandardResult, rv_result );
		break;

	// Error
	default:
		rv = ERR_INVALID_METHOD;
		break;
	}
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC: GetError
 * 
 ***************************************************************************************/
int CSvcPppcontroller::GetError( int aMethod, void *aArgs )
{
  TResult *result;
  
  // check assumption
  assert( (aMethod == CSTR_STARTPPPSESSION) || (aMethod == DSTR_REMOVEPPPSESSION) );
  
  // return error code
  result = (TResult*)aArgs;
  return result->iStandardResult;
}


/****************************************************************************************
 * 
 * PUBLIC: StartRPCService
 * 
 ***************************************************************************************/
int CSvcPppcontroller::StartRPCService( CComponentManager<CSPppcontroller> *aComponentManager, TStartupInfo *aArg )
{	
	sighandler_t oh;

	// get the server process's ID for the signal handler
	iServerProcess = getpid();

	// register the sigterm handler
	oh = signal( SIGTERM, handle_sigterm );
	if( oh == SIG_ERR ) {
		return ERR_SET_SIGNAL_ERROR;
	}

	// setup the component manager
	assert( iComponentManager == NULL );
	iComponentManager = aComponentManager;
	return ERR_NONE;
}


/****************************************************************************************
 * 
 * PUBLIC: StopRPCService
 * 
 ***************************************************************************************/
int CSvcPppcontroller::StopRPCService()
{
	iComponentManager = NULL;
	return ERR_NONE;
}
