Fixed Send Message Default Handler routines according to Dejana's request.
Removed some unnecessary funtions.
// 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; i<KNumErrorVariables; i++)
iVarMan->AddVariableL(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; i<KNumCommands; i++)
iCommands[i]=NULL;
}
// PCT stuff
iReadFound=EFalse;
iReadReq=0;
iReadFromPctPending=EFalse;
iDataToWrite.SetLength(0);
}
CScriptExecutor::~CScriptExecutor()
/**
Destructor.
Cancels active requests and deletes members.
*/
{
Cancel();
delete iDummySearchArray;
delete iScriptIO;
delete iScriptReader;
delete iVarMan;
delete iCharConv;
delete iLabelMan;
for(TInt i=0;i<KNumCommands ;i++)
delete iCommands[i];
}
void CScriptExecutor::SetLoginParams(const TDesC& aLoginName,const TDesC& aLoginPass)
/**
Sets login parameters.
@param aLoginName a reference to login name.
@param aLoginPass a reference to login password.
*/
{
iLoginName.Copy(aLoginName);
iLoginPass.Copy(aLoginPass);
}
void CScriptExecutor::SetScript(const TDesC& aScript)
/**
Sets script.
@param aScript a reference to login name.
*/
{
__ASSERT_DEBUG(iLastCommand==NULL, NetDialPanic(ELastCommandNotNull));
__ASSERT_DEBUG(iScriptReader!=NULL, NetDialPanic(ENullScriptReader));
__FLOG_STMT(_LIT8(logString,"Script:\tBeginning");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString());
iScriptReader->SetScript(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;i<KNumCommands;i++)
{
if(iCommands[i]->ParseL())
{
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<const TDesC8>(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<KRxBufferSize> 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<KLogBufferSize> temp;
temp.Copy(eightBitBuf.Left(Min(eightBitBuf.Length(),KLogBufferSize)));
__FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue<const TDesC>(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(aError<KNetdialInternalErrorBase)
aError=KErrExitScriptError;
}
void CScriptExecutor::CleanupLastCommand()
/**
Cleanup last command.
*/
{
if(iLastCommand!=NULL)
{
iLastCommand->Cleanup();
iLastCommand=NULL;
}
}
void CScriptExecutor::RunL()
/**
Complete script operation.
*/
{
iScript->ScriptOperationComplete(iStatus.Int());
}