// 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:///** @file PsdStates.cpp*/#include <comms-infras/cagentsmbase.h>#include <etelpckt.h>#include <connectprog.h> // for circuit-switched progress enums#include <netconerror.h>#include "psdlogger.h"#include "psdstates.h"#include "psdagt.h"#include "psdprog.h"#include "debuglogger.h"#include <logengevents.h>CPsdOutInit::CPsdOutInit(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CPsdInitBase(aObserver,aPsdSM,aDb)/**Constructor*/ {}CPsdOutInit::~CPsdOutInit()/**Destructor*/ {}CAgentStateBase* CPsdOutInit::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { if (iStatus==KErrNone && aContinue) // which it will be if there has been no error so far return new (ELeave) CPsdOutCheckConfig(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }CPsdOutCheckConfig::CPsdOutCheckConfig(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CPsdCheckConfig(aObserver,aPsdSM,aDb)/**Constructor*/ {}CPsdOutCheckConfig::~CPsdOutCheckConfig()/**Destructor*/ {}CAgentStateBase* CPsdOutCheckConfig::NextStateL(TBool aContinue)/**move the state machine to the next state function creates the next state in the state machine.@see CAgentStateBase* CPsdOutInit::NextStateL(TBool aContinue)*/ { if (iStatus==KErrNone && aContinue) // which it will be if there has been no error so far return new (ELeave) CPsdNetworkCheck(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }#ifndef INCOMING_NOT_SUPORTEDCPsdInInit::CPsdInInit(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CPsdInitBase(aObserver,aPsdSM,aDb)/**Constructor*/ {}CPsdInInit::~CPsdInInit()/**Destructor*/ {}void CPsdInInit::DoStartStateL()/**Internal function that initialises the state machine for an incoming connectionoverriding the virtual function in the base classCheck first of all whether we are allowed to do inbound*/ { TBool allowed = iDbPsd->IsIncomingAllowedL(); if (!allowed) User::Leave(KErrAccessDenied); CPsdInitBase::DoStartStateL(); } CAgentStateBase* CPsdInInit::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@see CAgentStateBase* CPsdOutInit::NextStateL(TBool aContinue)*/ { if (iStatus==KErrNone && aContinue) // which it will be if there has been no error so far return new (ELeave) CPsdInCheckConfig(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }CPsdInCheckConfig::CPsdInCheckConfig(MAgentObserver* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CPsdCheckConfig(aObserver,aPsdSM,aDb)/**Constructor*/ {}CPsdInCheckConfig::~CPsdInCheckConfig()/**Destructor*/ {}CAgentStateBase* CPsdInCheckConfig::NextStateL(TBool aContinue)/**@see CAgentStateBase* CPsdOutInit::NextStateL(TBool aContinue)*/ { if (iStatus==KErrNone && aContinue) // which it will be if there has been no error so far return new (ELeave) CPsdWaitForIncoming(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }#endif // #ifndef INCOMING_NOT_SUPORTEDCPsdInitBase::CPsdInitBase(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdInitBase::~CPsdInitBase()/**Desctructor*/ { Cancel(); }void CPsdInitBase::StartState() /**Function called by the genconn state machine framework to start the state*/ { TRAPD(ret,DoStartStateL()); if (ret!=KErrNone) JumpToRunl(ret); }void CPsdInitBase::DoStartStateL()/**Internal function that performs all the initialisation of the common resourcesheld by the state machine for use by subsequent states*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tInitialising");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1()); iSMObserver->PreventConnectionRetries(); // // PSD AGX does not allow any more connection retries. It assumes that GenConn has // already done the packet network availability check, so we would only get to this stage // should there be packet network (or if it was unknown). RTelServer& etel = iSM->TelServer(); RPhone& phone = iSM->Phone(); RPacketService& packetNetwork = iSM->PacketNetwork(); User::LeaveIfError(etel.Connect()); TBuf<KCommsDbSvrMaxFieldLength> tsyName; iSM->BaseEnv().Db()->GetTsyNameL(tsyName); User::LeaveIfError(etel.LoadPhoneModule(tsyName)); iSM->SetTsyLoaded(ETrue); User::LeaveIfError(etel.SetExtendedErrorGranularity(RTelServer::EErrorExtended)); RTelServer::TPhoneInfo info; TInt r=tsyName.Locate('.'); if (r!=KErrNotFound) tsyName.SetLength(r); GetPhoneInfoL(tsyName,info); // If this leaves, TSY should be unloaded // when RTelServer handle is closed. User::LeaveIfError(phone.Open(etel,info.iName)); User::LeaveIfError(packetNetwork.Open(phone)); // RPhone::TStatus status; User::LeaveIfError(phone.GetStatus(status)); if (status.iModemDetected==RPhone::EDetectedNotPresent || status.iModemDetected==RPhone::EDetectedUnknown) { phone.Initialise(iStatus); SetActive(); } else // status.iModemDetected==RPhone::EDetectedPresent JumpToRunl(KErrNone); }void CPsdInitBase::GetPhoneInfoL(const TDesC& aLoadedTsyName, RTelServer::TPhoneInfo& aInfo)/**Function obtains the info on the phone object implemented in the TSYAssumes aloadedTsyName has no ".TSY" appendageFinds the phone information for the TSY just loaded. Assumes just one phone in that TSY - or that every phone in it is equally useful.@param name of the loaded Tsy.@param information about the phone.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); TInt count; User::LeaveIfError(iSM->TelServer().EnumeratePhones(count)); if (count<=0) User::Leave(KErrNotFound); TBool found=EFalse; for (TInt i=0; i<count; i++) { TBuf<KCommsDbSvrMaxFieldLength> currentTsyName; User::LeaveIfError(iSM->TelServer().GetTsyName(i,currentTsyName)); TInt r=currentTsyName.Locate('.'); if (r!=KErrNotFound) currentTsyName.SetLength(r); if (currentTsyName.CompareF(aLoadedTsyName)==KErrNone) { User::LeaveIfError(iSM->TelServer().GetPhoneInfo(i,aInfo)); found=ETrue; break; } } if (!found) User::Leave(KErrNotFound); }void CPsdInitBase::RunL()/**Complete state for the initialisation state for both incomming and outgoing connections.*/ { __FLOG_STMT(_LIT8(logString2,"Packet Data:\tInitialised");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString2()); if (iStatus!=KErrNone) iSMObserver->ConnectionComplete(EPsdStartingConfiguration,iStatus.Int()); // correct progress? else iSM->BaseEnv().CompleteState(KErrNone); // this tells the SM to move onto the next state }void CPsdInitBase::DoCancel()/**Cancell the asynchronous request of initialisation state for both incomming and outgoing connections.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); iSM->Phone().InitialiseCancel(); }CPsdCheckConfig::CPsdCheckConfig(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ {}CPsdCheckConfig::~CPsdCheckConfig()/**Destructor*/ { Cancel(); }void CPsdCheckConfig::StartState()/**Start checking Configuration states.*/ { JumpToRunl(KErrNone); }void CPsdCheckConfig::DoInitL() { RPacketService& packetNetwork = iSM->PacketNetwork(); const CPsdContextConfig& config = iSM->Config(); if(!config.IsConfigSupportedL(packetNetwork,iSM->Direction()) ) { User::Leave(KErrNotSupported); } __FLOG_STMT(_LIT8(logString2,"Packet Data:\tChecked Config");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString2()); }void CPsdCheckConfig::RunL()/**Complete state for the config checking state for both incomming and outgoing connections.*/ { TRAPD(ret,DoInitL()); iStatus=ret; if (iStatus!=KErrNone) iSMObserver->ConnectionComplete(EPsdStartingConfiguration,ret); // correct progress? else iSM->BaseEnv().CompleteState(KErrNone); // this tells the SM to move onto the next state }void CPsdCheckConfig::DoCancel()/**Need do nothing since StartState() already triggered the request status.*/ {}CPsdNetworkCheck::CPsdNetworkCheck(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdNetworkCheck::~CPsdNetworkCheck()/**Destructor*/ { Cancel(); }void CPsdNetworkCheck::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tChecking network availability");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1()); iSubState = EGettingInitialStatus; iSM->PacketNetwork().GetNtwkRegStatus(iStatus,iRegStatus); SetActive(); }void CPsdNetworkCheck::DoNetworkCheck()/**Checking for Network*/ { __ASSERT_DEBUG(iSMObserver,User::Invariant()); if (iRegStatus==RPacketService::ERegistrationDenied || iRegStatus==RPacketService::ENotRegisteredNotSearching || iRegStatus==RPacketService::ENotRegisteredAndNotAvailable) { __FLOG_STMT(_LIT8(logString1,"Packet Data:\tNo network");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1()); JumpToRunl(KErrNetConNoGPRSNetwork); return; } if (iRegStatus==RPacketService::ERegisteredOnHomeNetwork || iRegStatus==RPacketService::ERegisteredRoaming || iRegStatus==RPacketService::ENotRegisteredButAvailable || iRegStatus==RPacketService::EUnknown) { __FLOG_STMT(_LIT8(logString1,"Packet Data:\tReg status %d. Proceeding");) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),iRegStatus); iSM->BaseEnv().CompleteState(KErrNone); return; } __ASSERT_ALWAYS(iRegStatus==RPacketService::ENotRegisteredSearching,PanicAgt(EPsdInvalidNtwkRegistration)); iSM->PacketNetwork().NotifyChangeOfNtwkRegStatus(iStatus,iRegStatus); SetActive(); }void CPsdNetworkCheck::RunL()/**iRegStatus should have been updated, if aError is KErrNoneComplete Connection for the Network Check state.*/ { if(iSubState == EGettingInitialStatus) { if(iStatus==KErrNotSupported) //tsy could not provide the information { iRegStatus=RPacketService::EUnknown; iStatus=KErrNone; } iSubState = EWaitingForStatusChange; } if (iStatus==KErrNone) DoNetworkCheck(); else iSMObserver->ConnectionComplete(EPsdStartingConfiguration,iStatus.Int()); }void CPsdNetworkCheck::DoCancel()/**Cancell Asynchronous request of network check state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); iSM->PacketNetwork().CancelAsyncRequest(EPacketNotifyChangeOfNtwkRegStatus); }CAgentStateBase* CPsdNetworkCheck::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@see CAgentStateBase* CPsdOutInit::NextStateL(TBool aContinue).*/ { if (iStatus==KErrNone && aContinue) return new (ELeave) CPsdCreateContext(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }#ifndef INCOMING_NOT_SUPORTEDCPsdWaitForIncoming::CPsdWaitForIncoming(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdWaitForIncoming::~CPsdWaitForIncoming()/**Destructor*/ { Cancel(); }void CPsdWaitForIncoming::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tWaiting for incoming Packet request");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSM->PacketNetwork().NotifyContextActivationRequested(iStatus,iPdpTypeRequested,iAddressRequested); SetActive(); }void CPsdWaitForIncoming::RunL()/**Rejects any incoming request for an IP address that isn't in our Incoming context configComplete Connection for wait for incomming state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); if (iStatus==KErrNone) { __FLOG_STMT(_LIT8(logString1,"Packet Data:\tReceived network context activation request");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); if(iSM->Config().QueryIfIncommingConnectionAcceptable(iPdpTypeRequested,iAddressRequested) ) { iSMObserver->UpdateProgress(EPsdAnsweringIncoming,KErrNone); TInt ret = iSMObserver->IncomingConnectionReceived(); // to switch NIFMAN to connecting // if this returns an error, it means NIFMAN is already // connected (this can only happen in the "window" // during callback if (ret==KErrNone) iSM->BaseEnv().CompleteState(KErrNone); else { iSM->PacketNetwork().RejectActivationRequest(); StartState(); } } else // wrong address { iSM->PacketNetwork().RejectActivationRequest(); // how long will this take? Should it be // asynchronous? StartState(); } } else iSMObserver->ConnectionComplete(EPsdAnsweringIncoming,iStatus.Int()); }void CPsdWaitForIncoming::DoCancel()/**Cancell Asynchronous request of wait for incomming state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); iSM->PacketNetwork().CancelAsyncRequest(EPacketNotifyContextActivationRequested); }CAgentStateBase* CPsdWaitForIncoming::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machineAssumes cancelling a notification will result in KErrCancel being passed back in iStatus@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { if (iStatus==KErrNone && aContinue) return new (ELeave) CPsdCreateContext(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }#endif // #ifndef INCOMING_NOT_SUPORTEDCPsdCreateContext::CPsdCreateContext(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdCreateContext::~CPsdCreateContext()/**Destructor*/ { Cancel(); }void CPsdCreateContext::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tCreating context");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); RPacketService& packetNetwork = iSM->PacketNetwork(); RPacketContext& context = iSM->Context(); TName name; TInt ret = context.OpenNewContext(packetNetwork,name); if (ret==KErrNone) { iSMObserver->UpdateProgress(EPsdStartingConfiguration,KErrNone); context.SetConfig(iStatus,iSM->Config().PackedConfig()); SetActive(); } else JumpToRunl(ret); }void CPsdCreateContext::RunL()/**Don't want to do any processing after SetConfig, just move to next state.Complete Connection for Create Context state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tCompleted with error %d");) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),iStatus.Int()); if (iStatus==KErrNone) { // Have added new configure qos state that follows this one // therefore don't report config completion until that state has finished iSM->BaseEnv().CompleteState(KErrNone); } else { // There is now another configuration state so we are still in starting configuration now iSMObserver->ConnectionComplete(EPsdStartingConfiguration,iStatus.Int()); } }void CPsdCreateContext::DoCancel()/**Cancell Asynchronous request of create context state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); iSM->Context().CancelAsyncRequest(EPacketContextSetConfig); }CAgentStateBase* CPsdCreateContext::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machineiStatus will be KErrNone if there has been no error so far. If the state has been cancelled,iStatus should be KErrCancel. (can we rely on this?)@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { if (iStatus==KErrNone && aContinue) // New state return new (ELeave) CPsdCreateQoS(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }CPsdCreateQoS::CPsdCreateQoS(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdCreateQoS::~CPsdCreateQoS()/**Destructor*/ { Cancel(); }void CPsdCreateQoS::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tCreating QoS");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); RPacketContext& context = iSM->Context(); RPacketQoS& qoS = iSM->QoS(); TName name; TInt ret = qoS.OpenNewQoS(context,name); if (ret==KErrNone) { qoS.SetProfileParameters(iStatus,iSM->QoSConfig().PackedQoSConfig()); SetActive(); } else if (ret == KErrNotSupported)//the TSY doesn't support QoS -> flag it { iSM->SetQoSSupported(EFalse); JumpToRunl(KErrNone); } else JumpToRunl(ret); }void CPsdCreateQoS::RunL()/**Don't want to do any processing after SetProfileParameters, just move to next state.Complete Connection for Create QoS state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tCompleted with error %d");) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),iStatus.Int()); if (iStatus==KErrNone) { iSMObserver->UpdateProgress(EPsdFinishedConfiguration,KErrNone); iSM->BaseEnv().CompleteState(KErrNone); } else iSMObserver->ConnectionComplete(EPsdFinishedConfiguration,iStatus.Int()); }void CPsdCreateQoS::DoCancel()/**Cancell Asynchronous request of create QoS state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); if(iSM->IsQoSSupported()) iSM->QoS().CancelAsyncRequest(EPacketQoSSetProfileParams); }CAgentStateBase* CPsdCreateQoS::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machineiStatus will be KErrNone if there has been no error so far. If the state has been cancelled,iStatus should be KErrCancel. (can we rely on this?)@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { if (iStatus==KErrNone && aContinue) return new (ELeave) CPsdActivateContext(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }CPsdActivateContext::CPsdActivateContext(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdActivateContext::~CPsdActivateContext()/**Destructor*/ { Cancel(); }void CPsdActivateContext::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tActivating context");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSMObserver->UpdateProgress(EPsdStartingActivation,KErrNone); // Check if the context is already active since in the reconnect case it may be RPacketContext::TContextStatus contextStatus; iSM->Context().GetStatus(contextStatus); iSubState = EActivatingContext; if( !((contextStatus==RPacketContext::EStatusActive) ||(contextStatus==RPacketContext::EStatusSuspended) ||(contextStatus==RPacketContext::EStatusActivating)) ) { // Context not active so activate it iSM->Context().Activate(iStatus); SetActive(); } else { // Context already active so move to the RunL JumpToRunl(KErrNone); } }void CPsdActivateContext::RunL()/**Complete Connection for Activate Context state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __ASSERT_DEBUG(iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tCompleted with error %d");) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),iStatus.Int()); if( (iSubState==EActivatingContext&&(iStatus==KErrNone || iStatus==KErrNotSupported) ) ||(iSubState==ELoaningCommPort&&iStatus==KErrNone) ) { if(iSubState==EActivatingContext) { iSM->Context().LoanCommPort(iStatus,iCommport); SetActive(); iSubState=ELoaningCommPort; } else { // Substate == ELoaningCommPort TRAPD(ret,iSM->BaseEnv().Db()->SetCommPortL(iCommport)); if (ret!=KErrNone) { iStatus=ret; iSMObserver->ConnectionComplete(EPsdFinishedActivation,iStatus.Int()); } else { iSMObserver->UpdateProgress(EPsdFinishedActivation,KErrNone);// may want to do this when it really // activates __FLOG_STMT(_LIT8(logString1,"Packet Data:\tHanding control to PPP");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSMObserver->ServiceStarted(); iSM->BaseEnv().CompleteState(KErrNone); } } } else iSMObserver->ConnectionComplete(EPsdFinishedActivation,iStatus.Int()); }void CPsdActivateContext::DoCancel()/**Cancell Asynchronous request of activate context state. */ { __ASSERT_DEBUG(iSM,User::Invariant()); iSM->Context().CancelAsyncRequest(EPacketContextActivate); }CAgentStateBase* CPsdActivateContext::NextStateL(TBool aContinue)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { if (iStatus==KErrNone && aContinue) return CPsdOpen::NewL(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdRecoverCommPort(iSMObserver,iSM,iDbPsd); }CPsdOpen* CPsdOpen::NewL(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb)/**Constructing an object of class CPsdOpen,pushing it to the clean up stack and popping it out.*/ { CPsdOpen* state = new (ELeave) CPsdOpen(aObserver,aPsdSM,aDb); CleanupStack::PushL(state); state->ConstructL(); CleanupStack::Pop(); return state; }CPsdOpen::CPsdOpen(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }void CPsdOpen::ConstructL()/**2nd Phase Construction*/ {}CPsdOpen::~CPsdOpen()/**Destructor*/ { delete iContextChangeMonitor; Cancel(); }void CPsdOpen::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM && iSMObserver,User::Invariant()); iSM->Context().GetStatus(iContextStatus); if (iContextStatus==RPacketContext::EStatusActive) { LogActive(); TRAPD(err,WatchForConfigChangesL()); if(err != KErrNone) { iSMObserver->ConnectionComplete(KConnectionOpen,err); return; } } //Either, we've successfully handled the active state or we have to //wait for TSY to tell us it has become active. This is because calling Activate() //doesn't necessarily mean it's activated in the network - have to wait for PPP to do its //stuff. RequestStatusChange(); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tCalling ConnectionComplete");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1()); iSMObserver->Notification(EAgentToNifEventTypeModifyInitialTimer,NULL); iSMObserver->UpdateProgress(KConnectionOpen,KErrNone); // I think NIFMAN just swallows this after // a ConnectComplete(Open) iSMObserver->ConnectionComplete(KConnectionOpen,KErrNone); }void CPsdOpen::LogActive()/**This internal function starts the logging and also starts watching for the connection qualitydropping below minimum acceptable valuesThis is called every time state goes to Active. Only want to log the first time, asensuing times it could be a Suspended->Active transition.*/ { if (!iEventLoggerStarted) { TBuf<KCommsDbSvrMaxFieldLength> remoteParty; remoteParty.Zero(); TRAPD(err, iDbPsd->GetRemotePartyL(remoteParty)); // logg err if(err != KErrNone) {#ifdef __FLOG_ACTIVE _LIT8(logString1,"CPsdOpen:\t Error in getting remote party %d."); __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),err); #endif } iEventLoggerStarted = ETrue; if (!iSM->BaseEnv().IsReconnect()) { if (iSM->Direction()==ECommDbConnectionDirectionOutgoing) iSM->Logger()->LogDataAddEvent(R_LOG_CON_CONNECTED, remoteParty,R_LOG_DIR_OUT,KNullDesC,KLogPacketDataEventTypeUid); else iSM->Logger()->LogDataAddEvent(R_LOG_CON_CONNECTED, remoteParty,R_LOG_DIR_IN,KNullDesC,KLogPacketDataEventTypeUid); iSM->DataLogger()->Start(); } else { //the logevent is already existing, we just have reconnected then update the status of the connection iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_CONNECTED, KLogPacketDataEventTypeUid); // no need to start again the datalogger since it has not been stopped previously } } }void CPsdOpen::WatchForConfigChangesL()/**Watch for Configuration changes in the open state*/ { // Should only be called once the context is active if(!iContextChangeMonitor) { //start watching for changes in the context status iContextChangeMonitor = CPsdContextChangeMonitor::NewL(iSM,this); } }void CPsdOpen::RequestStatusChange()/**Request for the change of status in the open state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); iSM->Context().NotifyStatusChange(iStatus,iContextStatus); SetActive(); }void CPsdOpen::RunL()/**No need for this state ever to call CompleteState(), because we are expecting the state machine to be told to Disconnect from above, which means this state will have NextStateL()called on it.Update progress for open state.*/ { __ASSERT_DEBUG(iSM && iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"PacketData:\tStatus change to %s\0");) if (iStatus==KErrNone) { switch (iContextStatus) { case RPacketContext::EStatusSuspended: { __FLOG_STMT(const TText8 value[] = "suspended";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); iSMObserver->Notification(EAgentToNifEventTypeDisableTimers,NULL); iSMObserver->UpdateProgress(EPsdSuspended,KErrNone); iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_SUSPENDED, KLogPacketDataEventTypeUid); RequestStatusChange(); } break; case RPacketContext::EStatusActive: { // if reconnect happened then the logger is allready started and we just do an update if (!iEventLoggerStarted) { __FLOG_STMT(const TText8 value[] = "log active";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); WatchForConfigChangesL(); //those 2 functions should have been called in start state but LogActive(); //RPacketContext was not EStatusActive at that time } else // the LogCallStart() has completed { iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_CONNECTED, KLogPacketDataEventTypeUid); __FLOG_STMT(const TText8 value[] = "active";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); } iSMObserver->Notification(EAgentToNifEventTypeEnableTimers,NULL); iSMObserver->UpdateProgress(KConnectionOpen,KErrNone); RequestStatusChange(); } break; case RPacketContext::EStatusDeactivating: { __FLOG_STMT(const TText8 value[] = "deactivating";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); iSMObserver->UpdateProgress(EPsdStartingDeactivation,KErrNone); iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_DISCONNECTING, KLogPacketDataEventTypeUid); RequestStatusChange(); } break; case RPacketContext::EStatusInactive: { __FLOG_STMT(const TText8 value[] = "inactive";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_DISCONNECTED, KLogPacketDataEventTypeUid); } break; case RPacketContext::EStatusDeleted: { __FLOG_STMT(const TText8 value[] = "deleted";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); iSMObserver->UpdateProgress(EPsdFinishedDeactivation,KErrNone); iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_DISCONNECTED, KLogPacketDataEventTypeUid); } break; case RPacketContext::EStatusActivating: { __FLOG_STMT(const TText8 value[] = "activating";) __FLOG_STATIC1(KPsdAgxLogFolder(),KPsdAgxLogFile(),TRefByValue<const TDesC8>(logString1()),&value); iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_CONNECTING, KLogPacketDataEventTypeUid); RequestStatusChange(); } break; default: PanicAgt(EPsdUnknownContextState); break; }; } // no way to signal upwards that there's been an error. // Have to rely on the agent's client to close down, or PPP to detect it's gone down }void CPsdOpen::DoCancel()/**The SM shouldn't call Cancel() on us because CancelConnect can never be called on it.But we must Cancel ourselves when leaving the state.Cancell Asynchronous request of open state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); // the only pending request is RequestStatusChange, do not cancel the logging request which is in the queue. iSM->Context().CancelAsyncRequest(EPacketContextNotifyStatusChange); } CAgentStateBase* CPsdOpen::NextStateL(TBool /*aContinue*/)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { Cancel(); return new (ELeave) CPsdRecoverCommPort(iSMObserver,iSM,iDbPsd); }void CPsdOpen::ReportContextBelowAcceptableQuality()/**Callback function from CPsdContextChangeMonitor objectwhen called launches a dialog to inform the user that theconnection has dropped below acceptable quality*/ { // The connection has gone below the acceptable level of quality // so put up a dialog asking the user what they want to do iSM->BaseEnv().DlgPrc()->QoSWarning(*this); }void CPsdOpen::MDPOQoSWarningComplete(TInt aError, TBool aResponse)/**Callback from the QoS warning dialog@param TInt aError indication if an error occured in the dialog@param TBool flag indicating the response from the dialog. ETrue means disconnect*/ { // Callback from the QoS warning dialog // aResponse == True means disconnect if((aResponse)&&(aError == KErrNone)) { // Disconnect // Request Nifman to disconnect iSMObserver->Notification(EAgentToNifEventTypeDisableConnection,NULL); } }void CPsdOpen::ReportError(TInt aError)/**Report error in open state.@param aError, error code for error occurs during open state.*/ { JumpToRunl(aError); }CPsdRecoverCommPort::CPsdRecoverCommPort(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdRecoverCommPort::~CPsdRecoverCommPort()/**Destructor*/ { Cancel(); }void CPsdRecoverCommPort::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM && iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tRecovering Comm Port to ETel");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSMObserver->UpdateProgress(EPsdStartingDeactivation,KErrNone); iSM->Context().RecoverCommPort(iStatus); SetActive(); }void CPsdRecoverCommPort::RunL()/**Complete state for Recover comm port state.*/ { __ASSERT_DEBUG(iSM,User::Invariant()); // what can we do with errors at this stage in the game? __FLOG_STMT(_LIT8(logString1,"Packet Data:\tRecovered Comm Port");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSM->BaseEnv().CompleteState(KErrNone); }void CPsdRecoverCommPort::DoCancel()/**Cancell Asynchronous request of comm port state.*/ { iSM->Context().CancelAsyncRequest(EPacketContextRecoverCommPort); }CAgentStateBase* CPsdRecoverCommPort::NextStateL(TBool /*aContinue*/)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machineIgnoring aContinue because the end is in sight now.If the SM has been asked to reconnect by PPP, we need to go back and activate the context again.@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { if (iSM->BaseEnv().IsReconnect()) { return new (ELeave) CPsdActivateContext(iSMObserver,iSM,iDbPsd); } else { iSM->Logger()->LogDataUpdateEvent(R_LOG_CON_DISCONNECTED, KLogPacketDataEventTypeUid); // request to update and close log iSM->DataLogger()->StopL(); return new (ELeave) CPsdCloseLog(iSMObserver,iSM,iDbPsd); } }////// CPsdCloseLog//// This class ensures that the asynchronous "final data transfer logging" completes // before the asynchronous Log Call End happens.CPsdCloseLog::CPsdCloseLog(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdCloseLog::~CPsdCloseLog()/**Destructor*/ { Cancel(); }void CPsdCloseLog::StartState()/**Function called by the genconn state machine framework to start the state*/ { __FLOG_STMT(_LIT8(logString1,"Packet Data:\tClosing Log");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1()); // We need to make sure that logging is finished before closing everything. // forward iStatus to the logger, which will be responsible to complete iStatus when it is finished. iStatus = KRequestPending; SetActive(); iSM->Logger()->LogDataNotifyLastEventUpdate(&iStatus); }void CPsdCloseLog::RunL()/**Complete state for Close Log state.*/ { iSM->BaseEnv().CompleteState(KErrNone); }void CPsdCloseLog::DoCancel()/**Cancell Asynchronous request of close log state.*/ { iSM->Logger()->Cancel(); //cancel because we will delete everything }CAgentStateBase* CPsdCloseLog::NextStateL(TBool /*aContinue*/)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machineIgnoring aContinue because the end is in sight now.If the context is still active, SM moves to Deactivation stateotherwise proceed to Closure state@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { RPacketContext::TContextStatus contextstatus; iSM->Context().GetStatus(contextstatus); if (contextstatus==RPacketContext::EStatusActive || contextstatus==RPacketContext::EStatusSuspended) return new (ELeave) CPsdDeactivation(iSMObserver,iSM,iDbPsd); else return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }CPsdDeactivation::CPsdDeactivation(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdDeactivation::~CPsdDeactivation()/**Destructor*/ { Cancel(); }void CPsdDeactivation::StartState()/**Function called by the genconn state machine framework to start the state*/ { __ASSERT_DEBUG(iSM,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tDeactivating Context");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSM->Context().Deactivate(iStatus); SetActive(); }void CPsdDeactivation::RunL()/**Complete state for deactivation state.*/ { __ASSERT_DEBUG(iSM && iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tDeactivated Context");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); iSMObserver->UpdateProgress(EPsdFinishedDeactivation,KErrNone); iSM->BaseEnv().CompleteState(KErrNone); }void CPsdDeactivation::DoCancel()/**Cancell Asynchronous request of deactivation state.*/ { iSM->Context().CancelAsyncRequest(EPacketContextDeactivate); } CAgentStateBase* CPsdDeactivation::NextStateL(TBool /*aContinue*/)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { return new (ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }////// CPsdClosure//CPsdClosure::CPsdClosure(MAgentStateMachineEnv* aObserver,MPsdEnv* aPsdSM, MPsdCommDbAccess* aDb): CAgentStateBase(*aObserver),iSM(aPsdSM),iDbPsd(aDb)/**Constructor*/ { __ASSERT_DEBUG(aObserver&&aPsdSM&&aDb, User::Invariant()); }CPsdClosure::~CPsdClosure()/**Destructor*/ { Cancel(); }void CPsdClosure::StartState()/**Function called by the genconn state machine framework to start the state*/ { iSubState = EClosureStart; JumpToRunl(KErrNone); }void CPsdClosure::RunL()/**Complete Disconnection for closure state.*/ { __ASSERT_DEBUG(iSM && iSMObserver,User::Invariant()); __FLOG_STMT(_LIT8(logString1,"Packet Data:\tClosing down");) __FLOG_STATIC(KPsdAgxLogFolder(),KPsdAgxLogFile(),logString1); RTelServer& etel = iSM->TelServer(); RPhone& phone = iSM->Phone(); RPacketService& packetNetwork = iSM->PacketNetwork(); RPacketContext& context = iSM->Context(); RPacketQoS& qoS = iSM->QoS(); if(iSubState == EClosureStart) { if (qoS.SubSessionHandle()!=0) { qoS.Close(); } if (context.SubSessionHandle()!=0) { TInt aError=KErrNone; if (context.GetLastErrorCause(aError)==KErrNone) iSM->ErrorCause()=aError; iSubState = EDeletingContext; context.Delete(iStatus); SetActive(); return; // break out and wait for delete to complete } else { // Advance to end sub state iSubState = EClosureEnd; } } if(iSubState == EDeletingContext) { // context delete completed so now close it down context.Close(); // Advance to end sub state iSubState = EClosureEnd; } // Intentional fallthrough if(iSubState == EClosureEnd) { packetNetwork.Close(); phone.Close(); if(iSM->TsyLoaded()) { TBuf<KCommsDbSvrMaxFieldLength> tsyName; iSM->BaseEnv().Db()->GetTsyNameL(tsyName); User::LeaveIfError(etel.UnloadPhoneModule(tsyName)); iSM->SetTsyLoaded(EFalse); } etel.Close(); // Phone module unloaded automatically iSMObserver->DisconnectComplete(); } }void CPsdClosure::DoCancel()/**Cancell Asynchronous request of closure state.*/ {}CAgentStateBase* CPsdClosure::NextStateL(TBool /*aContinue*/)/**Called by the genconn state machine frame work to move the state machine to the next statefunction creates the next state in the state machine@param TBool aContinue flag indicating if the state machine wishes to continue the connection or close it down@return CAgentStateBase* pointer to the next state in the state machine the calling function takes ownership of the returned object*/ { return new(ELeave) CPsdClosure(iSMObserver,iSM,iDbPsd); }