diff -r d0d9cc530d21 -r f45cd1ad4667 telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/spudman.cpp --- a/telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/spudman.cpp Thu Sep 02 21:42:07 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3247 +0,0 @@ -// Copyright (c) 2004-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: -// SPUD event manager -// WINSCW compiler has problems disambiguating TMetaDes8 and Meta::TMetaDes8 so -// I prevent metabuffer.h from being recursively included from other headers -// by defining its include guard. -// -// - -/** - @file - @internalComponent -*/ -#define METABUFFER_H - -#include "spudman.h" -#include "bindman.h" -#include "mux.h" - -#include -#include "rpdpfsminterface.h" -using namespace SpudMan; // Access the SpudFsm event names - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -const TUint KQosPlugInProtocolId = 360; //< Plug-in protocol ID - -static const TInt KMaxInetAddrPrintSize = 50; //This should be big enough for an IPv6 printout - - -#ifdef __FLOG_ACTIVE - -_LIT(KSpudUnknownLit, "Unknown event"); - -_LIT(KSpudSoIfControllerPlugInLit, "KSoIfControllerPlugIn"); -_LIT(KSpudLitKRegisterEventHandler, "KRegisterEventHandler"); -_LIT(KSpudContextSetEventsLit, "KContextSetEvents"); -_LIT(KSpudNifSetDefaultQoSLit, "KNifSetDefaultQoS"); -_LIT(KSpudContextCreateLit, "KContextCreate"); -_LIT(KSpudContextDeleteLit, "KContextDelete"); -_LIT(KSpudContextActivateLit, "KContextActivate"); -_LIT(KSpudContextQoSSetLit, "KContextQoSSet"); -_LIT(KSpudContextTFTModifyLit, "KContextTFTModify"); -_LIT(KSpudGetNegQoSLit, "KGetNegQoS"); -_LIT(KSpudContextModifyActiveLit, "KContextModifyActive"); -_LIT(KInitialisePdpFsmLit, "KInitialisePdpFsm"); - - -static const TDesC *SpudGuQoSEventToText(TInt aEvent) - { - switch(aEvent) - { - case KSoIfControllerPlugIn: - return &KSpudSoIfControllerPlugInLit; - case KRegisterEventHandler: - return &KSpudLitKRegisterEventHandler; - case KContextSetEvents: - return &KSpudContextSetEventsLit; - case KNifSetDefaultQoS: - return &KSpudNifSetDefaultQoSLit; - case KContextCreate: - return &KSpudContextCreateLit; - case KContextDelete: - return &KSpudContextDeleteLit; - case KContextActivate: - return &KSpudContextActivateLit; - case KContextQoSSet: - return &KSpudContextQoSSetLit; - case KContextTFTModify: - return &KSpudContextTFTModifyLit; - case KGetNegQoS: - return &KSpudGetNegQoSLit; - case KContextModifyActive: - return &KSpudContextModifyActiveLit; - case KInitialisePdpFsm: - return &KInitialisePdpFsmLit; - default: - return &KSpudUnknownLit; - } - } - -_LIT(KSpudContextDeleteEventLit, "KContextDeleteEvent"); -_LIT(KSpudContextActivateEventLit, "KContextActivateEvent"); -_LIT(KSpudContextParametersChangeEventLit, "KContextParametersChangeEvent"); -_LIT(KSpudContextBlockedEventLit, "KContextBlockedEvent"); -_LIT(KSpudContextUnblockedEventLit, "KContextUnblockedEvent"); -_LIT(KSpudNetworkStatusEventLit, "KNetworkStatusEvent"); -_LIT(KSpudContextQoSSetEventLit, "KContextQoSSetEvent"); -_LIT(KSpudContextTFTModifiedEventLit, "KContextTFTModifiedEvent"); -_LIT(KSpudPrimaryContextCreatedLit, "KPrimaryContextCreated"); -_LIT(KSpudSecondaryContextCreatedLit, "KSecondaryContextCreated"); -_LIT(KSpudGetNegQoSEventLit,"KGetNegQoSEvent"); -_LIT(KSpudContextModifyActiveEventLit, "KContextModifyActiveEvent"); -_LIT(KPdpFsmShuttingDownLit, "KPdpFsmShuttingDown"); - -static const TDesC *SpudFsmEventToText(TInt aEvent) - { - switch(aEvent) - { - case KContextDeleteEvent: - return &KSpudContextDeleteEventLit; - case KContextActivateEvent: - return &KSpudContextActivateEventLit; - case KContextParametersChangeEvent: - return &KSpudContextParametersChangeEventLit; - case KContextBlockedEvent: - return &KSpudContextBlockedEventLit; - case KContextUnblockedEvent: - return &KSpudContextUnblockedEventLit; - case KNetworkStatusEvent: - return &KSpudNetworkStatusEventLit; - case KContextQoSSetEvent: - return &KSpudContextQoSSetEventLit; - case KContextTFTModifiedEvent: - return &KSpudContextTFTModifiedEventLit; - case KPrimaryContextCreated: - return &KSpudPrimaryContextCreatedLit; - case KSecondaryContextCreated: - return &KSpudSecondaryContextCreatedLit; - case KGetNegQoSEvent: - return &KSpudGetNegQoSEventLit; - case KContextModifyActiveEvent: - return &KSpudContextModifyActiveEventLit; - case KPdpFsmShuttingDown: - return &KPdpFsmShuttingDownLit; - default: - return &KSpudUnknownLit; - } - } - -_LIT(KSpudStateSpudInactiveLit, "ESpudInactive"); -_LIT(KSpudStateSpudHaveQosLit, "ESpudHaveQos"); -_LIT(KSpudStateSpudCreatingPrimary, "ESpudCreatingPrimary"); -_LIT(KSpudStateSpudStartingPrimaryLit, "ESpudStartingPrimary"); -_LIT(KSpudStateSpudStartingPrimaryLowerNifLit, "ESpudStartingPrimaryLowerNif"); -_LIT(KSpudStateSpudStartingSecondaryLit, "ESpudStartingSecondary"); -_LIT(KSpudStateSpudStartingSecondaryLowerNifLit, "ESpudStartingSecondaryLowerNif"); -_LIT(KSpudStateSpudGettingNegQoSLit, "ESpudGettingNegQoS"); -_LIT(KSpudStateSpudUpLit, "ESpudUp"); -_LIT(KSpudStateSpudFlowOffLit, "ESpudFlowOff"); -_LIT(KSpudStateSpudSuspendedLit, "ESpudSuspended"); -_LIT(KSpudStateSpudFlowOffAndSuspendedLit, "ESpudFlowOffAndSuspended"); -_LIT(KSpudStateSpudLinkDownLit, "ESpudLinkDown"); -_LIT(KSpudStateSpudContextDeleteLit, "ESpudContextDelete"); -_LIT(KSpudStateSpudWaitLinkDownLit, "ESpudWaitLinkDown"); -_LIT(KSpudStateSpudWaitBinderDeleteLit, "ESpudWaitBinderDelete"); -_LIT(KSpudStateUnknownLit, "Unknown spud state"); - -static const TDesC *SpudStateToText(TSpudContextStates aState) - { - switch(aState) - { - case ESpudInactive: - return &KSpudStateSpudInactiveLit; - case ESpudHaveQos: - return &KSpudStateSpudHaveQosLit; - case ESpudCreatingPrimary: - return &KSpudStateSpudCreatingPrimary; - case ESpudStartingPrimary: - return &KSpudStateSpudStartingPrimaryLit; - case ESpudStartingPrimaryLowerNif: - return &KSpudStateSpudStartingPrimaryLowerNifLit; - case ESpudStartingSecondary: - return &KSpudStateSpudStartingSecondaryLit; - case ESpudStartingSecondaryLowerNif: - return &KSpudStateSpudStartingSecondaryLowerNifLit; - case ESpudGettingNegQoS: - return &KSpudStateSpudGettingNegQoSLit; - case ESpudUp: - return &KSpudStateSpudUpLit; - case ESpudFlowOff: - return &KSpudStateSpudFlowOffLit; - case ESpudSuspended: - return &KSpudStateSpudSuspendedLit; - case ESpudFlowOffAndSuspended: - return &KSpudStateSpudFlowOffAndSuspendedLit; - case ESpudLinkDown: - return &KSpudStateSpudLinkDownLit; - case ESpudContextDelete: - return &KSpudStateSpudContextDeleteLit; - case ESpudWaitLinkDown: - return &KSpudStateSpudWaitLinkDownLit; - case ESpudWaitBinderDelete: - return &KSpudStateSpudWaitBinderDeleteLit; - default: - return &KSpudStateUnknownLit; - } - } - -#endif - -CSpudMan::CSpudMan(CNifIfFactory& aFactory, MNifIfNotify* aNotify) - : CNifIfLink(aFactory), - iContextStatusOverride(RPacketContext::EStatusUnknown) - { - iNotify = aNotify; - ASSERT(iNotify); - __FLOG_OPEN(KSpudFirstTag,KSpudLog); - __FLOG_0(_L("CSpudMan::CSpudMan")); - } - -CSpudMan::~CSpudMan() - { - if (iBindMan) - { - // Only log if ConstructL() was called, where logger was initialized - __FLOG_0(_L("CSpudMan::~CSpudMan")); - } - - - if (AreQoSEventsEnabled()) - { - // Spud is being destroyed by Nifman. Tell GUQoS to stop bothering SPUD. - // GUQoS returns the favour by turning off the NIF events within this very call. - // ********************************************************************************************* - // N.B.: "DEF055691 GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack - // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event. - // Because of this defect, we cannot signal KNetworkInterfaceDown from anywhere but here. Once it is fixed, - // calls from the appropriate places will be enabled, and the line below will not be strictly necessary. - SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached); - // For safety, we should call this from here in any case. - //********************************************************************************************** - } - - delete iParkedDefaultQoS; - delete iBinderSweeperNotifierCb; - - delete iBindMan; - iPdpFsmInterface.Close(); - iSipServerAddr.Close(); - __FLOG_CLOSE; - } - -/** -Panics the current thread. - -@param aReason Panic reason code -*/ -void CSpudMan::Panic(TInt aReason) const - { - __FLOG_1(_L("CSpudMan::Panic with reason %d"), aReason); - User::Panic(KSpudName, aReason); - } - -/** -Construct the Link Protocol Object - -@param aBindMan Pointer to BindMan object (ownership is transferred) -@leave leaves if could not allocate memory -*/ -void CSpudMan::ConstructL(CBindMan* aBindMan) - { - __FLOG_1(_L("CSpudMan starting %x"), iNotify); - - - iBindMan = aBindMan; - ASSERT(iBindMan); - - // The lower NIF binder deletion & Nifman notification callback - iBinderSweeperNotifierCb = new (ELeave) CBinderSweeperNotifierCb(*this); - } - - -/** -Implements the Control method of CNifBase - used for retrieval of the P-CSCF (Sip Server) address -*/ -TInt CSpudMan::Control(TUint aLevel,TUint aName,TDes8& aOption, TAny*) - { - if (aLevel == KCOLConfiguration && aName == KConnGetSipServerAddr) - { - if (aOption.Length() != sizeof (SSipServerAddr)) - { - __FLOG(_L("CSpudMan::Control - Invalid Descriptior - Descriptor Must contain an SSipServerAddr")); - Panic(); - } - SSipServerAddr* sipServerAddr = reinterpret_cast(const_cast(aOption.Ptr())); - if (sipServerAddr->index < 0 || sipServerAddr->index >= iSipServerAddr.Count()) - { - __FLOG_1(_L("CSpudMan::Control - Index out of range : value = %d"), sipServerAddr->index); - return KErrNotFound; - } - sipServerAddr->address = iSipServerAddr[sipServerAddr->index]; -#ifdef __FLOG_ACTIVE - TBuf buf; - sipServerAddr->address.Output(buf); - __FLOG_2(_L("CSpudMan::Control Address %S returned for index %d"), &buf, sipServerAddr->index); -#endif - return KErrNone; - } - return KErrNotSupported; - } - - -/** -Retrieve any GPRS settings required from CommDB - -@param aConfigGprs Context configuration parameters to be filled in -*/ -void CSpudMan::RetrieveGprsConfig(RPacketContext::TContextConfigGPRS& aConfigGprs) const - { - TUint32 pdpType(0); - Notify()->ReadInt(TPtrC(GPRS_PDP_TYPE), pdpType); - __FLOG_1(_L8("ReadInt GPRS_PDP_TYPE [%d]"), pdpType); - aConfigGprs.iPdpType = STATIC_CAST(RPacketContext::TProtocolType, pdpType); - - Notify()->ReadDes(TPtrC(GPRS_APN), aConfigGprs.iAccessPointName); - __FLOG_1(_L8("ReadDes GPRS_APN [%S]"), &aConfigGprs.iAccessPointName); - - - TBool fromServer; - aConfigGprs.iPdpAddress.SetLength(0); - Notify()->ReadBool(TPtrC(GPRS_IP_ADDR_FROM_SERVER), fromServer); - if (!fromServer) - { - Notify()->ReadDes(TPtrC(GPRS_IP_ADDR), aConfigGprs.iPdpAddress); - } - - - // We can only use IPv4 or IPv6 - we use the first one listed in the IfNetworks field - TBuf networks; - Notify()->ReadDes(TPtrC(LAN_IF_NETWORKS), networks); - - ASSERT(networks.Length() > 0); // If the IfNetworks field is empty there is a serious misconfiguration - - TInt pos = networks.Find(_L(",")); - if (pos == KErrNotFound) - { - pos = networks.Length(); - } - TPtrC protocol(networks.Ptr(), pos); - _LIT(KIp4, "ip"); - _LIT(KIp6, "ip6"); - if (protocol.CompareF(KIp4) == 0) - { - // IPv4 settings - Notify()->ReadBool(TPtrC(GPRS_IP_DNS_ADDR_FROM_SERVER), fromServer); - if (!fromServer) - { - Notify()->ReadDes(TPtrC(GPRS_IP_NAME_SERVER1), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iPrimaryDns); - Notify()->ReadDes(TPtrC(GPRS_IP_NAME_SERVER2), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iSecondaryDns); - } - } - else if (protocol.CompareF(KIp6) == 0) - { - // IPv6 settings - Notify()->ReadBool(TPtrC(GPRS_IP6_DNS_ADDR_FROM_SERVER), fromServer); - if (!fromServer) - { - Notify()->ReadDes(TPtrC(GPRS_IP6_NAME_SERVER1), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iPrimaryDns); - Notify()->ReadDes(TPtrC(GPRS_IP6_NAME_SERVER2), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iSecondaryDns); - } - } - else - { - // Anything else is a serious misconfiguration - ASSERT(0); - } - - RetrieveGprsCompression(aConfigGprs.iPdpCompression); - __FLOG_1(_L8("Read GprsCompression [%d]"), aConfigGprs.iPdpCompression); - - RetrieveGprsAnonymousAccess(aConfigGprs.iAnonymousAccessReqd); - __FLOG_1(_L8("Read AnonymousAccess [%d]"), aConfigGprs.iAnonymousAccessReqd); - - TBuf readBuf; - Notify()->ReadDes(TPtrC(SERVICE_IF_AUTH_NAME), readBuf); - aConfigGprs.iProtocolConfigOption.iAuthInfo.iUsername.Copy(readBuf); - readBuf.Zero(); - Notify()->ReadDes(TPtrC(SERVICE_IF_AUTH_PASS), readBuf); - aConfigGprs.iProtocolConfigOption.iAuthInfo.iPassword.Copy(readBuf); - __FLOG_2(_L8("ReadDes SERVICE_IF_AUTH_NAME [%S] and SERVICE_IF_AUTH_PASS [%S]"), &aConfigGprs.iProtocolConfigOption.iAuthInfo.iUsername, - &aConfigGprs.iProtocolConfigOption.iAuthInfo.iPassword); - - aConfigGprs.iUseEdge = EFalse; - } - -void CSpudMan::RetrieveGprsCompression(TUint& aCompression) const - { - aCompression = 0; - TBool isCompression = EFalse; - Notify()->ReadBool(TPtrC(GPRS_DATA_COMPRESSION), isCompression); - if (isCompression) - { - aCompression |= RPacketContext::KPdpDataCompression; - } - - isCompression = EFalse; - Notify()->ReadBool(TPtrC(GPRS_HEADER_COMPRESSION), isCompression); - if (isCompression) - { - aCompression |= RPacketContext::KPdpHeaderCompression; - } - } - -void CSpudMan::RetrieveGprsAnonymousAccess(RPacketContext::TAnonymousAccess& aAnonymous) const - { - TBool isAnonymous = EFalse; - Notify()->ReadBool(TPtrC(GPRS_ANONYMOUS_ACCESS),isAnonymous); - if (isAnonymous) - aAnonymous = RPacketContext::ERequired; - else - aAnonymous = RPacketContext::ENotRequired; - } - - - -/** -Indicates whether QoS has been enabled or not. - -@return ETrue if QoS has been enabled for this NIF. -*/ -TBool CSpudMan::AreQoSEventsEnabled() const - { - return iQosEventHandler != NULL; - } - - -/** -Returns pointer to BindMan. - -@return Pointer to BindMan object -*/ -CBindMan* CSpudMan::BindMan() const - { - return iBindMan; - } - -/** -Returns pointer to the MNifIfNotify object in NIFMAN. - -@return Pointer to MNifIfNotify object -*/ -MNifIfNotify* CSpudMan::Notify() const - { - ASSERT(iNotify); - return iNotify; - } - -/** -Set default QoS parameters from the values in CommDb. - -@param aQos QoS parameters filled in on exit -*/ -void CSpudMan::ReadDefaultQoS(RPacketQoS::TQoSR99_R4Requested& aQos) const - { - TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName; - _LIT(KFormatText,"%s\\%s"); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRAFFIC_CLASS); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqTrafficClass)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_CLASS); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinTrafficClass)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVERY_ORDER); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqDeliveryOrderReqd)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVERY_ORDER); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinDeliveryOrderReqd)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVER_ERRONEOUS_SDU); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqDeliverErroneousSDU)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVER_ERRONEOUS_SDU); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinDeliverErroneousSDU)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_SDUSIZE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqMaxSDUSize)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_ACCEPTABLE_MAX_SDU_SIZE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinAcceptableMaxSDUSize)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_UPLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqMaxRate.iUplinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_UPLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinAcceptableMaxRate.iUplinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_DOWNLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqMaxRate.iDownlinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_DOWNLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinAcceptableMaxRate.iDownlinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_BER); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqBER)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_BER); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMaxBER)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_SDU_ERROR_RATIO); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqSDUErrorRatio)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_SDU_ERROR_RATIO); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMaxSDUErrorRatio)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRAFFIC_HANDLING_PRIORITY); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqTrafficHandlingPriority)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_HANDLING_PRIORITY); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinTrafficHandlingPriority)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRANSFER_DELAY); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqTransferDelay)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_TRANSFER_DELAY); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMaxTransferDelay)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_UPLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqGuaranteedRate.iUplinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_UPLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinGuaranteedRate.iUplinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_DOWNLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iReqGuaranteedRate.iDownlinkRate)); - - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_DOWNLINK_RATE); - Notify()->ReadInt (columnName, reinterpret_cast(aQos.iMinGuaranteedRate.iDownlinkRate)); - } - -#ifdef SYMBIAN_NETWORKING_UMTSR5 -/** -Set default R5 QoS parameters from the values in CommDb. - -@param aQos R5 QoS parameters filled in on exit -*/ -void CSpudMan::ReadDefaultR5QoS(RPacketQoS::TQoSR5Requested& aQos) const - { - ReadDefaultQoS(aQos); - - TBuf<2*KCommsDbSvrMaxColumnNameLength+2> columnName; - _LIT(KFormatText,"%s\\%s"); - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_SIGNALLING_INDICATION); - Notify()->ReadBool (columnName, aQos.iSignallingIndication); - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_SOURCE_STATISTICS_DESCRIPTOR); - Notify()->ReadInt(columnName, reinterpret_cast(aQos.iSourceStatisticsDescriptor)); - } -#endif -// SYMBIAN_NETWORKING_UMTSR5 - - -/** -Reads TSY name from CommDb. - -@param aTsyName TSY name filled in on exit -*/ -void CSpudMan::ReadTsyName(TName& aTsyName) const - { - TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName; - _LIT(KFormatText,"%s\\%s"); - columnName.Format(KFormatText,MODEM_BEARER,MODEM_TSY_NAME); - Notify()->ReadDes(columnName, aTsyName); // ignore error - } - -/** -Sets the error code to use for termination, unless it is already set. - -@param aError Error code to use when notifying NIFMAN -*/ -void CSpudMan::SetTerminateError(TInt aError) - { - if (iTerminateError == KErrNone) - { - iTerminateError = aError; - __FLOG_1(_L("Set SPUD termination error to [%d]"), aError); - - // There is no specific context associated with this termination - // So prevent a later overwrite of the error by the ETel error - if (iETelTerminateError == KErrNone) - { - iETelTerminateError = aError; - } - } - } - -/** -Sets the error code to use for termination, unless it is already set. - -@param aContextId context ID -@param aError Error code to use when notifying NIFMAN -*/ -void CSpudMan::SetTerminateError(TContextId aContextId, TInt aError) - { - if (iTerminateError == KErrNone) - { - iTerminateError = aError; - - // Now check to see if ETel was the originator of this error - if (iETelTerminateError == KErrNone) - { - // ask for the last ETel error received - ignore return code - iPdpFsmInterface.GetLastErrorCause(aContextId, iETelTerminateError); - } - - if (iETelTerminateError != KErrNone) - { - // Overwrite with the most likely original error code! - iTerminateError = iETelTerminateError; - } - - __FLOG_1(_L("Set SPUD termination error to [%d]"), iTerminateError); - } - - } - -//***************************************************************************** -// Events receivers -//***************************************************************************** - -/** -Receives events from SpudFsm. - -@param aContextId context ID -@param aEvent event ID -@param aParam optional parameter to event -*/ -void CSpudMan::Input(TContextId aContextId, TInt aEvent, TInt aParam) - { - __FLOG_4(_L("SpudMan::Input: SpudFsm event %S(%d) param[%d] context[%d]"), SpudFsmEventToText(aEvent), aEvent, aParam, aContextId); - ASSERT(aContextId == KAllContexts || (aContextId >=0 && aContextId < KMaxPdpContexts)); - - switch (aEvent) - { - case KPrimaryContextCreated: - { - HandlePrimaryContextCreatedEvent(aContextId, aParam); - break; - } - - case KContextDeleteEvent: - { - HandleContextDeleteEvent(aContextId, aParam); - break; - } - - case KSecondaryContextCreated: - { - HandleSecondaryContextCreatedEvent(aContextId, aParam); - break; - } - - case KContextActivateEvent: - { - HandleContextActivateEvent(aContextId, aParam); - break; - } - - case KContextQoSSetEvent: - { - HandleContextQoSSetEvent(aContextId, aParam); - break; - } - - case KContextTFTModifiedEvent: - { - HandleContextTFTModifiedEvent(aContextId, aParam); - break; - } - - case KGetNegQoSEvent: - { - HandleGetNegQoSEvent(aContextId, aParam); - break; - } - - case KContextModifyActiveEvent: - { - HandleContextModifyActiveEvent(aContextId, aParam); - break; - } - - case KNetworkStatusEvent: - { - HandleNetworkStatusEvent(); - break; - } - - case KContextParametersChangeEvent: - { - HandleContextParametersChangeEvent(aContextId, aParam); - break; - } - - case KContextBlockedEvent: - { - HandleContextBlockedEvent(aContextId); - break; - } - - case KContextUnblockedEvent: - { - HandleContextUnblockedEvent(aContextId); - break; - } - - - case KPdpFsmShuttingDown: - { - __FLOG_0(_L("UmtsGprsSCPR has shutdown the PDP Fsm Interface")); - iPdpFsmInterface.Close(); - break; - } - - default: - __FLOG_1(_L("Unhandled event %d"), aEvent); - ASSERT(EFalse); - break; - } - } - -void CSpudMan::InitPdpFsmInterfaceL() - { - class XAssociatedNifConnectionProviderQuery : public MFactoryQuery - /** Finds the connection provider associated with the specified Nif. - @internalTechnology - */ - { - public: - XAssociatedNifConnectionProviderQuery( const TDesC& aName, ::TMetaDes8& aNameBuffer ) : iNifName( aName ), iNifNameBuffer( aNameBuffer ) - { - } - - virtual TMatchResult Match( TFactoryObjectInfo& aObjectInfo ) - { - TConnInterfaceName& name = *reinterpret_cast( const_cast( iNifNameBuffer.iDes->Ptr() ) ); - name.iIndex = 1; - - TInt err = KErrNone; - TMatchResult result = EContinue; - - // Check each of the connection provider interfaces' names to see if it - // is associated with this NIF. - while( ETrue ) - { - TRAP( err, static_cast( aObjectInfo.iInfo.iFactoryObject )->ControlL(KCOLProvider, KConnGetInterfaceName, iNifNameBuffer, NULL) ); - - if( err == KErrNone ) - { - if( name.iName == iNifName ) - { - result = EMatch; - - break; - } - } - else - { - break; - } - - name.iIndex ++; - } - - return result; - } - - private: - const TDesC& iNifName; - ::TMetaDes8& iNifNameBuffer; - }; - - const TUint KShimConnectionProviderFactoryId = 0x10207104; //the same as CSubConnectionProviderFactoryShim - - TSockManData* sockManData = SockManGlobals::Get(); - ASSERT(sockManData); - - CConnectionFactoryContainer* connectionFactories = sockManData->iConnectionFactories; - ASSERT(connectionFactories); - - CConnectionProviderFactoryBase *factory = connectionFactories->FindFactory(KShimConnectionProviderFactoryId); - if(!factory) - { - User::Leave( KErrNotFound ); - } - - CSpudMux* mux = iBindMan->SpudMux(); - - // Get the name of our SPUDMUX interface - it uniquely identifies this SPUD object assembly. - TNifIfInfo info; - mux->Info( info ); - - // Create a buffer to hold the name of each interface we check to see if the interface is our SPUDMUX. - TPckgBuf name; - TPtrC8 desC( name ); - ::TMetaDes8* des = ::TMetaDes8::NewL( &desC ); - - XAssociatedNifConnectionProviderQuery connProviderQuery( info.iName, *des ); - - // Find the connection provider associated with this NIF. - CConnectionProviderBase* connectionProvider = factory->FindProvider(connProviderQuery); - delete des; - if(!connectionProvider) - { - User::Leave( KErrNotFound ); - } - - CSubConnectionFactoryContainer* subConnectionFactories = sockManData->iSubConnectionFactories; - ASSERT(subConnectionFactories); - - TDataClientQuery subConnProviderQuery(connectionProvider, ESubConnPlane, RSubConnection::EAttachToDefault); - - // Find the default subconnection provider. - CSubConnectionProviderBase* subConnProvider = subConnectionFactories->FindOrCreateProviderL(connectionProvider->CanDoSubConnection(RSubConnection::EAttachToDefault), subConnProviderQuery); - if(!subConnProvider || subConnProvider->Factory().Id() != KUmtsGprsSubConnectionProviderFactoryId) - { - User::Leave( KErrNotFound ); - } - - // Initialise the PDP FSM interface. - TPckg nifPckg(mux); - User::LeaveIfError(subConnProvider->Control(KSOLInterface, KInitialisePdpFsm, nifPckg)); - } - -void CSpudMan::HandlePrimaryContextCreatedEvent(TContextId aContextId, TInt aError) - { - - // Save the contextId for later - iPrimaryContextId = aContextId; - - // Primary context has been created; Start the lower NIF - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __FLOG_2(_L("Got lower NIF binder for context[%d] with error[%d]"), aContextId, rc); - if (rc == KErrNone) - { - // Make sure context was created successfully - rc = aError; - ASSERT(ref->IsBound()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - } - - if (KErrNone == rc) // Context created successfully. - { - // Get the details of the P-CSCF - RPacketContext::TContextConfigGPRS config; - - if (iPdpFsmInterface.Get(aContextId, config) == KErrNone) - { - TRAP(rc, SetSipServerAddrL(config.iProtocolConfigOption);); - { - __FLOG_1(_L("CSpudMan::HandlePrimaryContextCreatedEvent -Error occurred extracting the sip server address: %d"),rc); - //rc is now non zero, therefore should fail gracefully - } -#ifdef SYMBIAN_NETWORKING_UMTSR5 - // Since the value or IMCN Signalling flag also comes in PCO IE buffer along with the SipAddress, we - // need to extract the value here and set it to Parameter Bundle of SCPR - TBool imcn = EFalse; - TRAPD(err,imcn=GetIMCNSignallingFlagPcoL(config.iProtocolConfigOption);); - __FLOG_1(_L("CSpudMan::GetIMCNSignallingFlagPcoL - returns eror=%d"),err); - if (err == KErrNone) - { - iPdpFsmInterface.SetIMCNSignalling(imcn); //imcn contains ETrue or Efalse -#ifdef __FLOG_ACTIVE - if (imcn) - { - __FLOG_0(_L("CSpudMan::HandlePrimaryContextCreatedEvent - Network ACCEPTS the request for dedicated IMCN Signalling Flag ")); - } - else - { - __FLOG_0(_L("CSpudMan::HandlePrimaryContextCreatedEvent - Network REJECTS the request for dedicated IMCN Signalling Flag ")); - } -#endif - } - else - { - -#ifdef __FLOG_ACTIVE - __FLOG_1(_L("CSpudMan::HandlePrimaryContextCreatedEvent -Leave Error occurred %d"),err); -#endif - } -#endif // SYMBIAN_NETWORKING_UMTSR5 - } - } - - if (KErrNone == rc) // Sip server address retrieved - { - ASSERT(ref->State() == ESpudCreatingPrimary); - ref->SetState(ESpudStartingPrimary); - // Start the lower NIF and wait for the LinkLayerUp call - rc = ref->NifLink()->Start(); - if(KErrNone == rc) - { - ref->SetState(ESpudStartingPrimaryLowerNif); - } - // Lower NIF may still report failure to Start by signalling LinkLayerDown with error. - // E.G. PPP negotiation may fail. - __FLOG_2(_L("Lower NIF for Primary Context[%d] started with error[%d]."), aContextId, rc); - } - - - // Catch-all error handling: Could not create context, or could not start lower NIF. - if(KErrNone != rc) - { - SetTerminateError(rc); - - SendPrimaryContextCreated(aContextId, rc); // Notify GUQoS of error - - if(ESpudStartingPrimary == ref->State()) // Context created - { - ref->SetState(ESpudWaitLinkDown); // We've just notified GUQoS. - // Delete context via SpudFsm - __FLOG_2(_L("Failed to start lower NIF for Primary PDP context[%d] due to error[%d]. Deleting Primary via SpudFsm."), aContextId, rc); - rc = iPdpFsmInterface.Input(aContextId, EContextDelete); - ASSERT(rc == KErrNone); - } - else // Context was not created, else we would not be here. There is nothing to stop and delete. - { - __FLOG_1(_L("Failed to create Primary context[%d]. Spud will shut down."), aContextId); - - if (AreQoSEventsEnabled()) - { - // At this point we know that SPUD is about to shut down, because we are - // deleting the last context. We want to indicate to the upper layers early that - // data can no longer be sent to SPUD. - - // Tell GUQoS to stop bothering SPUD. - // GUQoS returns the favour by turning off the NIF events within this very call. - // This means we won't send KNetworkInterfaceDown, even if we try. - // ********************************************************************************************* - // N.B.: "DEF055691 GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack - // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event. - // As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only - // from the destructor. Once this defect is fixed, the following line must be uncommented: - // SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached); - //********************************************************************************************** - } - // We are about to delete the primary context NIF: this will notify Nifman that SPUD is finished. - DisposeOfBinder(ref); - } - } - } - -void CSpudMan::HandleContextDeleteEvent(TContextId aContextId, TInt aError) - { - aError = aError; // suppress compiler warning - // Ignore error on delete--nothing we can do, anyway - // For the upper layers, we treat this event as KErrDisconnected, because the network has torn down an - // existing context. - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - __FLOG_4(_L("Network deleted context %d, in state %S(%d). Deletion error=%d"), - aContextId, SpudStateToText(ref->State()), ref->State(), aError); - - // Are we about to shut down after this context is deleted? - TBool shutdownStarted(BindMan()->IsLastContext(aContextId)); - // We must determine this before we make any state transitions. But we can act on this - // only after we've done all GUQoS notifications to make sure shutdown is graceful. - - switch (ref->State()) - { - case ESpudUp: - case ESpudFlowOff: - case ESpudSuspended: - case ESpudFlowOffAndSuspended: - ref->SetState(ESpudWaitLinkDown); - SendContextDeleteEvent(aContextId); - ref->NifLink()->Stop(KErrConnectionTerminated, MNifIfNotify::EDisconnect); - break; - - case ESpudStartingPrimaryLowerNif: - ref->SetState(ESpudWaitLinkDown); - SendPrimaryContextCreated(aContextId, KErrDisconnected); - SendContextDeleteEvent(aContextId); - ref->NifLink()->Stop(KErrConnectionTerminated, MNifIfNotify::EDisconnect); - break; - - case ESpudGettingNegQoS: // Context was activated. It is assumed that QoS retrieval would be cancelled by deletion. - case ESpudStartingSecondaryLowerNif: - ref->SetState(ESpudStartingSecondary); - FillInContextConfig(iTempContextConfig, aContextId); - SendContextActivateEvent(aContextId, iTempContextConfig, KErrDisconnected); - SendContextDeleteEvent(aContextId); - ref->NifLink()->Stop(KErrConnectionTerminated, MNifIfNotify::EDisconnect); - break; - - case ESpudStartingPrimary: - // this should never happen - SendPrimaryContextCreated(aContextId, KErrDisconnected); - SendContextDeleteEvent(aContextId); - DisposeOfBinder(ref); - break; - - case ESpudStartingSecondary: - // This should never happen, and may cause problems if it does because there could be - // another outstanding request from GUQoS that never gets completed. - __FLOG_0(_L("Network should not have deleted context in ESpudStartingSecondary state!")); - // Fall through and treat the same as ESpudLinkDown - - case ESpudLinkDown: - SendContextDeleteEvent(aContextId); - DisposeOfBinder(ref); - break; - - case ESpudWaitLinkDown: - DisposeOfBinder(ref); - break; - - - default: - __FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State()); - ASSERT(EFalse); - break; - } - - if(shutdownStarted) // Additional steps if we are shutting down as as result of this deletion. - { - SetTerminateError(KErrDisconnected); - // We don't reuse errorForGuqos, because we may want to keep Nifman errors and GUQoS errors separate. - if (AreQoSEventsEnabled()) - { - // At this point we know that SPUD is about to shut down, because the last context - // was just deleted. We want to indicate to the upper layers early that - // data can no longer be sent to SPUD. - - // Tell GUQoS to stop bothering SPUD. - // GUQoS returns the favour by turning off the NIF events within this very call. - // This means we send KNetworkInterfaceDown only once. - // ******************************************************************************************* - // N.B.: "DEF055691 GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack - // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event. - // As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only - // from the destructor. Once this defect is fixed, the following line must be uncommented: - // SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached); - //********************************************************************************************** - } - } - } - -void CSpudMan::HandleSecondaryContextCreatedEvent(TContextId aContextId, TInt aError) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - if (rc == KErrNone) - { - ASSERT(ref->IsBound()); - __FLOG_4(_L("Network created secondary context[%d] in state %S(%d). Creation error=%d "),aContextId, SpudStateToText(ref->State()), ref->State(), aError); - if (ref->State() != ESpudStartingSecondary) - { - __FLOG_3(_L("KSecondaryContextCreated context %d is in unexpected state %S(%d)"), - aContextId, SpudStateToText(ref->State()), ref->State()); - } - ref = ref; // Eliminate compiler warning in release builds - - // Make sure context was created successfully - rc = aError; - if(KErrNone != rc) // Creation failed: we don't have the context, only the binder. Delete it. - { - DisposeOfBinder(ref); - } - } - SendSecondaryContextCreated(aContextId, rc); - } - -void CSpudMan::HandleContextActivateEvent(TContextId aContextId, TInt aError) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - if (rc == KErrNone) - { - // Make sure context was activated successfully - rc = aError; - - ASSERT(ref->IsBound()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - } - - if (rc == KErrNone) - { - ASSERT(ref->State() == ESpudStartingSecondary); - // Start the lower NIF - rc = ref->NifLink()->Start(); - // Even if we get KErrNone here, we may still get LinkLayerDown with error later. - __FLOG_2(_L("KContextActivateEvent: Start on lower NIF returned for Context[%d] returned error[%d]"),aContextId, rc); - } - - if(KErrNone == rc) // Start OK. - { - - ref->SetState(ESpudStartingSecondaryLowerNif); - } - else - { - // Error activating PDP context - FillInContextConfig(iTempContextConfig, aContextId); - SendContextActivateEvent(aContextId, iTempContextConfig, rc); - } - } - -void CSpudMan::HandleContextQoSSetEvent(TContextId aContextId, TInt aError) - { - // Notify GUQoS of success or failure - SendContextQoSSetEvent(aContextId, aError); - } - -void CSpudMan::HandleContextTFTModifiedEvent(TContextId aContextId, TInt aError) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - ref = ref; // Eliminate compiler warning in release builds - - // Notify GUQoS of success or failure - TTFTOperationCode opCode; - iPdpFsmInterface.Get(aContextId, opCode); - SendContextTFTModifiedEvent(aContextId, opCode, aError); - } - -void CSpudMan::HandleGetNegQoSEvent(TContextId aContextId, TInt aError) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - - ASSERT(ref->IsBound()); - __FLOG_4(_L("CSpudMan: Retrieved Negotiated QoS, error=%d: context %d is in state %S(%d)"), aError, aContextId, SpudStateToText(ref->State()), ref->State()); - if (ref->State() == ESpudGettingNegQoS) - { - // Negotiated QoS retrieved successfully. At this point the ctx is up both on control and data paths. - if(KErrNone == aError) - { - // Context is now fully up. Notify GUQoS. - ref->SetState(ESpudUp); - // Notify GUQoS of success or failure - FillInContextConfig(iTempContextConfig, aContextId); - SendContextActivateEvent(aContextId, iTempContextConfig, aError); - - if(ref->State() == ESpudUp) // GUQoS can delete the context from the activation notification. - { - BindMan()->SpudProtocol()->DoStartSending(); - SendContextUnblockedEvent(aContextId); - } - } - // If the QoS could not be retrieved, we remain in ESpudGettingNegQoS and wait for - // the network to delete the context. The rest would be handled from the deletion event. - - // N.B. CRITICAL ASSUMPTION: - // The network / TSY will delete the ctx if the negotiated QoS could not be retrieved. - // (The idea is that if QoS negotiation is errored out, then everything is errored out. - // So we either do not get to this point at all, or will be errored out soon after this handler completes.) - // This leaves the issue of internal ETel/TSY errors such as OOM conditions.) - // At this point Spud is idle (no requests outstanding), so nothing will drive us - // forward to clean up this failure. GUQoS does NOT time out on PDP context creation failure. - } - else - { - // If we are not getting negotiated QoS, but we receive this notification, then: - // - ETel has sent us a stray notification totally uncalled for, i.e. it's a bug in ETel or more likely a TSY. - if(KErrNone == aError) - { - __FLOG(_L("WARNING! Negotiated QoS retrieval completed successfully, but totally out of order! See the comments in the code.)")); - } - // We don't assert, because it can be a race condition outside of ETel's control: - // - ETel, lower NIF, GUQoS, Nifman has errored the context out (e.g. ctx deleted by network), so there was a - // state transition as a result of that, and now the QoS retrieval has completed after that with KErrNone. - } - } - - -void CSpudMan::HandleContextModifyActiveEvent(TContextId aContextId, TInt aError) - { - // Notify GUQoS of success or failure - FillInContextConfig(iTempContextConfig, aContextId); - SendContextModifyActiveEvent(aContextId, iTempContextConfig, aError); - } - -void CSpudMan::HandleNetworkStatusEvent() - { - // This is a network status change - RPacketService::TStatus status; - iPdpFsmInterface.Get(status); - - // Assume that anything other than EStatusUnattached means the network - // is still up, so just ignore this event. - if (status == RPacketService::EStatusUnattached) - { - // Notify GUQoS - SendNetworkStatusEvent(KNetworkConnectionLost, status); - } - else - { - __FLOG_1(_L("Ignoring KNetworkStatusEvent with status %d (NOT EStatusUnattached)"), - status); - } - } - -void CSpudMan::HandleContextParametersChangeEvent(TContextId aContextId, TInt aError) - { - // This is a status change on an individual context - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - if (ref->State() == ESpudGettingNegQoS || ref->State() == ESpudUp || ref->State() == ESpudFlowOff || ref->State() == ESpudSuspended || ref->State() == ESpudFlowOffAndSuspended) - { - // Only pass on context changes while the context is up - FillInContextConfig(iTempContextConfig, aContextId); - SendContextParametersChangeEvent(aContextId, iTempContextConfig, aError); - } - else - { - __FLOG_3(_L("KContextParametersChangeEvent ignored on context %d because of nonoperational state %S(%d)"), - aContextId, SpudStateToText(ref->State()), ref->State()); - SetTerminateError(aContextId, aError); - } - } - -void CSpudMan::HandleContextBlockedEvent(TContextId aContextId) - { - // Context is suspended (see StopSending) - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - switch (ref->State()) - { - case ESpudUp: - { - ref->SetState(ESpudSuspended); - if (AreQoSEventsEnabled()) - { - SendContextBlockedEvent(aContextId); - } - - // Send an IfProgress to Nifman so that RConnection::ProgressNotification reports the blockage etc. - Notify()->IfProgress(KDataTransferTemporarilyBlocked, KErrNone); - break; - } - - case ESpudFlowOff: - ref->SetState(ESpudFlowOffAndSuspended); - - // Send an IfProgress to Nifman so that RConnection::ProgressNotification reports the blockage etc. - Notify()->IfProgress(KDataTransferTemporarilyBlocked, KErrNone); - break; - - case ESpudSuspended: - case ESpudFlowOffAndSuspended: - // Ignore this since we're already suspended - break; - - default: - // Ignore this since we're still starting up or shutting down - __FLOG_1(_L("Can't send blocked event now on context %d"), aContextId); - break; - } - - // TODO: Probably need to send IfProgress here where aStage==KDataTransferTemporarilyBlocked - // or Notification with aEvent=EAgentToNifEventTypeDisableTimers - // - // NOTE: The IfProgress has now been implemented so that callers of RConnection::ProgressNotification - // expecting to receive KDataTransferTemporarilyBlocked actually get it if the PDP context is - // suspended (details of problem in INC107930). - } - -void CSpudMan::HandleContextUnblockedEvent(TContextId aContextId) - { - // Context is suspended (see StartSending) - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - switch (ref->State()) - { - case ESpudUp: - case ESpudFlowOff: - // Ignore this since we're already in an unsuspended state - break; - - case ESpudSuspended: - { - ref->SetState(ESpudUp); - - BindMan()->SpudProtocol()->DoStartSending(); - - if (AreQoSEventsEnabled()) - { - SendContextUnblockedEvent(aContextId); - } - Notify()->IfProgress(KLinkLayerOpen, KErrNone); - break; - } - - case ESpudFlowOffAndSuspended: - { - ref->SetState(ESpudFlowOff); - Notify()->IfProgress(KLinkLayerOpen, KErrNone); - break; - } - - default: - // Ignore this since we're still starting up or shutting down - __FLOG_1(_L("Can't send unblocked event now on context %d; this may cause problems"), aContextId); - break; - } - } - -/** -Receives event from GUQoS. - -@param aName event identification -@param aOption optional data associated with event -@return error code -*/ -TInt CSpudMan::GuqosInput(TUint aName, TDes8& aOption) - { - __FLOG_2(_L("SpudMan::GuqosInput: GUQoS event %S(%d)"), SpudGuQoSEventToText(aName), aName); - switch (aName) - { - case KSoIfControllerPlugIn: - { - // Indicate that we want GUQoS - TSoIfControllerInfo& opt = *reinterpret_cast(const_cast(aOption.Ptr())); - _LIT(KQosPlugInName, "guqos"); - opt.iPlugIn = KQosPlugInName; - opt.iProtocolId = KQosPlugInProtocolId; - return KErrNone; - } - - case KRegisterEventHandler: - { - // GUQoS has passed a pointer to its event handler - const TEvent *handler = reinterpret_cast(aOption.Ptr()); - iQosEventHandler = static_cast(handler->iEvent); - ASSERT(iQosEventHandler); - return KErrNone; - } - - case KContextSetEvents: - { - if (!AreQoSEventsEnabled()) - { - // Event handler must be registered first - return KErrGeneral; - } - const TBool* eventsEnabledPtr = reinterpret_cast(aOption.Ptr()); - ASSERT(eventsEnabledPtr); - iQosEventsEnabled = *eventsEnabledPtr; - - // Has a primary PDP context has already been created? - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = BindMan()->GetAnyRefL()); - const TBool havePrimary(rc == KErrNone && (ref->State() == ESpudUp || ref->State() == ESpudFlowOff || ref->State() == ESpudSuspended || ref->State() == ESpudFlowOffAndSuspended)); - - if (iQosEventsEnabled && havePrimary) - { - // iPrimaryContextId == KPrimaryContextId == 0 at startup - SendPrimaryContextCreated(iPrimaryContextId, KErrNone); - } - return KErrNone; - } - - case KNifSetDefaultQoS: - { - ASSERT(aOption.Ptr()); - const TContextParameters& opt = *reinterpret_cast(aOption.Ptr()); - - if (!iPdpFsmInterface.IsInitialised()) - { - __FLOG_0(_L("CSpudMan::GuqosInput: iPdpFsmInterface not initialised, parking KNifSetDefaultQoS.")); - - if (iParkedDefaultQoS == NULL) - { - TRAPD(err, iParkedDefaultQoS = HBufC8::NewL (sizeof (TContextParameters))); - if (err != KErrNone) - { - __FLOG_0(_L("CSpudMan::GuqosInput: Failed to park default QoS.")); - return err; - } - } - - iParkedDefaultQoS->Des().Copy (aOption); - - return KErrNone; - } - - CSpudBinderRef* ref = NULL; - // Lower NIF for primary context has already been loaded by factory - TRAPD(rc, ref = BindMan()->GetRefL(iPrimaryContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - - ASSERT(ref->State() == ESpudInactive); - ref->SetState(ESpudHaveQos); - -#ifdef SYMBIAN_NETWORKING_UMTSR5 - // Store R5 QoS parameters - RPacketQoS::TQoSR5Requested qos; -#else - // Store QoS parameters - RPacketQoS::TQoSR99_R4Requested qos; -#endif -// SYMBIAN_NETWORKING_UMTSR5 - - opt.iContextConfig.GetUMTSQoSReq(qos); - rc = iPdpFsmInterface.Set(iPrimaryContextId, qos); - - if (rc != KErrNone) - { - __FLOG_1(_L("Setting default QoS on primary context failed with error [%d]. SPUD will shut down."), rc); - SetTerminateError(iPrimaryContextId, rc); - - SendPrimaryContextCreated(iPrimaryContextId, rc); // Notify GUQoS of error - - // At this point we know that SPUD is about to shut down, because we could not bring the - // primary context UP. - - //********************************************************************************************** - // Tell GUQoS to stop bothering SPUD. - // GUQoS returns the favour by turning off the NIF events within this very call. - // N.B.: "DEF055691 GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack - // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event. - // As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only - // from the destructor. Once this defect is fixed, the following line must be uncommented: - // SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached); - //********************************************************************************************** - - __FLOG_1(_L("Setting default QoS on primary context failed: mark lower NIF binder for context[%d] for async deletion."), iPrimaryContextId); - // We are about to delete the primary context NIF: this will notify Nifman that SPUD is finished. - DisposeOfBinder(ref); - } - - return KErrNone; - } - - case KContextCreate: - { - ASSERT(aOption.Ptr()); - TContextParameters& opt=*reinterpret_cast(const_cast(aOption.Ptr())); - ASSERT(opt.iContextType == ESecondaryContext); - - TContextId id(KAllContexts); // placeholder context ID - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = BindMan()->GetNewRefForSecondaryL(id);); - if(KErrNone != rc) - { - __FLOG_1(_L("Error %d creating a binder for the lower NIF"), rc); - opt.iReasonCode = rc; // The error code is the only argument we can pass to GUQoS, because there is no context. - return KErrNone; - } - - - TRAP(rc, BindMan()->LoadNifL(iName, *ref);) - if (rc != KErrNone) - { - __FLOG_1(_L("Error %d loading the lower NIF"), rc); - FillInParameters(opt, id, rc); - return KErrNone; - } - - ASSERT(ref->IsBound()); - ref->SetState(ESpudStartingSecondary); - - - // Reset the default QoS and TFT here. KContextQoSSet should arrive soon - // with the proper values. -#ifdef SYMBIAN_NETWORKING_UMTSR5 - RPacketQoS::TQoSR5Requested qos; -#else - RPacketQoS::TQoSR99_R4Requested qos; -#endif -// SYMBIAN_NETWORKING_UMTSR5 - rc = iPdpFsmInterface.Set(id, qos); - - TTFTInfo tft; - rc = iPdpFsmInterface.Set(id, tft); - - // Pass in the new context ID to SpudFsm to use for the new context - - // Notify SpudFsm - __FLOG_1(_L("Sending SpudFsm event ECreateSecondaryPDPContext context %d"), id); - rc = iPdpFsmInterface.Input(id, ECreateSecondaryPDPContext); - - // Set up the synchronous response - FillInParameters(opt, id, rc); - return KErrNone; - } - - case KContextDelete: - { - ASSERT(aOption.Ptr()); - TContextParameters& opt = *reinterpret_cast(const_cast(aOption.Ptr())); - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId)); - if (rc != KErrNone) - { - __FLOG_1(_L("Error: KContextDelete specifies context %d which does not exist"), opt.iContextInfo.iContextId); - opt.iReasonCode = rc; // The error code is the only argument we can pass to GUQoS, because there is no context. - return KErrNone; - } - - ASSERT(ref->IsBound()); - __FLOG_3(_L("KContextDelete context[%d] in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State()); - - switch (ref->State()) - { - // NIF is up: need to stop the NIF first, then delete the binder. - case ESpudGettingNegQoS: - case ESpudStartingSecondaryLowerNif: - // Assumption: GUQoS will never delete primary context. - case ESpudUp: - case ESpudFlowOff: - case ESpudSuspended: - case ESpudFlowOffAndSuspended: - ref->SetState(ESpudContextDelete); - - if(BindMan()->IsLastContext(opt.iContextInfo.iContextId)) // Are we about to shutdown after this? - { - SetTerminateError(KErrCancel); // KErrCancel is normally used to indicate "graceful" - } // user-initiated shutdown. - - // GUQoS ordered the shutdown: Network is still OK: initiate graceful shutdown of the lower NIF. - ref->NifLink()->Stop(KErrCancel, MNifIfNotify::EDisconnect); - break; - - case ESpudStartingSecondary: // NIF not started: need to delete the context. - ref->SetState(ESpudWaitLinkDown); - - // Delete context via SpudFsm - __FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), opt.iContextInfo.iContextId); - rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextDelete); - ASSERT(rc == KErrNone); - break; - - case ESpudWaitLinkDown: - // We're in the middle of deleting. Ignore this request. - break; - - case ESpudLinkDown: - // We're in the middle of deleting, but we no longer need to notify - // GUQoS when done. - ref->SetState(ESpudWaitLinkDown); - break; - - case ESpudWaitBinderDelete: // context deleted, NIF about to be deleted: ignore. - break; - - default: - __FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State()); - ASSERT(EFalse); - break; - } - - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - case KContextActivate: - { - ASSERT(aOption.Ptr()); - TContextParameters& opt=*reinterpret_cast(const_cast(aOption.Ptr())); - CSpudBinderRef* ref = NULL; - // Validate context ID - TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId)); - if (KErrNone != rc) - { - opt.iReasonCode = rc; // Can supply error code only, as the context does not exist. - __FLOG_1(_L("Error: KContextActivate specifies context %d which does not exist."), opt.iContextInfo.iContextId); - return KErrNone; - } - - if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete) - { - __FLOG_1(_L("Error: KContextActivate specifies context %d which is not bound to lower NIF."), opt.iContextInfo.iContextId); - rc = KErrNotReady; // that's what the GuQoS docs say - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - __FLOG_3(_L("KContextActivate context %d in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State()); - - ASSERT(ref->State() == ESpudStartingSecondary || ref->State() == ESpudUp); - - - // Notify SpudFsm - __FLOG_1(_L("Sending SpudFsm event EContextActivate context %d"), opt.iContextInfo.iContextId); - rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextActivate); - // Set up the synchronous response - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - case KContextQoSSet: - { - TContextParameters& opt=*reinterpret_cast(const_cast(aOption.Ptr())); - CSpudBinderRef* ref = NULL; - // Validate context ID - TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId)); - if (KErrNone != rc) - { - __FLOG_1(_L("Error: KContextQoSSet specifies context %d which does not exist"), opt.iContextInfo.iContextId); - opt.iReasonCode = rc; // Can only supply error code, as the context does not exist. - return KErrNone; - } - - if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete) - { - __FLOG_1(_L("Error: KContextQoSSet specifies context %d which is not bound to the lower NIF."), opt.iContextInfo.iContextId); - rc = KErrNotReady; // that's what the GuQoS docs say - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - __FLOG_3(_L("KContextQoSSet context %d in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State()); - - ASSERT(ref->State() == ESpudStartingSecondary - || ref->State() == ESpudUp - || ref->State() == ESpudFlowOff - || ref->State() == ESpudSuspended - || ref->State() == ESpudFlowOffAndSuspended - || ref->State() == ESpudLinkDown ); - -#ifdef SYMBIAN_NETWORKING_UMTSR5 - RPacketQoS::TQoSR5Requested qos; -#else - RPacketQoS::TQoSR99_R4Requested qos; -#endif -// SYMBIAN_NETWORKING_UMTSR5 - - // Store QoS parameters - opt.iContextConfig.GetUMTSQoSReq(qos); - rc = iPdpFsmInterface.Set(opt.iContextInfo.iContextId, qos); - - // Notify SpudFsm - if (rc == KErrNone) - { - __FLOG_1(_L("Sending SpudFsm event EContextQoSSet context %d"), opt.iContextInfo.iContextId); - rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextQoSSet); - } - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - case KContextTFTModify: - { - TContextParameters& opt=*reinterpret_cast(const_cast(aOption.Ptr())); - CSpudBinderRef* ref = NULL; - // Validate context ID - TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId)); - if (KErrNone != rc) - { - __FLOG_1(_L("Error: KContextTFTModify specifies context %d which does not exist"), opt.iContextInfo.iContextId); - opt.iReasonCode = rc; // Can only supply error code as the context does not exist. - return KErrNone; - } - - // keep local reference to Primary Context up to date - if (opt.iContextType == EPrimaryContext) - { - iPrimaryContextId = opt.iContextInfo.iContextId; - } - - if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete) - { - __FLOG_1(_L("Error: KContextTFTModify specifies context %d which is not bound to the lower NIF."), opt.iContextInfo.iContextId); - rc = KErrNotReady; // that's what the GuQoS docs say - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - __FLOG_3(_L("KContextTFTModify context %d in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State()); - - ASSERT(ref->State() == ESpudStartingSecondary || - ref->State() == ESpudUp || - ref->State() == ESpudWaitLinkDown || - ref->State() == ESpudLinkDown || - ref->State() == ESpudGettingNegQoS); - // It is assumed that the TFT can be modified before the ctx reported activation - - // Store TFT parameters - TTFTInfo tft; - opt.iContextConfig.GetTFTInfo(tft); - - rc = iPdpFsmInterface.Set(opt.iContextInfo.iContextId, tft); - if (rc != KErrNone) - { - __FLOG_1(_L("Error %d setting TFT"), rc); - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - rc = iPdpFsmInterface.Set(opt.iContextInfo.iContextId, opt.iTFTOperationCode); - if (rc != KErrNone) - { - __FLOG_1(_L("Error %d setting TFT operation code"), rc); - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - // Notify SpudFsm - __FLOG_1(_L("Sending SpudFsm event EContextTFTModify context %d"), opt.iContextInfo.iContextId); - rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextTFTModify); - - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - case KContextModifyActive: - { - TContextParameters& opt=*reinterpret_cast(const_cast(aOption.Ptr())); - CSpudBinderRef* ref = NULL; - // Validate context ID - TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId)); - if (KErrNone != rc) - { - __FLOG_1(_L("Error: KContextModifyActive specifies context %d which does not exist"), opt.iContextInfo.iContextId); - opt.iReasonCode = rc; - return KErrNone; - } - - if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete) - { - __FLOG_1(_L("Error: KContextModifyActive specifies context %d which is not bound to the lower NIF."), opt.iContextInfo.iContextId); - rc = KErrNotReady; // that's what the GuQoS docs say - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - // Notify SpudFsm - __FLOG_1(_L("Sending SpudFsm event EContextModifyActive context %d"), opt.iContextInfo.iContextId); - rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextModifyActive); - - FillInParameters(opt, opt.iContextInfo.iContextId, rc); - return KErrNone; - } - - case KInitialisePdpFsm: - { - MPdpFsmInterface* pdpFsm = *reinterpret_cast(const_cast(aOption.Ptr())); - iPdpFsmInterface.Init(pdpFsm); - return KErrNone; - } - - default: - __FLOG_1(_L("Unhandled event %d"), aName); - break; - } - return KErrNotSupported; - } - -/** -Receives link up indication from a lower NIF. - -@param aContextId PDP context ID of the associated lower NIF -*/ -void CSpudMan::LinkLayerUp(TContextId aContextId) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound() && ref->State() != ESpudWaitBinderDelete); - - __FLOG_3(_L("Lower NIF LinkLayerUp on context[%d], in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - switch (ref->State()) - { - case ESpudStartingPrimaryLowerNif: - { - ref->SetState(ESpudUp); - if (AreQoSEventsEnabled()) - { - SendPrimaryContextCreated(aContextId, KErrNone); - } - // If QoS is not yet enabled, SendPrimaryContextCreated() will be called when it is - - Notify()->LinkLayerUp(); - - // If mobile IP is enabled, this progress notification should not be sent here. - // This will need to be addressed if MIP is ever enabled for UMTS. - Notify()->IfProgress(KLinkLayerOpen, KErrNone); - } - break; - - case ESpudStartingSecondaryLowerNif: - { - // lower nif is up, now get the Negotiated QoS - ref->SetState(ESpudGettingNegQoS); - - TInt rc = iPdpFsmInterface.Input(aContextId, EGetNegQoS); - ASSERT(rc == KErrNone); - // Now wait for retrieval of negotiated QoS. - // The following 2 functions will be fired from CSpudMan::HandleGetNegQoSEvent(): - // FillInContextConfig(iTempContextConfig, aContextId); - // SendContextActivateEvent(aContextId, iTempContextConfig, KErrNone); - } - break; - - default: - __FLOG_3(_L("Lower NIF LinkLayerUp on context[%d], in unexpected state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - ASSERT(EFalse); - } - } - -/** -Receives link down indication from a lower NIF. - -@param aContextId Valid PDP context ID of the associated lower NIF -@param aReason A Symbian OS error code indicating the reason for the link closing down -@param aAction The action that should be taken as a result of link layer down being signalled -*/ -void CSpudMan::LinkLayerDown(TContextId aContextId, TInt aReason, MNifIfNotify::TAction aAction) - { - __FLOG_3(_L("CSpudMan::LinkLayerDown: context %d reason %d action %d"), aContextId, aReason, aAction); - - if (aAction == MNifIfNotify::ENoAction) - { - // This call indicates a renegotiation of the lower link, not that the link has - // actually gone down. This is of no interest to SPUD. - __FLOG_0(_L("Ignoring MNifIfNotify::ENoAction")); - return; - } - - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - - - TBool isUpperFlowOn = EFalse; // Can GUQoS attempt to send on this PDP context? - - switch (ref->State()) - { - case ESpudUp: - isUpperFlowOn = ETrue; // ESpudUp is the only state where GUQoS is allowed to send on us. - // Fall through - case ESpudFlowOff:// NIF & context were activated succcessfully. - case ESpudSuspended: - case ESpudFlowOffAndSuspended: - ref->SetState(ESpudLinkDown); // Must Notify GUQoS that context is down. - - // Must inform upper layers they can no longer send on this context. - if (isUpperFlowOn && AreQoSEventsEnabled()) - { - // At this point the context status does not indicate to GUQoS that the context is about to go down. - // Most likely, the status is EStatusActive, indicating that the context can handle requests. - // Since the lower NIF is down, we are about to delete the context, so logically, this context - // is EStatusDeactivating.(From spudman's PoV, a context is a union of lower NIF and ETel's RPacketContext) - // GUQoS does not know this, it may try to issue requests, - // such as send packets on this context, modify TFT, modify QoS, etc. - // Note: this does not seem to happen, but it is feasible. - - // N.B. Ideally, we should signal context change status in not just in EStateUp, but in - // EStateFlowOff etc, i.e. any state in which the context is alive. Unfortunately, GUQoS - // does not allow us to do this - there is no pure "ContextStatusChange" upcall on GUQoS. - // Context Parameters Change upcall should not be used, because GUQoS interprets it as a - // QoS parameters change, and sends QoSEventAdapt to the QoS framework. This is wrong. - // - // We could send ContextBlocked in FlowOff / Suspended states, however, this is problematic, - // because GUQoS has already received one of these notifications. We could "trick" it and cycle - // the state (send Flow On / Resume, then Flow Off / Suspend again), but this hackery should be - // avoided unless absolutely necessary. So far, GUQoS does not seem to do anything beside sending - // a packet on a deactivaing context, so we only worry about it. - - // N.B. SpudFSM is asynchronous, it will not issue a an actual deletion request on ETel until this RunL - // returns. This means that the context status will not be updated to EStatusDeactiving in ETel - // until then, so when we fill in context paramters, the status is going to be EStatusActive. - // We "sneak in" the correct status by overriding it. Doing it in SpudFSM would be wrong, because - // SpudFSM reflects the ETel side of the context, so overriding the status there is misleading, - // because it can be used internally by SpudFSM / SpudTel. - - __FLOG_0(_L("Upper flow on the context is On: flow Off GUQoS to prevent it from sending on a context with dead lower NIF.")); - iContextStatusOverride = RPacketContext::EStatusDeactivating; - SendContextBlockedEvent(aContextId); // resets the override - isUpperFlowOn = EFalse; - } - - // The only way we can notify GUQoS once the context has been activated is - // to delete it via the SpudFsm - __FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), aContextId); - rc = iPdpFsmInterface.Input(aContextId, EContextDelete); - __FLOG_1(_L("SpudFsm::Input() returned status %d"), rc); - if (rc == KErrNotReady) //This is becuase the FSM has been shut down via UMTSGPRSSCPR - { - HandleContextDeleteEvent(aContextId, aReason); //Just pretend that the fsm returned something sensible - } - ASSERT(rc == KErrNone || rc == KErrNotReady); - break; - - case ESpudGettingNegQoS: // CNifIfLink::Stop will handle this just as if the NIF was still being CNifIfLink::Start'ed. - case ESpudStartingSecondaryLowerNif: // Attempt to bring up the lower NIF was made. - ref->SetState(ESpudStartingSecondary); // GUQoS should delete us later. - // Notify GUQoS that Activation failed. It will take the control from here, most likely deleting the context. - FillInContextConfig(iTempContextConfig, aContextId); - if(ref->Error() != KErrNone) - { - SendContextActivateEvent(aContextId, iTempContextConfig, ref->Error()); - } - else - { - SendContextActivateEvent(aContextId, iTempContextConfig, aReason); - } - break; - - case ESpudContextDelete: - ref->SetState(ESpudWaitLinkDown); // GUQoS triggered us: don't need to notify it. - - // Delete context via SpudFsm - __FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), aContextId); - rc = iPdpFsmInterface.Input(aContextId, EContextDelete); - __FLOG_1(_L("SpudFsm::Input() returned status %d"), rc); - ASSERT(rc == KErrNone); - break; - - case ESpudStartingSecondary: - case ESpudLinkDown: // Added for INC066156. - case ESpudWaitLinkDown: - // Link has finally gone down. Context is already deleted. - __FLOG_1(_L("Lower NIF reported LinkLayerDown: mark the binder for context[%d] for async deletion"), aContextId); - DisposeOfBinder(ref); - break; - - case ESpudStartingPrimaryLowerNif: - { - SetTerminateError(aContextId, aReason); // SPUD is going to terminate. - SetTerminateError(KErrCouldNotConnect); - - // The primary context is managed by SPUD. We delete it ourselves. - __FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), aContextId); - ref->SetState(ESpudWaitLinkDown); - rc = iPdpFsmInterface.Input(aContextId, EContextDelete); - __FLOG_1(_L("SpudFsm::Input() returned status %d"), rc); - ASSERT(rc == KErrNone); - - // Meanwhile, notify GUQoS about the failed primary creation - if (AreQoSEventsEnabled()) - { - SendPrimaryContextCreated(aContextId, aReason); - } - break; - } - - default: - __FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State()); - ASSERT(EFalse); - break; - } - } - -/** -Receives flow off indication from a lower NIF. - -@param aContextId Valid PDP context ID of the associated lower NIF -*/ -void CSpudMan::StopSending(TContextId aContextId) - { - __FLOG_1(_L("CSpudMan::StopSending context %d"), aContextId); - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - switch (ref->State()) - { - case ESpudUp: - ref->SetState(ESpudFlowOff); - if (AreQoSEventsEnabled()) - { - SendContextBlockedEvent(aContextId); - } - break; - - case ESpudSuspended: - ref->SetState(ESpudFlowOffAndSuspended); - break; - - case ESpudContextDelete: - case ESpudWaitLinkDown: - case ESpudLinkDown: //sometimes this leaks in - // ignore - break; - - default: - // error - __FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State()); - ASSERT(EFalse); - break; - } - } - -/** -Receives flow on indication from a lower NIF. - -@param aContextId Valid PDP context ID of the associated lower NIF -*/ -void CSpudMan::StartSending(TContextId aContextId) - { - __FLOG_1(_L("CSpudMan::StartSending context %d"), aContextId); - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - __FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State()); - switch (ref->State()) - { - case ESpudGettingNegQoS: // Lower NIF for the 2ndary ctx is up, waiting for negotiated QoS. - break; // GUQoS, TCP/IP stack will be notified when negotiated QoS is retrieved. - // Notes: - // 1.there is a *potential* race condition where the negotiated QoS is retrived before lower NIF signals StartSending. - // This does not seem to happen with PPP. If this happens somehow, the ctx will be in the "UP" state and it will be handled correctly. - // 2. Theoretically, the lower NIF may report LinkLayerUp (triggering retrieval of negotiated QoS), then signal - // StartSending much later (e.g. a PPP implementation singalling LinkLayerUp from LCP, but StartSending from NCP). - // SPUD CANNOT HANDLE THIS. - // Existing Raw IP and PPP NIFs signal StartSending immediately after LinkLayerUp, so this has no consequences. - - case ESpudUp: - // This can happen for the initial StartSending after the lower NIF comes up - // Treat it the same as ESpudFlowOff and fall through. - case ESpudFlowOff: - ref->SetState(ESpudUp); - - // This must only be done AFTER the KPrimaryContextCreated event is sent (which in this state it is) - // It's not clear if StartSending is needed/allowed in addition to the GUQoS event. - BindMan()->SpudProtocol()->DoStartSending(); - - if (AreQoSEventsEnabled()) - { - SendContextUnblockedEvent(aContextId); - } - break; - - case ESpudFlowOffAndSuspended: - ref->SetState(ESpudSuspended); - break; - - case ESpudSuspended: - case ESpudContextDelete: - case ESpudWaitLinkDown: - // ignore - __FLOG_1(_L("Ignored StartSending on context %d (this should be OK)"), aContextId); - break; - - default: - // We have encountered a serious problem. If we get StartSending before reaching the ESpudUp - // state, we'll lose it and the upper networking protocol will never be notified. - // As long as the lower NIF calls LinkLayerUp before StartSending, we'll be fine. - __FLOG_1(_L("Can't send unblocked event now on context %d; this may cause problems"), aContextId); - ASSERT(EFalse); - break; - } - } - - -//***************************************************************************** -// Event senders to GUQoS -//***************************************************************************** - -/** -Sends event to GUQoS. - -@param aName event identifier -@param aOption TPckg<> event data -*/ -void CSpudMan::RaiseEvent(TUint aName, TDes8& aOption) const - { - __FLOG_2(_L("Sending event %S(%d) to GUQoS"), SpudFsmEventToText(aName), aName); - iQosEventHandler->Event(reinterpret_cast(iBindMan->SpudMux()), aName, aOption); - } - -/** -Fills in common event parameters for the given context. - -@param aParams parameter structure -@param aContextId Valid PDP context ID -*/ -void CSpudMan::FillInParameters(TContextParameters& aParams, TContextId aContextId, TInt aError) const - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = BindMan()->GetRefL(aContextId)); - ASSERT(rc == KErrNone); - - TContextType type(EContextTypeUnknown); - if (rc == KErrNone) - { - switch (ref->State()) - { - case ESpudHaveQos: - case ESpudCreatingPrimary: - case ESpudStartingPrimary: - type = EPrimaryContext; - break; - - case ESpudStartingSecondary: - type = ESecondaryContext; - break; - - default: - type = (aContextId == iPrimaryContextId) ? EPrimaryContext : ESecondaryContext;; - break; - } - } - aParams.iContextType = type; // Context type - aParams.iReasonCode = aError; // Error code - //aParams.iContextInfo.iStatus = StateToStatus(*ref); - iPdpFsmInterface.Get(aContextId, aParams.iContextInfo.iStatus); - aParams.iContextInfo.iContextId = aContextId; - } - -/** -Fill in context configuration parameter structure using SpudFsm's parameters. - -@param aConfig parameter structure -@param aContextId PDP context ID -*/ -void CSpudMan::FillInContextConfig(TContextConfig& aConfig, TContextId aContextId) const - { -#ifdef SYMBIAN_NETWORKING_UMTSR5 - RPacketQoS::TQoSR5Negotiated qos; -#else - RPacketQoS::TQoSR99_R4Negotiated qos; -#endif -// SYMBIAN_NETWORKING_UMTSR5 - - iPdpFsmInterface.Get(aContextId, qos); - aConfig.SetUMTSQoSNeg(qos); - - iPdpFsmInterface.Get(aContextId, iTempTftInfo); - aConfig.SetTFTInfo(iTempTftInfo); - - iPdpFsmInterface.Get(aContextId, iTempGprsContext); - aConfig.SetContextConfig(iTempGprsContext); - } - -/** -Sends KPrimaryContextCreated event to GUQoS. -*/ -void CSpudMan::SendPrimaryContextCreated(TContextId aContextId, TInt aError) - { - __FLOG_2(_L("SendPrimaryContextCreated context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - // We make this assumption in various places - ASSERT(aContextId == 0); - - TContextParameters primaryContextCreatedEvent; - FillInParameters(primaryContextCreatedEvent, aContextId, aError); - TPckg event(primaryContextCreatedEvent); - RaiseEvent(KPrimaryContextCreated, event); - } - - -/** -Sends KSecondaryContextCreated event to GUQoS. - -@param aContextId Context ID -@param aError error code -*/ -void CSpudMan::SendSecondaryContextCreated(TContextId aContextId, TInt aError) - { - __FLOG_2(_L("SendSecondaryContextCreated context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - // We make this assumption in various places - ASSERT(aContextId != 0); - - TContextParameters event; - FillInParameters(event, aContextId, aError); - TPckg eventPckg(event); - RaiseEvent(KSecondaryContextCreated, eventPckg); - } - - -/** -Sends KContextBlockedEvent event to GUQoS. -*/ -void CSpudMan::SendContextBlockedEvent(TContextId aContextId) - { - __FLOG_2(_L("SendContextBlockedEvent context %d error %d"), aContextId, KErrNone); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId); - - /** The status we want to signal to GUQoS may be different from the context status we get from SpudFSM - E.g., if we are about to deactivate the context, the logical status of the context is EStatusDeactivating, rather than - EStatusActive, even though that's what SpudFSM will tell us */ - if(RPacketContext::EStatusUnknown != iContextStatusOverride) - { - __FLOG_2(_L("SendContextBlockedEvent: context status overriden to %d, original: %d."), - iContextStatusOverride, event.iContextInfo.iStatus); - - event.iContextInfo.iStatus = iContextStatusOverride; - iContextStatusOverride = RPacketContext::EStatusUnknown; - } - - TPckg eventPckg(event); - RaiseEvent(KContextBlockedEvent, eventPckg); - } - -/** -Sends KContextUnblockedEvent event to GUQoS. -*/ -void CSpudMan::SendContextUnblockedEvent(TContextId aContextId) - { - __FLOG_2(_L("SendContextUnblockedEvent context %d error %d"), aContextId, KErrNone); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId); - TPckg eventPckg(event); - RaiseEvent(KContextUnblockedEvent, eventPckg); - } - -/** -Sends KContextQoSSetEvent event to GUQoS. - -@param aContextId Context ID -@param aError error code -*/ -void CSpudMan::SendContextQoSSetEvent(TContextId aContextId, TInt aError) - { - __FLOG_2(_L("SendContextQoSSetEvent context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId, aError); - TPckg eventPckg(event); - RaiseEvent(KContextQoSSetEvent, eventPckg); - } - -/** -Sends KContextTFTModifiedEvent event to GUQoS. - -@param aContextId Context ID -#param aTFTOperationCode TFT operation code -@param aError error code -*/ -void CSpudMan::SendContextTFTModifiedEvent(TContextId aContextId, TTFTOperationCode aTFTOperationCode, TInt aError) - { - __FLOG_2(_L("SendContextTFTModifiedEvent context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId, aError); - // Also need to fill in TTFTOperationCode, an undocumented requirement - event.iTFTOperationCode = aTFTOperationCode; - TPckg eventPckg(event); - RaiseEvent(KContextTFTModifiedEvent, eventPckg); - } - -/** -Sends KContextModifyActiveEvent event to GUQoS. - -@param aContextId Context ID -@param aContextConfig Configuration parameters for this context -@param aError error code -*/ -void CSpudMan::SendContextModifyActiveEvent(TContextId aContextId, TContextConfig& aContextConfig, TInt aError) - { - __FLOG_2(_L("SendContextModifyActiveEvent context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId, aError); - event.iContextConfig = aContextConfig; - TPckg eventPckg(event); - RaiseEvent(KContextModifyActiveEvent, eventPckg); - } - -/** -Sends KContextActivateEvent event to GUQoS. - -@param aContextId Context ID -@param aContextConfig Configuration parameters for this context -@param aError error code -*/ -void CSpudMan::SendContextActivateEvent(TContextId aContextId, TContextConfig& aContextConfig, TInt aError) - { - __FLOG_2(_L("SendContextActivateEvent context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId, aError); - event.iContextConfig = aContextConfig; - TPckg eventPckg(event); - RaiseEvent(KContextActivateEvent, eventPckg); - } - -/** -Sends KContextParametersChangeEvent event to GUQoS. - -@param aContextId Context ID -@param aContextConfig Configuration parameters for this context -@param aError error code -*/ -void CSpudMan::SendContextParametersChangeEvent(TContextId aContextId, TContextConfig& aContextConfig, TInt aError) - { - __FLOG_2(_L("SendContextParametersChangeEvent context %d error %d"), aContextId, aError); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId, aError); - event.iContextConfig = aContextConfig; - TPckg eventPckg(event); - RaiseEvent(KContextParametersChangeEvent, eventPckg); - } - -/** -Sends KContextDeleteEvent event to GUQoS. - -@param aContextId Context ID -*/ -void CSpudMan::SendContextDeleteEvent(TContextId aContextId) - { - __FLOG_2(_L("SendContextDeleteEvent context %d error %d"), aContextId, KErrNone); - - if (!iQosEventsEnabled) - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TContextParameters event; - FillInParameters(event, aContextId); - TPckg eventPckg(event); - RaiseEvent(KContextDeleteEvent, eventPckg); - } - -/** -Sends KNetworkStatusEvent event to GUQoS. - -@param aEventCode Event code -@param aStatus Network status -*/ -void CSpudMan::SendNetworkStatusEvent(TNetworkEventCode aEventCode, RPacketService::TStatus aStatus) - { - __FLOG_2(_L("SendNetworkStatusEvent event code %d status %d"), aEventCode, aStatus); - - if (!iQosEventsEnabled) // QoS events not turned on yet, or have been turned off by GUQoS - { - __FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?")); - return; - } - - TNetworkParameters event; - event.iNetworkEventCode = aEventCode; - event.iNetworkStatus = aStatus; - TPckg eventPckg(event); - RaiseEvent(KNetworkStatusEvent, eventPckg); - } - - -//***************************************************************************** -// CNifIfLink methods -//***************************************************************************** - - -/** -Return the link protocol handler object. - -@param aName Protocol name desired -@return Pointer to link protocol handler (ownership is transferred) -*/ -CNifIfBase* CSpudMan::GetBinderL(const TDesC& aName) - { - __FLOG_1(_L("CSpudMan::GetBinderL %S"), &aName); - iName = aName; - return static_cast(iBindMan->TransferSpudMux()); - } - -/** -Return information about the SPUD NIF. - -@param aInfo Receives the NIF interface info -*/ -void CSpudMan::Info(TNifIfInfo& aInfo) const - { - CSpudBinderRef* ref = NULL; - // Get the binder for the first (default) lower NIF. - TRAPD(err, ref = iBindMan->GetAnyRefL()); - if (err == KErrNone) - { - // Read the protocol supported value from the lower NIF - ref->NifLink()->Info(aInfo); - ASSERT(aInfo.iFlags == (KNifIfIsBase | KNifIfUsesNotify | KNifIfIsLink | KNifIfCreatedByFactory | KNifIfCreatesBinder)); - } - else - { - aInfo.iProtocolSupported=KProtocolUnknown; - } - - aInfo.iVersion = TVersion(KSpudMajorVersionNumber, KSpudMinorVersionNumber, KSpudBuildVersionNumber); - aInfo.iFlags = KNifIfIsBase | - KNifIfUsesNotify | - KNifIfIsLink | - KNifIfCreatedByFactory | - KNifIfCreatesBinder; - aInfo.iName = KSpudName; - } - -/** -Processes notifications from Agent - -@param aEvent Event type -@param aInfo Data relating to event - -@return Error code -*/ -TInt CSpudMan::Notification(TAgentToNifEventType aEvent, void * aInfo) - { - __FLOG_1(_L("CSpudMan::Notification event %d"), aEvent); - TInt rc = KErrNotSupported; - switch (aEvent) - { - case EAgentToNifEventTypeModifyInitialTimer: - case EAgentToNifEventTypeDisableTimers: - case EAgentToNifEventTypeEnableTimers: - case EAgentToNifEventTsyConfig: - case EAgentToNifEventTsyConnectionSpeed: - // Send notification to all lower NIFs - rc = KErrNotReady; - TContextId i; - for (i=0; i < KMaxPdpContexts; ++i) - { - CSpudBinderRef* ref = NULL; - TRAP(rc, ref = iBindMan->GetRefL(i)); - if (rc == KErrNone) - { - rc = ref->NifLink()->Notification(aEvent, aInfo); - } - } - break; - - case EAgentToNifEventTypeGetDataTransfer: - { - TPckg* totalDataPackage = (TPckg*) aInfo; - RPacketContext::TDataVolume& totalData = (*totalDataPackage)(); - totalData.iBytesSent = 0; - totalData.iOverflowCounterSent = 0; - totalData.iBytesReceived = 0; - totalData.iOverflowCounterReceived = 0; - - RPacketContext::TDataVolume data; - TPckg dataPackage(data); - - // Add up data reported by all NIFs - rc = KErrNotReady; - TContextId i; - for (i=0; i < KMaxPdpContexts; ++i) - { - CSpudBinderRef* ref = NULL; - TRAP(rc, ref = iBindMan->GetRefL(i)); - if (rc == KErrNone) - { - rc = ref->NifLink()->Notification(aEvent, &dataPackage); - if (rc == KErrNone) - { - totalData.iBytesSent += data.iBytesSent; - totalData.iOverflowCounterSent += data.iOverflowCounterSent; - totalData.iBytesReceived += data.iBytesReceived; - totalData.iOverflowCounterReceived += data.iOverflowCounterReceived; - } - } - } - break; - } - - case EAgentToNifEventTypeDisableConnection: - // TODO: what to do with this? - default: - __FLOG_1(_L("Notification event %d was ignored"), aEvent); - break; - } - - return rc; - } - - -/** -Start the link. -At this point only the primary PDP context is valid. - -@return Error code -*/ -TInt CSpudMan::Start() - { - __FLOG_1(_L("CSpudMan::Start(0x%x)"), this); - - // SpudTel needs TSY name from CommDb - TName tsyName; - ReadTsyName(tsyName); - - // Initialise SpudFsm - TRAPD(err, InitPdpFsmInterfaceL()); - if (err != KErrNone) - { - __FLOG_1(_L("CSpudMan::Start: Failed to initialise the PDP Fsm Interface,Error = %d"),err); - return err; - } - - // Open SpudFsm - TRAP(err, iPdpFsmInterface.OpenL(this, tsyName)); - if (err != KErrNone) - { - __FLOG_1(_L("CSpudMan::Start: Failed to open the PDP Fsm Interface,Error = %d"),err); - return err; - } - - - // re-initialise the temporary data structure before retrieving - // GPRS config parameters from CommDB - __FLOG_0(_L("CSpudMan::Start: Getting default GPRS settings from Commdb")); - RetrieveGprsConfig(iTempGprsContext); - - TRAP(err, SetupSipServerAddrRetrievalL(iTempGprsContext.iProtocolConfigOption);); - -#ifdef SYMBIAN_NETWORKING_UMTSR5 - // Add the IMCN Signalling Status flag. IM CN status flag is retrieved from the Database - // Request For the status of IM CN dedicated signalling context - TRAP(err,SetIMCNSignallingFlagPcoL(iTempGprsContext.iProtocolConfigOption)); - - // Not sure what can be done after trapping the error, because its not an error condition for starting of - // Primary PDP context. -#ifdef __FLOG_ACTIVE - if(err != KErrNone) - { - __FLOG_1(_L("CSpudMan::Start: Failed to set IM CN signalling Flag.Error = %d"),err); - } -#endif -#endif // SYMBIAN_NETWORKING_UMTSR5 - - iPdpFsmInterface.Set(iPrimaryContextId, iTempGprsContext); - if (err != KErrNone) - { - __FLOG_1(_L("CSpudMan::Start: Setup sip server address retrieval. Failed with %d"),err); - return err; - } - - if (iParkedDefaultQoS != NULL) - { - __FLOG_0(_L("CSpudMan::Start: Found parked QoS settings from GuQoS")); - - TPtr8 qos(iParkedDefaultQoS->Des()); - GuqosInput (KNifSetDefaultQoS, qos); - - delete iParkedDefaultQoS; - iParkedDefaultQoS = NULL; - } - - CSpudBinderRef* ref = NULL; - // Get the binder for the first (default) lower NIF. - TRAP(err, ref = iBindMan->GetRefL(iPrimaryContextId)); - if (err != KErrNone) - { - __FLOG_0(_L("CSpudMan::Start: Error - no context could be found")); - return err; - } - - ASSERT(ref->State() == ESpudInactive || ref->State() == ESpudHaveQos); - ASSERT(ref->State() != ESpudWaitBinderDelete); - - if (ref->State() == ESpudWaitBinderDelete) - { - return KErrNotReady; - } - - if (ref->State() != ESpudHaveQos) - { - __FLOG_0(_L("CSpudMan::Start: No QoS parameters have been set - is GuQoS present?")); - - // Sets default QoS parameters because either - // 1) they weren't supplied by GUQoS - this shouldn't happen - // 2) or GuQoS has been configured out -#ifdef SYMBIAN_NETWORKING_UMTSR5 - // Sets default R5 QoS parameters because they weren't supplied by GUQoS. - RPacketQoS::TQoSR5Requested qos; - ReadDefaultR5QoS(qos); -#else - RPacketQoS::TQoSR99_R4Requested qos; - ReadDefaultQoS(qos); -#endif -// SYMBIAN_NETWORKING_UMTSR5 - iPdpFsmInterface.Set(iPrimaryContextId, qos); // ignore any error - - } - - // Set default TFT - TTFTInfo tft; - iPdpFsmInterface.Set(iPrimaryContextId, tft); // ignore any error - - - // Have Etel create a context - ref->SetState(ESpudCreatingPrimary); - __FLOG_1(_L("CSpudMan::Start: Sending SpudFsm event ECreatePrimaryPDPContext context %d"), iPrimaryContextId); - TInt rc = iPdpFsmInterface.Input(iPrimaryContextId, ECreatePrimaryPDPContext); - // TODO: handle errors properly - ASSERT(rc == KErrNone); - rc = rc; // Eliminate compiler warning in release builds - - return KErrNone; - } - -/** -Cleanly stop the link. - -@param aReason The reason the link is going down -@param aAction The action to take once the link is down -*/ -void CSpudMan::Stop(TInt aReason, MNifIfNotify::TAction aAction) - { - __FLOG_3(_L("CSpudMan::Stop: reason %d action %d. %d contexts exist."), aReason, aAction, BindMan()->NumContexts()); - ASSERT(BindMan()->NumContexts()); // Primary PDP context is created in the factory. - - SetTerminateError(aReason); // Store this error code for use when the SPUD goes down - if (AreQoSEventsEnabled()) - { - // Spud was administratively stopped. It can be some time before SPUD signals LinkLayerDown. - // In the meanwhile, we can receive requests from GUQoS that can interfere with the shutdown. - // To prevent this, we tell GUQoS to stop bothering SPUD. - // GUQoS returns the favour by turning off the NIF events within this very call. - // This means we will not send KNetworkInterfaceDown again, even though we'll try. - // ********************************************************************************************* - // N.B.: "DEF055691 GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack - // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event. - // As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only - // from the destructor. Once this defect is fixed, the following line must be uncommented: - // SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached); - //********************************************************************************************** - } - - - // Send Stop to all lower NIFs that were started but not stopped yet - TContextId i; - for (i=0; i < KMaxPdpContexts; ++i) - { - StopContext(i, aReason, aAction); - } - // Eventually, the last lower NIF will call LinkLayerDown to trigger the final cleanup - } - -/** -Cleanly stop a context. - -@param aReason The reason the link is going down -@param aAction The action to take once the link is down -@param aContextId context -*/ -void CSpudMan::StopContext(TContextId aContextId, TInt aReason, MNifIfNotify::TAction aAction) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - if (rc == KErrNone && // Binder exists - ref->IsBound()) // Is bound to a lower NIF. - { - - // Save the Context failure reason - if (ref->Error() == KErrNone) - { - ref->SetError(aReason); - } - - switch(ref->State()) // NIFs in some states are not eligible for Stop. - { - // Context created and NIF started. - case ESpudStartingPrimaryLowerNif: // Waiting for LinkLayerUp/Down - case ESpudStartingSecondaryLowerNif:// Waiting for LinkLayerUp/Down - case ESpudGettingNegQoS: // Waiting for retrieval of negotiated QoS, context activated - case ESpudUp: // LinkLayerUp received, NIF is up. - case ESpudFlowOff: // LinkLayerUp received, NIF is up. - case ESpudSuspended: // LinkLayerUp received, NIF is up. - case ESpudFlowOffAndSuspended: // LinkLayerUp received, NIF is up. - __FLOG_2(_L("Lower NIF binder for context[%d] is in state[%S]: Stopping lower NIF."),aContextId,SpudStateToText(ref->State())); - // Stop the NIF and delete the context via SpudFsm: - ref->NifLink()->Stop(aReason, aAction); - // stay in the Up state so that that GUQoS is notified. - break; - - // Context is being created - case ESpudCreatingPrimary: - // SpudFsm will clean up the context and generate a context created event with an error - rc = iPdpFsmInterface.Input(aContextId, ECancelContextCreate); - break; - - // Context created, but NIF not started - case ESpudStartingPrimary: - ref->SetState(ESpudWaitLinkDown); - // Any outstanding SpudFsm request will be cancelled by this delete request. - rc = iPdpFsmInterface.Input(aContextId, EContextDelete); - aReason = (KErrNone != aReason) ? aReason : KErrCancel; // Must not be KErrNone. - SendPrimaryContextCreated(aContextId, aReason); - break; - - case ESpudStartingSecondary: - // Delete the context via SpudFsm - ref->SetState(ESpudLinkDown); // We'll notify GUQoS from deletion event handler. - __FLOG_1(_L("Context[%d] created: Sending SpudFsm event EContextDelete"), aContextId); - - // Any outstanding SpudFsm request will be cancelled by this delete request. - rc = iPdpFsmInterface.Input(aContextId, EContextDelete); - ASSERT(rc == KErrNone); - break; - - // Can't call Stop: the NIF either not started, or stopped already - case ESpudContextDelete: // Context deleted by GUQoS, Stop was called. - case ESpudWaitLinkDown: // Stop was called, waiting for LinkLayerDown - case ESpudWaitBinderDelete: // LinkLayerDown received, queued for deletion - case ESpudLinkDown: // LinkLayerDown received, not queued for deletion. - __FLOG_2(_L("Lower NIF binder for context[%d] is in state[%S], and is not eligible for Stop."),aContextId,SpudStateToText(ref->State())); - break; - - case ESpudHaveQos: - default: - __FLOG_2(_L("Lower NIF binder for context[%d] is in unexpected state[%S]."),aContextId,SpudStateToText(ref->State())); - ASSERT(EFalse); - break; - } - } - } - -/** -Send a packet across the link. -This function should not be called; the Mux is the one that should get the data. - -@param aPacket MBuf chain containing packet (ignored) -@param aSource (ignored) - -@return Error code, or 1 if packet was queued, - or KErrNone to flow off sender -*/ -TInt CSpudMan::Send(RMBufChain& /*aPacket*/, TAny* /*aSource*/) - { - _LIT(KPanicMsg, "CSpudMan"); - User::Panic(KPanicMsg, KErrNotSupported); - return KErrNotSupported; // never reached - } - - -/** -Receives notification from NIFMAN that the authenticate data is ready. -*/ -void CSpudMan::AuthenticateComplete(TInt aResult) - { - // Send AuthenticateComplete to all lower NIFs - TContextId i; - for (i=0; i < KMaxPdpContexts; ++i) - { - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(i)); - if (rc == KErrNone) - { - ref->NifLink()->AuthenticateComplete(aResult); - } - } - } - -void CSpudMan::Restart(CNifIfBase* /*aIf*/) - { - // TODO: Is it safe to simply ignore this? - __FLOG_0(_L("CSpudMan::Restart. Ignored.")); - ASSERT(EFalse); - } - - -//***************************************************************************** -// SPUD methods -//***************************************************************************** - -/** -Receives progress notifications from lower NIF. - -@param aContextId Context ID of lower NIF -@param aStage Progress stage -@param aError Error code -*/ -void CSpudMan::IfProgress(TContextId aContextId, TInt aStage, TInt aError) - { - __FLOG_3(_L("CSpudMan::IfProgress context ID %d received stage %d error %d"), - aContextId, aStage, aError); - // Eliminate compiler warnings in release builds - aContextId = aContextId; - aStage = aStage; - aError = aError; - - // Drop all progress indications from lower NIFs on the floor because they'll just confuse NIFMAN. - // SpudMan generates its own progress notifications. - } - -/** -Receives progress notifications from lower NIF. - -@param aContextId Context ID of lower NIF -@param aSubConnectionUniqueId Subconnection ID -@param aStage Progress stage -@param aError Error code -*/ -void CSpudMan::IfProgress(TContextId aContextId, TSubConnectionUniqueId aSubConnectionUniqueId, TInt aStage, TInt aError) - { - __FLOG_4(_L("CSpudMan::IfProgress context ID %d subconnection ID %d received stage %d error %d"), - aContextId, aSubConnectionUniqueId, aStage, aError); - // Eliminate compiler warnings in release builds - aContextId = aContextId; - aSubConnectionUniqueId = aSubConnectionUniqueId; - aStage = aStage; - aError = aError; - - // Drop all progress indications from lower NIFs on the floor because they'll just confuse NIFMAN. - // SpudMan generates its own progress notifications. - } - -/** -Receives notifications from lower NIF to agent. - -@param aContextId Valid context ID of lower NIF -@param aEvent Event type -@param aInfo Additional information for event (ignored) -@return KErrNone on success, or KErrNotSupported -*/ -TInt CSpudMan::Notification(TContextId aContextId, TNifToAgentEventType aEvent, void* /*aInfo*/) - { - __FLOG_2(_L("CSpudMan::Notification context ID %d event ID %d"), aContextId, aEvent); - switch (aEvent) - { - case ENifToAgentEventTsyConfig: - { - // Return GPRS context structure to lower NIF - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - - iPdpFsmInterface.Get(aContextId, iTempGprsContext); - ref->NifLink()->Notification(EAgentToNifEventTsyConfig, reinterpret_cast(&iTempGprsContext)); - return KErrNone; - } - - case ENifToAgentEventTsyConnectionSpeed: - { - // Return connection speed to lower NIF - CSpudBinderRef* ref = NULL; - TRAPD(rc, ref = iBindMan->GetRefL(aContextId)); - __ASSERT_ALWAYS(rc == KErrNone, Panic()); - ASSERT(ref->IsBound()); - -#ifdef SYMBIAN_NETWORKING_UMTSR5 - RPacketQoS::TQoSR5Negotiated params; -#else - RPacketQoS::TQoSR99_R4Negotiated params; -#endif -// SYMBIAN_NETWORKING_UMTSR5 - - iPdpFsmInterface.Get(aContextId, params); - ref->NifLink()->Notification(EAgentToNifEventTsyConnectionSpeed, - reinterpret_cast(static_cast(params.iMaxRate.iUplinkRate))); - - return KErrNone; - } - - default: - // Just ignore all the other notifications - __FLOG_0(_L("Ignoring notification")); - break; - } - - return KErrNotSupported; - } - -/** -Read a boolean field from the connection settings provider. -Intercepts reads of CommPort and returns the correct value. - -@param aContextId Valid context ID of lower NIF -@param aField The name of the field to read -@param aValue On return, contains the value of the field read -@return KErrNone, if successful; otherwise one of the standard Symbian OS error codes -*/ -TInt CSpudMan::ReadInt(TContextId aContextId, const TDesC& aField, TUint32& aValue) - { - - //This fix is needed to ensure that multiple PPP channels can be used for different PDP contexts. - //The returned value of ECommDbCdmaNaiMobileIp will cause PPP to skip external IP configuration (NCPIP). - if ( (TPtrC(CDMA_NAI_TYPE) == aField) && (iPrimaryContextId != aContextId) ) - { - __FLOG_2(_L("CSpudMan::ReadInt context ID %d field = CDMA_NAI_TYPE - Therefore explicitly setting Value to ECommDbCdmaNaiMobileIp"), - aContextId, &aField); - __FLOG(_L("No call to AgentRef Will be make")); - // Lower NIF is requesting the NAI type - aValue = ECommDbCdmaNaiMobileIp; - return KErrNone; - } - __FLOG_2(_L("CSpudMan::ReadInt context ID %d field %S"), aContextId, &aField); - // Read CommDB normally - return Notify()->ReadInt(aField, aValue); - } - -/** -Read a 8-bit descriptor field from the connection settings provider. -Intercepts reads of CommPort and returns the value returned from ETel. - -@param aContextId Valid context ID of lower NIF -@param aField The name of the field to read -@param aValue On return, contains the value of the field read -@return KErrNone, if successful; otherwise one of the standard Symbian OS error codes -*/ -TInt CSpudMan::ReadDes(TContextId aContextId, const TDesC& aField, TDes8& aValue) - { - __FLOG_2(_L("CSpudMan::ReadDes context ID %d field %S"), aContextId, &aField); - TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName; - _LIT(KFormatText,"%s\\%s"); - - columnName.Format(KFormatText,MODEM_BEARER,MODEM_PORT_NAME); - if (columnName == aField) - { - // Lower NIF is requesting the CSY port name - // Use the TDes16 version of ReadDes to retrieve the data - TBuf16 data; - TInt rc(ReadDes(aContextId, aField, data)); - aValue.Copy(data); - return rc; - } - - columnName.Format(KFormatText,MODEM_BEARER,MODEM_CSY_NAME); - if (columnName == aField) - { - // Lower NIF is requesting the CSY file name - // Use the TDes16 version of ReadDes to retrieve the data - TBuf16 data; - TInt rc(ReadDes(aContextId, aField, data)); - aValue.Copy(data); - return rc; - } - - // Read CommDB normally - return Notify()->ReadDes(aField, aValue); - } - -/** -Read a 16-bit descriptor field from the connection settings provider. -Intercepts reads of CommPort and returns the value returned from ETel. - -@param aContextId Valid context ID of lower NIF -@param aField The name of the field to read -@param aValue On return, contains the value of the field read -@return KErrNone, if successful; otherwise one of the standard Symbian OS error codes -*/ -TInt CSpudMan::ReadDes(TContextId aContextId, const TDesC& aField, TDes16& aValue) - { - __FLOG_2(_L("CSpudMan::ReadDes context ID %d field %S"), aContextId, &aField); - TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName; - _LIT(KFormatText,"%s\\%s"); - - columnName.Format(KFormatText,MODEM_BEARER,MODEM_PORT_NAME); - if (columnName == aField) - { - // Lower NIF is requesting the CSY port name - iPdpFsmInterface.Get(aContextId, iTempDataChannelV2); - __FLOG_1(_L("Returning ETel port name %S"), &iTempDataChannelV2.iPort); - aValue.Copy(iTempDataChannelV2.iPort); - return KErrNone; - } - - columnName.Format(KFormatText,MODEM_BEARER,MODEM_CSY_NAME); - if (columnName == aField) - { - // Lower NIF is requesting the CSY file name - iPdpFsmInterface.Get(aContextId, iTempDataChannelV2); - __FLOG_1(_L("Returning ETel CSY name %S"), &iTempDataChannelV2.iCsy); - aValue.Copy(iTempDataChannelV2.iCsy); - return KErrNone; - } - - return Notify()->ReadDes(aField, aValue); - } - -/** -Marks the binder to the lower NIF for asynchronous deletion - -@param aRef the binder -@pre the binder must be bound the lower NIF. -*/ -void CSpudMan::DisposeOfBinder(CSpudBinderRef* aRef) - { - ASSERT(aRef); - ASSERT(aRef->IsBound()); // We can only mark - sweep bound instances - ASSERT(aRef->State() != ESpudWaitBinderDelete); - aRef->SetState(ESpudWaitBinderDelete); - iBinderSweeperNotifierCb->Call(); // Queue deletion of marked binders & optional Nifman notification. - } - -/** -Sweeps the set of lower NIF binding, deleting the marked ones. If no contexts remain after, -notifies Nifman that SPUD has gone down. - -@param aContextId The ID of the context to delete -@param aReason error code that is passed to Nifman -*/ -void CSpudMan::SweepBindersAndNotify() - { - const TUint KNumContextsRemaining(BindMan()->SweepBinders()); - if (0 == KNumContextsRemaining) - { - SetTerminateError(KErrAbort); // This is a last ditched effort to provide termination - // error code. We cannot determine in all cases what has caused SPUD to terminate. - // E.g. if several secondary contexts were deleted by the network, which of them caused SPUD termination? - // In such case we say that SPUD is shutting down due to internal event (namely, last context deletion). - - __FLOG_3(_L("Last lower NIF has been deleted: Notifying Nifman with action EDisconnect[%d], progress KLinkLayerClosed[%d], reason[%d]"), - MNifIfNotify::EDisconnect, KLinkLayerClosed, iTerminateError); - - // Once we've notified LinkLayerDown & IfProgress, we are finished. Nifman will delete us any moment after - // the RunL we are working from returns. - __FLOG(_L("SPUD is finished, and expects to be deleted by Nifman. Reason: last PDP context has gone down, possibly due to Stop on SPUD.")); - - // Tell Nifman clients that SPUD is finished. - Notify()->LinkLayerDown(iTerminateError, MNifIfNotify::EDisconnect); - Notify()->IfProgress(KLinkLayerClosed, iTerminateError); - } - else - { - __FLOG_1(_L("There are [%d] contexts remaining."), KNumContextsRemaining); - } - } - -void CSpudMan::SetupSipServerAddrRetrievalL(RPacketContext::TProtocolConfigOptionV2& aPco) - { - __FLOG(_L("CSpudMan::SetupSipServerAddrRetrieval - Requesting the P-CSCF address from the PCO buffer")); - - TPtr8 pcoPtr(const_cast(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength()); - - // attach TTlv to the buffer - TTlvStruct tlv(pcoPtr,0); - tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktPCSCFAddressRequest), - TPtr8(static_cast(NULL), 0, 0)); - aPco.iMiscBuffer.SetLength(pcoPtr.Length()); - } - - -#ifdef SYMBIAN_NETWORKING_UMTSR5 - -void CSpudMan::SetIMCNSignallingFlagPcoL(RPacketContext::TProtocolConfigOptionV2& aPco) -/** -Put the value for IMCN Signalling flag in the pco buffer if it is set in database - -@param PCO IE Buffer -*/ - { - TBool imcn=EFalse; - TBuf<2*KCommsDbSvrMaxColumnNameLength+2> columnName; - _LIT(KFormatText,"%s\\%s"); - columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_IM_CN_SIGNALLING_INDICATOR); - TRAPD(ret, Notify()->ReadBool(columnName,imcn);); - __FLOG_1(_L("CSpudMan::SetIMCNSignallingFlagPcoL - Requesting IMCN Signalling status from Database: error = %d"),ret); - - if (imcn && ret==KErrNone ) - - { - TPtr8 pcoPtr(const_cast(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength()); - TTlvStruct tlv(pcoPtr,0); - tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktIMCNMSSubsystemSignallingFlag ), - TPtr8(static_cast(NULL), 0, 0)); - aPco.iMiscBuffer.SetLength(pcoPtr.Length()); - } - } -TBool CSpudMan::GetIMCNSignallingFlagPcoL(RPacketContext::TProtocolConfigOptionV2& aPco) -/** -Get the value for IMCN Signalling from the network pco buffer - -@param PCO IE Buffer -*/ - { - - __FLOG(_L("CSpudMan::GetIMCNSignallingFlagPcoL - Retrieving the IMCN signalling Flag from the PCO buffer")); - - TPtr8 pcoPtr(const_cast(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength()); - TTlvStruct tlv(pcoPtr,0); - tlv.ResetCursorPos(); - - TInt err = tlv.NextItemL(RPacketContext::EEtelPcktIMCNNetworkSubsystemSignallingFlag,pcoPtr); - return (err == KErrNone); - - } - -#endif // SYMBIAN_NETWORKING_UMTSR5 - - -void CSpudMan::SetSipServerAddrL(const RPacketContext::TProtocolConfigOptionV2& aPco) - { - __FLOG(_L("CSpudMan::SetSipServerAddr - Retrieving the P-CSCF address from the PCO buffer")); - iSipServerAddr.Reset(); //Free all existing entries - TPtr8 pcoPtr(const_cast(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength()); - TTlvStruct - tlv(pcoPtr,0); - - tlv.ResetCursorPos(); - TIp6Addr addr; - TPtr8 addrPtr(NULL, 0); - TPckg addrPckg(addr); - - while (tlv.NextItemL(RPacketContext::EEtelPcktPCSCFAddress,addrPtr) == KErrNone) - { - TInetAddr inetAddr; - addrPckg.Copy(addrPtr); - inetAddr.SetAddress(addr); - TBuf testbuf; - inetAddr.Output(testbuf); - __FLOG_1(_L("CSpudMan::SetSipServerAddr - P-CSCF address ---> %S"),&testbuf); - if (testbuf.Length()) //ie the address is invalid - { - iSipServerAddr.AppendL(inetAddr); - } - } - } - -void CSpudMan::SetContextTerminationErrorAndStop(TContextId aContextId, TInt aErrorCode) - { - __FLOG_2(_L("SetContextTerminateError on StatusEvent: aContextId[%d], aErrorCode[%d]"), - aContextId, aErrorCode); - - // If there is no error then simply return - if (KErrNone == aErrorCode) return; - - // If secondary context, store error code in individual contexts reference - // and stop the secondary context - if(aContextId != iPrimaryContextId) - { - StopContext(aContextId, aErrorCode, MNifIfNotify::EDisconnect); - } - else - { - // This is a problem with the Primary context so stop and disconnect - // Now save the termination error code if not already set - if (iTerminateError == KErrNone) - { - iTerminateError = aErrorCode; - } - - // This may be the first ETel error code so save it - if (iETelTerminateError == KErrNone) - { - iETelTerminateError = aErrorCode; - } - - // Primary context has a problem so disconnect - Stop(aErrorCode, MNifIfNotify::EDisconnect); - } - } - -//************************************************************************* -// CLowerNifBinderDeletionCb -// Asynchronous deletion of CSpudBinderRefs and notification to Nifman -//************************************************************************* -// Use Spudman's logging. -// Because we are owned by Spudman, we don't have to worry about the logger being deleted. -#ifdef __FLOG_ACTIVE -#define BINDER_SWEEPER_LOG(x) iSpudMan.x -#else -#define BINDER_SWEEPER_LOG(x) -#endif - -// Construct a High-Priority AO that calls into the SPUD -// This will work with any priority AO, but because we are releasing memory and -// potentially notifying Nifman, we want to run ASAP. -CBinderSweeperNotifierCb::CBinderSweeperNotifierCb(CSpudMan& aSpudMan) - : - CAsyncOneShot(CActive::EPriorityHigh), - iSpudMan(aSpudMan) - { - } - -// Queues the deletion callback -void CBinderSweeperNotifierCb::Call() - { - if(!IsActive()) // We can be called again before we had a chance to run. - { - BINDER_SWEEPER_LOG(__FLOG(_L("CBinderSweeperNotifierCb: Queueing async deletion of dead lower NIF bindings."));) - CAsyncOneShot::Call(); - return; - } - BINDER_SWEEPER_LOG(__FLOG(_L("CBinderSweeperNotifierCb: Async deletion of dead lower NIF bindings is already queued."));) - } - - -// Called by ActiveScheduler. -// -// If the lower NIF deletion is attempted after Nifman deletes the SPUD -// (from CNifAgentRef::DisconnectionComplete), the lower NIF deletion AO is corrupted in the -// ActiveScheduler, causing ESock thread to crash. To prevent this, lower NIFs are deleted -// before signalling LinkLayerDown to Nifman. When a lower NIF signals LinkLayerDown, a callback into Spudman is queued. -// This callback deletes the lower NIFs that are eligible for deletion, and notifies Nifman, if necessary. */ -void CBinderSweeperNotifierCb::RunL() - { - iSpudMan.SweepBindersAndNotify(); - } -