--- /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 <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#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;
+}
+