diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/csdagt/script/SSCREXEC.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyprotocols/csdagt/script/SSCREXEC.CPP Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,766 @@ +// Copyright (c) 2003-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: +// NetDial Script Executor +// +// + +/** + @file Sscrexec.cpp +*/ + +#include "SSCREXEC.H" +#include "SIO.H" +#include "SLOGGER.H" +#include "ND_SCR.H" + +_LIT(KPPPProtocolName,"PPP."); + +const TInt KNumErrorVariables=9; +//const TInt KMaxReadFromPctLength=256; +//const TInt KMaxReadFromPctLength8=2*KMaxReadFromPctLength; + +const SErrorVariable ErrorVariables[KNumErrorVariables]= + { + {KErrExitScriptTimeOutString,KErrExitScriptTimeOut}, + {KErrExitLoginFailString,KErrExitLoginFail}, + {KErrExitNoModemString,KErrExitNoModem}, + {KErrExitModemErrorString,KErrExitModemError}, + {KErrExitNoAnswerString,KErrEtelNoAnswer}, + {KErrExitNoCarrierString,KErrEtelNoCarrier}, + {KErrExitNoDialToneString,KErrEtelNoDialTone}, + {KErrExitBusyString,KErrEtelBusyDetected}, + {KErrExitModemInitErrorString,KErrEtelInitialisationFailure}, + }; + +// CScriptExecutor definitons +CScriptExecutor* CScriptExecutor::NewL(CNetDialScript* aScript,const TDesC& aCommChannel, TInt aScriptLength) + +/** +2 phased constructor for CScriptExecutor, first phase. + +@param aScript a pointer to used script. +@param aCommPort a reference to COMM port. +@param aScriptLength is lenght for used script. +@exception Leaves if ConstructL() leaves, or not enough memory is available. +@return a new CScriptExecutor object. +*/ + { + CScriptExecutor* p=new(ELeave) CScriptExecutor(aScript); + CleanupStack::PushL(p); + p->ConstructL(aCommChannel, aScriptLength); + CleanupStack::Pop(); + return p; + } + +CScriptExecutor::CScriptExecutor(CNetDialScript* aScript) + : CActive(EPriorityStandard), iScript(aScript), iInitializationFlag(EFalse),iServerRetransmitLoginPromptStatus(EFirstWaitCommand) +/** +Constructor for CScriptExecutor, used in the first phase of construction. + +@param aScript a pointer to used script. +*/ + {} + +void CScriptExecutor::ConstructL(const TDesC& aCommChannel, TInt aScriptLength) +/** +Instantiate member variables. + +@param aCommPort a reference to COMM port. +@param aScriptLength is script lenght. +*/ + { + CActiveScheduler::Add(this); + + iScriptIO=CScriptIO::NewL(this, aCommChannel); + +// create script reader if script length is greater than zero + if (aScriptLength>0) + { + iScriptReader=CScriptReader::NewL(aScriptLength); + TScriptStatus scriptStatus=iScriptReader->ScriptStatus(); + iVarMan=CScriptVarMan::NewL(); + iCharConv=CScriptCharacterConverter::NewL(); + iLabelMan=CScriptLabelMan::NewL(); +// Construct Command Managers + iWaitCommand=CWaitCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv,iScriptIO,iLabelMan, this); + iCommands[0]=iWaitCommand; + iCommands[1]=CSendCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv,iScriptIO); + iReadCommand=CReadPCTCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv,this); + iCommands[2]=iReadCommand; + iLoopCommand=CLoopCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv); + iCommands[3]=iLoopCommand; + iCommands[4]=CExitCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv); + iGotoCommand=CGotoCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv,iLabelMan); + iCommands[5]=iGotoCommand; + iCommands[6]=CSetCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv); + iCommands[7]=CDTRCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv,iScriptIO); + iCommands[8]=CCharMapCommand::NewL(scriptStatus,iScriptReader,iVarMan,iCharConv); +// Add Error Variables + __ASSERT_DEBUG((sizeof(ErrorVariables)/sizeof(SErrorVariable))==KNumErrorVariables,NetDialPanic(ENumOfVariablesIncorrect)); + TInt i; + for (i=0; iAddVariableL(TPtrC(ErrorVariables[i].iString),ErrorVariables[i].iValue); + } + else + { + iScriptReader=NULL; + iVarMan=NULL; + iCharConv=NULL; + iLabelMan=NULL; + iWaitCommand=NULL; + iReadCommand=NULL; + iGotoCommand=NULL; + iLoopCommand=NULL; + TInt i; + for (i=0; iSetScript(aScript); + iLoopCommand->Loop(EFalse); + } + +void CScriptExecutor::ScanScriptL() +/** +Scans script for READ command. +*/ + { + __FLOG_STMT(_LIT8(logString1,"Script:\tScanning");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString1()); + + __ASSERT_DEBUG(iScriptReader!=NULL, NetDialPanic(ENullScriptReader)); + + iReadFound=EFalse; + TInt ret=KErrNone; + iScriptReader->SetLoggingOff(); + while (ret!=KErrScriptCompleted) + { + TRAP(ret,(iReadFound=iReadCommand->CheckReadL())); + if (iReadFound || ret!=KErrNone) + break; + ret=iScriptReader->GetNextLine(); + } + + if (iReadFound) + { + __FLOG_STMT(_LIT8(logString2,"Script:\tFound Read");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString2()); + } + else + { + __FLOG_STMT(_LIT8(logString3,"Script:\tDid Not Find Read");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString3()); + } + + User::LeaveIfError(iScriptReader->Reset()); + } + +void CScriptExecutor::RunScript() +/** +Runs script. +*/ + { + iScriptIO->Start(); + iStatus=KRequestPending; + SetActive(); + } + +void CScriptExecutor::ProcessScript() +/** +Processes script line by line +*/ + { + TRAPD(ret,ProcessNextLinesL()); + if(ret!=KErrNone) + { + CompletedScript(ret); + } + } + +void CScriptExecutor::ProcessNextLinesL() +/** +If read/write not pending clear previous command. Toggle skip mode if necessary then +either parse label or jump to beginning of loop or parse command as necessary. +*/ + { + __ASSERT_DEBUG(iScriptReader!=NULL, NetDialPanic(ENullScriptReader)); + + while(!(iScriptIO->RWPending())&& !(iReadFromPctPending)) + { + CleanupLastCommand(); + iGotoCommand->ServiceSkipReqs(); + if(iGotoCommand->ParseLabelL()) + continue; + if(iLoopCommand->CheckLoopL()) + continue; + + TInt i; + for(i=0;iParseL()) + { + iLastCommand=iCommands[i]; + break; + } + } + if(iLastCommand==NULL) + User::Leave(KErrIllegalCommand); + } + } + +void CScriptExecutor::CompletedWrite(TInt aStatus) +/** +Stops script if aStatus is an error, otherwise continue to process. + +@param aStatus is status passed from caller. +*/ + { + if((aStatus==KErrTimedOut)&&(iInitializationFlag)) + CompletedScript(KErrExitNoModem); + else if((aStatus==KErrNone)||(aStatus==KErrTimedOut)) + { + if (iDataToWrite.Length()>0 && !iScriptIO->WritePending()) + { + iScriptIO->Write(iDataToWrite); + iDataToWrite.SetLength(0); + } + else + { + iInitializationFlag=EFalse; + if(iServerRetransmitLoginPromptStatus == ESendingCR) + { + // The previous WAIT for a login prompt timed out and we sent + // a 0x0d to encourage the server to resend the login + // So wait for the login prompt again + iServerRetransmitLoginPromptStatus = ESecondWaitCommand; + TRAPD(ret, iDummySearchArray=new(ELeave) CLabelSearchArray(1)); + if(ret != KErrNone) + { + iServerRetransmitLoginPromptStatus = EDeactivated; + ProcessScript(); + } + else iScriptIO->Read(iDummySearchArray, iRetransmitLoginTimeOut); + } + else ProcessScript(); + } + } + else + CompletedScript(aStatus); + } + +void CScriptExecutor::CompletedReadL(TInt aStatus,TInt aIndex) +/** +Stops script if there is an error, or otherwise continue to process or jump to +label as ncessary. Ignore comms line fail errors. + +@param aStatus is passed from caller. +@param aIndex is index for label. +*/ + { + __ASSERT_DEBUG(iScriptReader!=NULL, NetDialPanic(ENullScriptReader)); + + if(iServerRetransmitLoginPromptStatus == ESecondWaitCommand) + { + // We must have sent a 0x0d to try and force the server to retransmit the + // login prompt + // Delete the dummy search array and stop the RetransmitLogin mechanism since + // irrespective of the outcome of the read, we're not going to send any more 0x0d + delete iDummySearchArray; + iDummySearchArray=NULL; + iServerRetransmitLoginPromptStatus=EDeactivated; + } + + if(iInitializationFlag) + { + iInitializationFlag=EFalse; + ProcessScript(); + } + else + { + switch(aStatus) + { + case KErrNone: + { + iServerRetransmitLoginPromptStatus=EDeactivated; + TPtrC label=iWaitCommand->LabelFromIndexL(aIndex); + iGotoCommand->Goto(label); + } + ProcessScript(); + break; + case KErrTimedOut: + // If the very first WAIT script command fails it's possible that the + // server sent the login prompt before MM.TSY had finished with + // the serial port + // If so, we can send a 0x0d (Carriage Return) to wake it up + // and re-transmit the login prompt + if(iServerRetransmitLoginPromptStatus == EFirstWaitCommand) + { + // Transmit a 0x0d to the server + iServerRetransmitLoginPromptStatus=ESendingCR; + TBuf8<1> CarriageReturn; + CarriageReturn.SetLength(1); + CarriageReturn[0]=0x0d; + TPtrC8 CR(CarriageReturn); + iScriptIO->Write(CR); + break; + } + iServerRetransmitLoginPromptStatus=EDeactivated; + ProcessScript(); + break; + case KErrCommsLineFail: + iServerRetransmitLoginPromptStatus=EDeactivated; + ProcessScript(); + break; + default: + iServerRetransmitLoginPromptStatus=EDeactivated; + CompletedScript(aStatus); + break; + } + } + } + +void CScriptExecutor::CompletedScript(TInt aStatus) +/** +If aStatus is not an error, check that not still looking for a label. +Convert internal error to public error and finish. + +@param aStatus is passed from caller. +*/ + { + // Safety check - this method may be called from multiple locations, + // possibly resulting in more than one call for the same event. + if (iStatus==KRequestPending) + { + __ASSERT_DEBUG(iScriptReader!=NULL, NetDialPanic(ENullScriptReader)); + + if(aStatus==KErrScriptCompleted) + aStatus=KErrNone; + + TInt error=aStatus; + + __FLOG_STMT(_LIT8(logString,"Script:\tScript Completed With Error %d");) + __FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue(logString()),error); + + ConvertScriptError(error); + PctCancelAndClose(); + + CleanupLastCommand(); + iLoopCommand->Loop(EFalse); + + iScriptIO->Cancel(); + + TRequestStatus* statusPtr=&iStatus; + User::RequestComplete(statusPtr,error); + } + } + +void CScriptExecutor::DoCancel() +/** +Cancel read/write, and callbacks and cleanup last command +*/ + { + if(iServerRetransmitLoginPromptStatus == ESecondWaitCommand) + { + delete iDummySearchArray; + iDummySearchArray=NULL; + iServerRetransmitLoginPromptStatus=EDeactivated; + } + + CleanupLastCommand(); + iScriptIO->Cancel(); + PctCancelAndClose(); + + TRequestStatus* statusPtr=&iStatus; + User::RequestComplete(statusPtr,KErrCancel); + iScript->ScriptOperationComplete(KErrCancel); + } + +void CScriptExecutor::Disconnect() +/** +Disconect. +*/ + { + iScriptIO->Disconnect(); + } + +void CScriptExecutor::ReConfigureAndCancelCommPort(TRequestStatus& aStatus) +/** +Call ReConfigureAndCancelPort() from script IO handler. +*/ + { + iScriptIO->ReConfigureAndCancelPort(aStatus); + } + + +void CScriptExecutor::CloseScript() +/** +Close script. +*/ + { + __FLOG_STMT(_LIT8(logString,"Script:\tClosing");) + __FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString()); + if (iScriptReader!=NULL) + iScriptReader->Reset(); // ignore error + } + +void CScriptExecutor::Close() +/** +Cleanup last command, close script file, and delete all variables and labels from lists. +*/ + { + CleanupLastCommand(); + + if (iLoopCommand!=NULL) + iLoopCommand->Loop(EFalse); + + PctCancelAndClose(); + CloseScript(); + + if (iVarMan!=NULL) + iVarMan->DeleteAll(); + if (iLabelMan!=NULL) + iLabelMan->DeleteAll(); + } + +void CScriptExecutor::SetRetransmittedLoginTimeout(TReal& aRetransmitLoginTimeOut) +/** +Remember the timeout used on the wait statement that is currently executing + +@param aRetransmitLoginTimeOut is passed from CWaitCommand. +*/ + { + iRetransmitLoginTimeOut = aRetransmitLoginTimeOut; + if(iServerRetransmitLoginPromptStatus == EFirstWaitCommand) + { + // This is the first time we are going to wait for anything + // If we wait too long, the TCP/IP stack will time out so better not + // wait more than say 30 seconds the first time around + if(aRetransmitLoginTimeOut > 30) + aRetransmitLoginTimeOut = 30; + } + } + +TInt CScriptExecutor::WritePct(const TDesC8& aBuffer) +/** +CScriptIO calls to write incoming data to PCT. Convert the 8 bit data to +default character set and pass up to the dialog server. + +@param aBuffer a reference to buffer to be written. +@return error code from WritePct() or leave code if ConvertFromDefaultL() leaves. +*/ + { + __ASSERT_DEBUG(aBuffer.Length()<=KRxBufferSize, User::Invariant()); + TBuf convertedBuf; + TRAPD(ret, iCharConv->ConvertFromDefaultL(aBuffer,convertedBuf)); + if (ret == KErrNone) + { + return iScript->WritePct(convertedBuf); + } + else + { + return ret; + } + } + +void CScriptExecutor::SetReadPctBuffer() +/** +This is for the test dialog server only because we can't type in the value. +*/ + { + iReadBuffer.SetLength(0); + iReadReq++; + if (iReadReq==1) + iReadBuffer.Copy(iLoginName.Left(Min(iLoginName.Length(),3))); + else if (iReadReq==2) + { + if (iLoginName.Length()>3) + iReadBuffer.Copy(iLoginName.Right(iLoginName.Length()-3)); + iReadBuffer.Append('.'); + } + else if (iReadReq==3) + iReadBuffer.Copy(iLoginPass.Left(Min(iLoginPass.Length(),3))); + else if (iReadReq==4) + { + if (iLoginPass.Length()>3) + iReadBuffer.Copy(iLoginPass.Right(iLoginPass.Length()-3)); + iReadBuffer.Append('.'); + } + else if (iReadReq==5) + iReadBuffer.Copy(KPPPProtocolName); + else + iReadBuffer.Zero(); + } + +void CScriptExecutor::ReadPct() +/** +Read PCT. +*/ + { + SetReadPctBuffer(); + iScript->ReadPct(iReadBuffer); + iScriptIO->ReadEcho(); + iReadFromPctPending=ETrue; + } + +void CScriptExecutor::ReadPctComplete(TInt aStatus) +/** +Data recived from PCT to be written to port. For unicode - need to know the +character set it should be sent in and convert to this from UNICODE (or whatever +PCT uses). Pass to the Script IO as 8 bit. + +@param aStatus passed from caller. +*/ + { + __ASSERT_ALWAYS(iReadFromPctPending, NetDialPanic(EIllegalReadPctComplete)); + + if (aStatus==KErrCancel) // means that NetDial has called Cancel() or ClosePct() while read request outstanding + { + iReadFromPctPending=EFalse; + return; + } + + if (aStatus!=KErrNone) // something other than KErrCancel + { + iScriptIO->ReadEchoCancel(); + iReadFromPctPending=EFalse; + CompletedScript(aStatus); + return; + } + + HBufC8* buf=NULL; + TRAPD(ret,buf=iCharConv->ConvertL(iReadBuffer,iReadCommand->CharSet())); + if(ret!=KErrNone) + { + iScriptIO->ReadEchoCancel(); + iReadFromPctPending=EFalse; + CompletedScript(ret); + return; + } + TPtr8 eightBitBuf(buf->Des()); +#ifdef __FLOG_ACTIVE + _LIT(logString,"Script:\tRead %S from PCT"); + TBuf16 temp; + temp.Copy(eightBitBuf.Left(Min(eightBitBuf.Length(),KLogBufferSize))); + __FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue(logString()),&temp); +#endif + TInt end=iReadBuffer.Locate(KCarriageReturn); + TInt spaceInBuffer=iDataToWrite.MaxLength()-iDataToWrite.Length(); + + if (end<0) + iDataToWrite.Append(eightBitBuf.Left(Min(spaceInBuffer,eightBitBuf.Length()))); + else + iDataToWrite.Append(eightBitBuf.Left(Min(spaceInBuffer,end+1))); + + if (!iScriptIO->WritePending()) + { + iScriptIO->Write(iDataToWrite); + iDataToWrite.SetLength(0); // clear buffer so we know it's been sent + } + + if (end<0) + { + SetReadPctBuffer(); + iScript->ReadPct(iReadBuffer); + } + else + { + iScriptIO->ReadEchoCancel(); + iReadFromPctPending=EFalse; + } + + delete buf; + } + +void CScriptExecutor::DestroyPctNotificationReceived(TInt aStatus) +/** +PCT destroyed. Assume KErrNone means destroyed by user / someone else and +otherwise we destroyed it. + +@param aStatus is passed from caller. +*/ + { + if (aStatus==KErrNone) // user cancelled + { + iScriptIO->Cancel(); + iScript->CancelDialogServer(); // cancels any outstanding reads + CompletedScript(KErrCancel); // this will close the PCT + } + else + iScript->ClosePct(); // NetDial is in charge of closing the PCT whatever happens + + } + +void CScriptExecutor::PctCancelAndClose() +/** +Cancel any outstanding requests and cancel the active object waiting on the +destroy notification) and close the pct +*/ + { + iScript->CancelDialogServer(); + iScript->ClosePct(); + } + +void CScriptExecutor::SetVariableL(const TDesC& aName, const TDesC& aContent) +/** +Add variable with name aName and content aContent to list + +@param aName a reference to variable name. +@param aContent a reference to content. +*/ + { + iVarMan->AddVariableL(aName,aContent); + } + +void CScriptExecutor::ConfigureCommPort(TRequestStatus& aStatus, const TCommConfig& aConfiguration) +/** +Configure COMM port. + +@param aConfiguration a reference to confiquration +@return error code from ConfigurePort(). +*/ + { + iScriptIO->ConfigurePort(aStatus, aConfiguration); + } + +void CScriptExecutor::DropSignals(TRequestStatus& aStatus) +/** +Drop signals on COMM port. +*/ + { + iScriptIO->DropSignals(aStatus); + } + +void CScriptExecutor::CancelConfigureCommPort() +/** +Cancel Configure COMM port. +*/ + { + iScriptIO->CancelConfigurePort(); + } + +void CScriptExecutor::DropDTR(TRequestStatus* aStatusPtr) +/** +Drop DTR. +*/ + { + iScriptIO->DropDTR(aStatusPtr); + } + +void CScriptExecutor::CreateChannel(TRequestStatus& aStatus) + { + ASSERT(iScriptIO); + iScriptIO->CreateChannel(aStatus); + } + +void CScriptExecutor::CancelCreateChannel() + { + ASSERT(iScriptIO); + iScriptIO->CancelCreateChannel(); + } + +void CScriptExecutor::ShutdownChannel(TRequestStatus& aStatus) + { + ASSERT(iScriptIO); + iScriptIO->ShutdownChannel(aStatus); + } + +TInt CScriptExecutor::GetExcessData(TDes8& aBuffer) +/** +Get excess data. + +@param aBuffer a reference to excess data. +*/ + { + return iScriptIO->GetExcessData(aBuffer); + } + +void CScriptExecutor::ConvertScriptError(TInt& aError) const +/** +Convert internal errors to KErrExitScriptError. + +@param a reference to error code. New value is passed back by using it. +*/ + { + if(aErrorCleanup(); + iLastCommand=NULL; + } + } + +void CScriptExecutor::RunL() +/** +Complete script operation. +*/ + { + iScript->ScriptOperationComplete(iStatus.Int()); + } +