--- a/telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/spudman.cpp Mon May 03 13:37:20 2010 +0300
+++ b/telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/spudman.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,3247 +1,3247 @@
-// 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 <comms-infras/dbaccess.h>
-#include "rpdpfsminterface.h"
-using namespace SpudMan; // Access the SpudFsm event names
-
-#include <etelpckt.h>
-#include <comms-infras/commsdebugutility.h>
-#include <in_sock.h>
-#include <networking/qos_if.h>
-#include <nifman.h>
-#include <comms-infras/es_config.h>
-
-#include <networking/umtsgprs_subconnprovfactory.h>
-#include <ss_glob.h>
-#include <ss_subconnprov.h>
-
-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<SSipServerAddr*>(const_cast<TUint8*>(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<KMaxInetAddrPrintSize> 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<KCommsDbSvrMaxFieldLength> 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<KCommsDbSvrMaxUserIdPassLength> 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<TUint32&>(aQos.iReqTrafficClass));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_CLASS);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinTrafficClass));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVERY_ORDER);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqDeliveryOrderReqd));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVERY_ORDER);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinDeliveryOrderReqd));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVER_ERRONEOUS_SDU);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqDeliverErroneousSDU));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVER_ERRONEOUS_SDU);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinDeliverErroneousSDU));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_SDUSIZE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxSDUSize));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_ACCEPTABLE_MAX_SDU_SIZE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxSDUSize));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_UPLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxRate.iUplinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_UPLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxRate.iUplinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_DOWNLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxRate.iDownlinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_DOWNLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxRate.iDownlinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_BER);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqBER));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_BER);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxBER));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_SDU_ERROR_RATIO);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqSDUErrorRatio));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_SDU_ERROR_RATIO);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxSDUErrorRatio));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRAFFIC_HANDLING_PRIORITY);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTrafficHandlingPriority));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_HANDLING_PRIORITY);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinTrafficHandlingPriority));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRANSFER_DELAY);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTransferDelay));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_TRANSFER_DELAY);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxTransferDelay));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_UPLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqGuaranteedRate.iUplinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_UPLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinGuaranteedRate.iUplinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_DOWNLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqGuaranteedRate.iDownlinkRate));
-
- columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_DOWNLINK_RATE);
- Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(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<TUint32&>(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<TConnInterfaceName*>( const_cast<TUint8*>( 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<CConnectionProviderBase*>( 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<TConnInterfaceName> 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<CNifIfBase*> 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<TSoIfControllerInfo*>(const_cast<TUint8*>(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<const TEvent *>(aOption.Ptr());
- iQosEventHandler = static_cast<MNifEvent *>(handler->iEvent);
- ASSERT(iQosEventHandler);
- return KErrNone;
- }
-
- case KContextSetEvents:
- {
- if (!AreQoSEventsEnabled())
- {
- // Event handler must be registered first
- return KErrGeneral;
- }
- const TBool* eventsEnabledPtr = reinterpret_cast<const TBool *>(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<const TContextParameters*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<MPdpFsmInterface**>(const_cast<TUint8*>(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<CProtocolBase*>(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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TNetworkParameters> 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<CNifIfBase*>(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<RPacketContext::TDataVolume>* totalDataPackage = (TPckg<RPacketContext::TDataVolume>*) aInfo;
- RPacketContext::TDataVolume& totalData = (*totalDataPackage)();
- totalData.iBytesSent = 0;
- totalData.iOverflowCounterSent = 0;
- totalData.iBytesReceived = 0;
- totalData.iOverflowCounterReceived = 0;
-
- RPacketContext::TDataVolume data;
- TPckg<RPacketContext::TDataVolume> 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<void*>(&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<void*>(static_cast<TUint>(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<KCommsDbSvrMaxFieldLength> 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<KCommsDbSvrMaxFieldLength> 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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
-
- // attach TTlv to the buffer
- TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
- tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktPCSCFAddressRequest),
- TPtr8(static_cast<TUint8*>(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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
- TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
- tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktIMCNMSSubsystemSignallingFlag ),
- TPtr8(static_cast<TUint8*>(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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
- TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> 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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
- TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength>
- tlv(pcoPtr,0);
-
- tlv.ResetCursorPos();
- TIp6Addr addr;
- TPtr8 addrPtr(NULL, 0);
- TPckg<TIp6Addr> addrPckg(addr);
-
- while (tlv.NextItemL(RPacketContext::EEtelPcktPCSCFAddress,addrPtr) == KErrNone)
- {
- TInetAddr inetAddr;
- addrPckg.Copy(addrPtr);
- inetAddr.SetAddress(addr);
- TBuf<KMaxInetAddrPrintSize> 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();
- }
-
+// 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 <comms-infras/dbaccess.h>
+#include "rpdpfsminterface.h"
+using namespace SpudMan; // Access the SpudFsm event names
+
+#include <etelpckt.h>
+#include <comms-infras/commsdebugutility.h>
+#include <in_sock.h>
+#include <networking/qos_if.h>
+#include <nifman.h>
+#include <comms-infras/es_config.h>
+
+#include <networking/umtsgprs_subconnprovfactory.h>
+#include <ss_glob.h>
+#include <ss_subconnprov.h>
+
+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<SSipServerAddr*>(const_cast<TUint8*>(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<KMaxInetAddrPrintSize> 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<KCommsDbSvrMaxFieldLength> 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<KCommsDbSvrMaxUserIdPassLength> 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<TUint32&>(aQos.iReqTrafficClass));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_CLASS);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinTrafficClass));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVERY_ORDER);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqDeliveryOrderReqd));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVERY_ORDER);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinDeliveryOrderReqd));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVER_ERRONEOUS_SDU);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqDeliverErroneousSDU));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVER_ERRONEOUS_SDU);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinDeliverErroneousSDU));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_SDUSIZE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxSDUSize));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_ACCEPTABLE_MAX_SDU_SIZE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxSDUSize));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_UPLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxRate.iUplinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_UPLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxRate.iUplinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_DOWNLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxRate.iDownlinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_DOWNLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxRate.iDownlinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_BER);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqBER));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_BER);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxBER));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_SDU_ERROR_RATIO);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqSDUErrorRatio));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_SDU_ERROR_RATIO);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxSDUErrorRatio));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRAFFIC_HANDLING_PRIORITY);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTrafficHandlingPriority));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_HANDLING_PRIORITY);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinTrafficHandlingPriority));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRANSFER_DELAY);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTransferDelay));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_TRANSFER_DELAY);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxTransferDelay));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_UPLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqGuaranteedRate.iUplinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_UPLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinGuaranteedRate.iUplinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_DOWNLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqGuaranteedRate.iDownlinkRate));
+
+ columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_DOWNLINK_RATE);
+ Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(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<TUint32&>(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<TConnInterfaceName*>( const_cast<TUint8*>( 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<CConnectionProviderBase*>( 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<TConnInterfaceName> 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<CNifIfBase*> 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<TSoIfControllerInfo*>(const_cast<TUint8*>(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<const TEvent *>(aOption.Ptr());
+ iQosEventHandler = static_cast<MNifEvent *>(handler->iEvent);
+ ASSERT(iQosEventHandler);
+ return KErrNone;
+ }
+
+ case KContextSetEvents:
+ {
+ if (!AreQoSEventsEnabled())
+ {
+ // Event handler must be registered first
+ return KErrGeneral;
+ }
+ const TBool* eventsEnabledPtr = reinterpret_cast<const TBool *>(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<const TContextParameters*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<TContextParameters*>(const_cast<TUint8*>(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<MPdpFsmInterface**>(const_cast<TUint8*>(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<CProtocolBase*>(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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TContextParameters> 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<TNetworkParameters> 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<CNifIfBase*>(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<RPacketContext::TDataVolume>* totalDataPackage = (TPckg<RPacketContext::TDataVolume>*) aInfo;
+ RPacketContext::TDataVolume& totalData = (*totalDataPackage)();
+ totalData.iBytesSent = 0;
+ totalData.iOverflowCounterSent = 0;
+ totalData.iBytesReceived = 0;
+ totalData.iOverflowCounterReceived = 0;
+
+ RPacketContext::TDataVolume data;
+ TPckg<RPacketContext::TDataVolume> 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<void*>(&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<void*>(static_cast<TUint>(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<KCommsDbSvrMaxFieldLength> 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<KCommsDbSvrMaxFieldLength> 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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
+
+ // attach TTlv to the buffer
+ TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
+ tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktPCSCFAddressRequest),
+ TPtr8(static_cast<TUint8*>(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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
+ TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
+ tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktIMCNMSSubsystemSignallingFlag ),
+ TPtr8(static_cast<TUint8*>(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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
+ TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> 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<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
+ TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength>
+ tlv(pcoPtr,0);
+
+ tlv.ResetCursorPos();
+ TIp6Addr addr;
+ TPtr8 addrPtr(NULL, 0);
+ TPckg<TIp6Addr> addrPckg(addr);
+
+ while (tlv.NextItemL(RPacketContext::EEtelPcktPCSCFAddress,addrPtr) == KErrNone)
+ {
+ TInetAddr inetAddr;
+ addrPckg.Copy(addrPtr);
+ inetAddr.SetAddress(addr);
+ TBuf<KMaxInetAddrPrintSize> 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();
+ }
+