diff -r 000000000000 -r 3da2a79470a7 testexecmgmt/ucc/Source/pppcontroller/CSPppcontroller.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecmgmt/ucc/Source/pppcontroller/CSPppcontroller.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,642 @@ +/* +* 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:12 2003 +* +*/ + + + + +/**************************************************************************************** + * + * System Includes + * + ***************************************************************************************/ +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#include +#endif + + +/**************************************************************************************** + * + * Local Includes + * + ***************************************************************************************/ +#include "CSvcPppcontroller.h" +#include "CSPppcontroller.h" +#include "../include/standard_unix.h" +#include "../include/strncpynt.h" +#include "../DynamicsConfigurationLibrary/file_utilities.h" + + +/**************************************************************************************** + * + * Definitions + * + ***************************************************************************************/ +#define MAXLOGNAME 64 +#define MAXCOMMANDLINE 2048 +#define MAXLOGLINELENGTH 1024 +#define PPPD_BINARY "./pppd" +#define GATEWAY_BINARY "./pppdgateway" +#define MAXINTERFACENAMESIZE 64 +#define MAXLISTLINES 32 +#define CONNECTED_STRING "Script /etc/ppp/ip-up finished" +#define DISCONNECTED_STRING "Connection terminated" + +#define IS_INLINE_WHITESPACE(c) (((c) == ' ')||((c) == '\t')) + +/**************************************************************************************** + * + * Implementation + * + ***************************************************************************************/ +CSPppcontroller::CSPppcontroller() +{ + iProcess = NULL; + iSessionStatus = SS_NOT_STARTED; +} + +CSPppcontroller::~CSPppcontroller() +{ + assert( iProcess == NULL ); +} + +int CSPppcontroller::GetKey() +{ + return iKey; +} + +void CSPppcontroller::SetKey( int aKey ) +{ + iKey = aKey; +} + + +/**************************************************************************************** + * + * PUBLIC FUNCTION: cstr_startpppsession + * + ***************************************************************************************/ +TResult CSPppcontroller::cstr_startpppsession( TPppSessionConfig aArgs ) +{ + int err, errcode; + TResult rv = { ERR_NONE, 0, 0 }; + char logfilename[MAXLOGNAME]; + char commandline[MAXCOMMANDLINE]; + TCAProcessError perr; + + // check that we are not already started + assert( iProcess == NULL ); + + // save the config + iSessionConfig = aArgs; + + // construct the name of the logfile + snprintf( logfilename, MAXLOGNAME, "pppd%04d.log", iKey ); + + // remove the file if it exists -- if an error other than file not exists happens then exit + err = unlink( logfilename ); + if( (err != 0) && (errno != ENOENT) ) { + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = 0; + rv.iSystemError = errno; + return rv; + } + + // construct the command line for the PPP session +#ifndef __UNIT_TEST_13 + snprintf( commandline, MAXCOMMANDLINE, "%s pty \'%s %s %s %d\' logfile %s %s", PPPD_BINARY, GATEWAY_BINARY, + iSessionConfig.iMobsterAddress, iSessionConfig.iMobsterPort, iSessionConfig.iMTID, logfilename, iSessionConfig.iSessionConfiguration ); +#else + snprintf( commandline, MAXCOMMANDLINE, "%s notty logfile %s %s", PPPD_BINARY, logfilename, iSessionConfig.iSessionConfiguration ); +#endif + + // now start the process + iProcess = new CAProcess(); + assert( iProcess != NULL ); + perr = iProcess->StartProcess( commandline, &errcode, false, false, true ); + if( perr != CAE_NONE ) { + rv.iStandardResult = ERR_START_PROCESS_ERROR; + rv.iExtendedCode = (int)perr; + rv.iSystemError = errcode; + delete iProcess; + iProcess = NULL; + return rv; + } + + // done - success + return rv; +} + + +/**************************************************************************************** + * + * PUBLIC FUNCTION: dstr_removepppsession + * + ***************************************************************************************/ +TResult CSPppcontroller::dstr_removepppsession( int aArgs, int *aDeleteInstance ) +{ + TResult rv = { ERR_NONE, 0, 0 }; + TCAProcessError perr; + TProcessStatus pstatus; + char logfilename[MAXLOGNAME]; + + // make sure that we still have a process + assert( iProcess != NULL ); + + // get the status of the process to make sure we are ok + perr = iProcess->GetProcessStatus( &pstatus ); + assert( perr == CAE_NONE ); + if( pstatus == PS_STARTED ) { + *aDeleteInstance = 0; + rv.iStandardResult = ERR_INVALIDSTATE; + return rv; + } + + // remove the log file + snprintf( logfilename, MAXLOGNAME, "pppd%04d.log", iKey ); + unlink( logfilename ); + + // ok - remove the process + delete iProcess; + iProcess = NULL; + + // done - success + *aDeleteInstance = 1; + return rv; +} + + +/**************************************************************************************** + * + * PUBLIC FUNCTION: killsession + * + ***************************************************************************************/ +TResult CSPppcontroller::killsession( int aArgs ) +{ + return StopProcessWithSignal( SIGKILL ); +} + + +/**************************************************************************************** + * + * PUBLIC FUNCTION: stopsession + * + ***************************************************************************************/ +TResult CSPppcontroller::stopsession( int aArgs ) +{ + return StopProcessWithSignal( SIGTERM ); +} + + +/**************************************************************************************** + * + * PUBLIC FUNCTION: getsessioninfo + * + ***************************************************************************************/ +TPppSessionDesc CSPppcontroller::getsessioninfo( int aArgs ) +{ + TPppSessionDesc rv; + TResult res; + int exitcode = 0; + TCAProcessError perr; + TProcessStatus pstatus = PS_INVALID; + TProcessExitReason preason = ER_INVALID; + + // check state + assert( iProcess != NULL ); + memset( &rv, 0, sizeof(rv) ); + + // interrogate the process + perr = iProcess->GetProcessStatus( &pstatus ); + assert( perr == CAE_NONE ); + if( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) ) { + perr = iProcess->GetExitReason( &preason ); + assert( perr == CAE_NONE ); + } + if( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) ) { + perr = iProcess->GetExitCode( &exitcode ); + assert( perr == CAE_NONE ); + } + + // update the dynamic config + res = GetInterfaceName(); + if( res.iStandardResult != ERR_NONE ) { + rv.iErrorCode = res.iStandardResult; + rv.iErrorDetail = res.iExtendedCode; + return rv; + } + res = UpdateSessionStatus(); + if( res.iStandardResult != ERR_NONE ) { + rv.iErrorCode = res.iStandardResult; + rv.iErrorDetail = res.iExtendedCode; + return rv; + } + res = GetIPAddresses(); + if( res.iStandardResult != ERR_NONE ) { + rv.iErrorCode = res.iStandardResult; + rv.iErrorDetail = res.iExtendedCode; + return rv; + } + + // now return the info + rv.iErrorCode = ERR_NONE; + rv.iErrorDetail = 0; + rv.iConfig = iSessionConfig; + rv.iProcessStatus = (int)pstatus; + rv.iProcessExitReason = (int)preason; + rv.iProcessExitCode = exitcode; + rv.iSessionStatus = iSessionStatus; + STRNCPY_NULL_TERMINATE( rv.iInterfaceName, iInterfaceName.c_str(), MAXSESSIONNAMELEN ); + rv.iLocalIPAddress = iLocalIPAddress; + rv.iRemoteIPAddress = iRemoteIPAddress; + return rv; +} + + +/**************************************************************************************** + * + * PUBLIC FUNCTION: getppplog + * + ***************************************************************************************/ +TVarData CSPppcontroller::getppplog( int aArgs ) +{ + TVarData rv; + TResult res; + char logname[MAXLOGNAME]; + + // get the logfilename + snprintf( logname, MAXLOGNAME, "pppd%04d.log", iKey ); + + // now copy the file into the vardata buffer + res = CopyFileIntoBuffer( logname, &rv ); + if( res.iStandardResult != ERR_NONE ) { + assert( rv.TVarData_len == 0 ); + assert( rv.TVarData_val == NULL ); + } + + // done + return rv; +} + + +/**************************************************************************************** + * + * PRIVATE FUNCTION: StopProcessWithSignal + * + ***************************************************************************************/ +TResult CSPppcontroller::StopProcessWithSignal( int aSignal ) +{ + TResult rv = { ERR_NONE, 0, 0 }; + TCAProcessError perr; + TProcessStatus pstatus; + + // since we create in the constructor and stop in the destructor there must be a process + assert( iProcess != NULL ); + + // if the process isn't running then it has died outside the scope of this controller, + // clean up the state, return an error since this is noteworthy and should be either + // expected or not happen. + perr = iProcess->GetProcessStatus( &pstatus ); + assert( perr == CAE_NONE ); + if( pstatus != PS_STARTED ) { + assert( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) ); + rv.iStandardResult = ERR_PROCESS_TERMINATED_OUTSIDE_SCOPE; + return rv; + } + + // request the process to stop + perr = iProcess->RequestStop( aSignal ); + if( perr != CAE_NONE ) { + rv.iStandardResult = ERR_STOP_PROCESS_ERROR; + rv.iExtendedCode = (int)perr; + return rv; + } + + // wait for the process to stop + perr = iProcess->WaitForProcessToTerminate( -1 ); + if( perr != CAE_NONE ) { + rv.iStandardResult = ERR_WAIT_PROCESS_ERROR; + rv.iExtendedCode = (int)perr; + return rv; + } + + // done - success + return rv; +} + + +/**************************************************************************************** + * + * PRIVATE FUNCTION: GetInterfaceName + * + ***************************************************************************************/ +TResult CSPppcontroller::GetInterfaceName() +{ + TResult rv; + string line; + char interface_name[MAXINTERFACENAMESIZE]; + + // clear the interface (so if not found we don't have an old value) + iInterfaceName = ""; + + // we want to know the interface name, on line "Using interface pppX"; + rv = GetTokenFromFile( "Using", &line, MM_FIRST ); + if( rv.iStandardResult != ERR_NONE ) { + if( rv.iStandardResult == ERR_INVALIDARG ) { + rv.iStandardResult = ERR_NONE; + rv.iExtendedCode = 0; + } + return rv; + } + + // now grab the interface name + sscanf( line.c_str(), "Using interface %s", interface_name ); + iInterfaceName = interface_name; + + // done - success; + return rv; +} + + +/**************************************************************************************** + * + * PRIVATE FUNCTION: GetIPAddresses + * + ***************************************************************************************/ +TResult CSPppcontroller::GetIPAddresses() +{ + TResult rv; + string line; + char address[MAXINTERFACENAMESIZE]; + + // clear old values + iLocalIPAddress = iRemoteIPAddress = 0; + + // we want to know the local IP address + rv = GetTokenFromFile( "local IP address", &line, MM_LAST ); + if( rv.iStandardResult != ERR_NONE ) { + if( rv.iStandardResult == ERR_INVALIDARG ) { + rv.iStandardResult = ERR_NONE; + rv.iExtendedCode = 0; + } + return rv; + } + + // grab address + sscanf( line.c_str(), "local IP address %s", address ); + iLocalIPAddress = inet_addr( address ); + + // we want to know the remote IP address + rv = GetTokenFromFile( "remote IP address", &line, MM_LAST ); + if( rv.iStandardResult != ERR_NONE ) { + if( rv.iStandardResult == ERR_INVALIDARG ) { + rv.iStandardResult = ERR_NONE; + rv.iExtendedCode = 0; + } + return rv; + } + + // grab address + sscanf( line.c_str(), "remote IP address %s", address ); + iRemoteIPAddress = inet_addr( address ); + + // done - success; + return rv; +} + + +/**************************************************************************************** + * + * PRIVATE FUNCTION: UpdateSessionStatus + * + ***************************************************************************************/ +TResult CSPppcontroller::UpdateSessionStatus() +{ + TResult rv = { ERR_NONE, 0, 0 }; + TFUError ferr; + int mline[MAXLISTLINES], match_count, errcode, once_connected, disconnected; + char logfilename[MAXLOGNAME]; + struct stat fstat; + + // get the logfilename + snprintf( logfilename, MAXLOGNAME, "pppd%04d.log", iKey ); + + // see if the file exists - if not then the status is SS_NOT_STARTED + errcode = stat( logfilename, &fstat ); + if( (errcode == -1) && (errno == ENOENT) ) { + iSessionStatus = SS_NOT_STARTED; + return rv; + } + + // look for the line with the CONNECTED_STRING prefix + match_count = MAXLISTLINES; + ferr = FindMatchingLinesByRawPrefix( logfilename, CONNECTED_STRING, mline, &match_count, &errcode ); + if( ferr != FUE_NONE ) { + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = (int)ferr; + rv.iSystemError = errcode; + return rv; + } + once_connected = ((match_count > 0) ? 1 : 0); + + // look for the line with the DISCONNECTED_STRING prefix + match_count = MAXLISTLINES; + ferr = FindMatchingLinesByRawPrefix( logfilename, DISCONNECTED_STRING, mline, &match_count, &errcode ); + if( ferr != FUE_NONE ) { + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = (int)ferr; + rv.iSystemError = errcode; + return rv; + } + disconnected = ((match_count > 0) ? 1 : 0); + + // set the state based on the log + if( (once_connected == 0) && (disconnected == 0) ) { + iSessionStatus = SS_CONNECTING; + } else if( (once_connected == 1) && (disconnected == 0) ) { + iSessionStatus = SS_CONNECTED; + } else if( (once_connected == 1) && (disconnected == 1) ) { + iSessionStatus = SS_DISCONNECTED; + } else if( (once_connected == 0) && (disconnected == 1) ) { + iSessionStatus = SS_DISCONNECTED; + } + + // done - success + return rv; +} + + +/******************************************************************************* + * + * PRIVATE FUNCTION: CopyFileIntoBuffer + * + ******************************************************************************/ +TResult CSPppcontroller::CopyFileIntoBuffer( char *aFilename, TVarData *aData ) +{ + TResult rv = { ERR_NONE, 0, 0 }; + int err; + int filesize; + int i; + char c; + FILE *fp; + + // check params + assert( aFilename != NULL ); + assert( aData != NULL ); + + // initialise the data to empty + aData->TVarData_val = NULL; + aData->TVarData_len = 0; + + // open the logfile + fp = fopen( aFilename, "rb" ); + if( fp == NULL ) { + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = 0; + rv.iSystemError = errno; + return rv; + } + + // get the file size + fseek( fp, 0, SEEK_END ); + filesize = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + + // if the filesize is zero then just return + if( filesize == 0 ) { + return rv; + } + + // allocate space for the file data + aData->TVarData_val = (char*)calloc( (filesize + 1), 1 ); + assert( aData->TVarData_val != NULL ); + aData->TVarData_len = (filesize + 1); + + // now copy the data + for( i = 0; i < filesize; i++ ) { + + // read one byte + err = fread( &c, 1, 1, fp ); + if( err != 1 ) { + free( aData->TVarData_val ); + aData->TVarData_val = NULL; + aData->TVarData_len = 0; + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = 0; + rv.iSystemError = errno; + fclose( fp ); + return rv; + } + + // save the byte in the buffer + (aData->TVarData_val)[i] = c; + } + + // cleanup and return + fclose( fp ); + return rv; +} + + +/**************************************************************************************** + * + * PRIVATE FUNCTION: GetTokenFromFile + * + ***************************************************************************************/ +TResult CSPppcontroller::GetTokenFromFile( string aPrefix, string *aLine, TMultiMatchSemantics aMultiMatchSemantics ) +{ + TResult rv = { ERR_NONE, 0, 0 }; + TFUError ferr; + char logfilename[MAXLOGNAME]; + char cline[MAXLOGLINELENGTH]; + int mline[MAXLISTLINES], match_count, errcode, entry; + struct stat fstat; + + // check params + assert( aLine != NULL ); + + // get the logfilename + snprintf( logfilename, MAXLOGNAME, "pppd%04d.log", iKey ); + + // fprintf( stderr, "DEBUG: request for lines starting with '%s'\n", aPrefix.c_str() ); + + // see if the file exists - if not then just return - this is NOT an error + errcode = stat( logfilename, &fstat ); + if( (errcode == -1) && (errno == ENOENT) ) { + rv.iStandardResult = ERR_INVALIDARG; + rv.iExtendedCode = 1; + // fprintf( stderr, "DEBUG: file doesn't exist.\n" ); + return rv; + } + + // look for the lines that match the prefix + match_count = MAXLISTLINES; + ferr = FindMatchingLinesByRawPrefix( logfilename, (char*)aPrefix.c_str(), mline, &match_count, &errcode ); + if( ferr != FUE_NONE ) { + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = (int)ferr; + rv.iSystemError = errcode; + // fprintf( stderr, "DEBUG: error parsing logfile.\n" ); + return rv; + } + + // if there is no match then nothing to do + if( match_count == 0 ) { + rv.iStandardResult = ERR_INVALIDARG; + rv.iExtendedCode = 2; + // fprintf( stderr, "DEBUG: no matches.\n" ); + return rv; + } + + // if there are multiple matches then print warning (just for the admin) + if( match_count > 1 ) { + // fprintf( stderr, "WARNING: multiple matches for token \"%s\" in '%s'.\n", aPrefix.c_str(), logfilename ); + } + + // handle multiple matches + if( (aMultiMatchSemantics == MM_ERROR) && (match_count > 1) ) { + rv.iStandardResult = ERR_MULTIPLE_MATCHES_IN_LOG_FILE; + return rv; + } + entry = ((aMultiMatchSemantics == MM_FIRST) ? 0 : (match_count-1)); + + // now get the matching line + ferr = GetLine( logfilename, mline[entry], cline, MAXLOGLINELENGTH, &errcode ); + if( ferr != FUE_NONE ) { + rv.iStandardResult = ERR_LOG_FILE_ERROR; + rv.iExtendedCode = (int)ferr; + rv.iSystemError = errcode; + // fprintf( stderr, "DEBUG: error getting the matching line.\n" ); + return rv; + } + + // copy the line into the passed buffer + (*aLine) = cline; + // fprintf( stderr, "DEBUG: successfully retrieved line '%s'\n", aLine->c_str() ); + + // done - success; + return rv; +} +