telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/spudman.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // SPUD event manager
       
    15 // WINSCW compiler has problems disambiguating TMetaDes8 and Meta::TMetaDes8 so
       
    16 // I prevent metabuffer.h from being recursively included from other headers
       
    17 // by defining its include guard.
       
    18 // 
       
    19 //
       
    20 
       
    21 /**
       
    22  @file
       
    23  @internalComponent
       
    24 */
       
    25 #define METABUFFER_H
       
    26 
       
    27 #include "spudman.h"
       
    28 #include "bindman.h"
       
    29 #include "mux.h"
       
    30 
       
    31 #include <comms-infras/dbaccess.h>
       
    32 #include "rpdpfsminterface.h"
       
    33 using namespace SpudMan; // Access the SpudFsm event names
       
    34 
       
    35 #include <etelpckt.h>
       
    36 #include <comms-infras/commsdebugutility.h>
       
    37 #include <in_sock.h>
       
    38 #include <networking/qos_if.h>
       
    39 #include <nifman.h>
       
    40 #include <comms-infras/es_config.h>
       
    41 
       
    42 #include <networking/umtsgprs_subconnprovfactory.h>
       
    43 #include <ss_glob.h>
       
    44 #include <ss_subconnprov.h>
       
    45 
       
    46 const TUint KQosPlugInProtocolId = 360; //< Plug-in protocol ID
       
    47 
       
    48 static const TInt KMaxInetAddrPrintSize = 50; //This should be big enough for an IPv6 printout
       
    49 
       
    50 
       
    51 #ifdef __FLOG_ACTIVE
       
    52 
       
    53 _LIT(KSpudUnknownLit, "Unknown event");
       
    54 
       
    55 _LIT(KSpudSoIfControllerPlugInLit, "KSoIfControllerPlugIn");
       
    56 _LIT(KSpudLitKRegisterEventHandler, "KRegisterEventHandler");
       
    57 _LIT(KSpudContextSetEventsLit, "KContextSetEvents");
       
    58 _LIT(KSpudNifSetDefaultQoSLit, "KNifSetDefaultQoS");
       
    59 _LIT(KSpudContextCreateLit, "KContextCreate");
       
    60 _LIT(KSpudContextDeleteLit, "KContextDelete");
       
    61 _LIT(KSpudContextActivateLit, "KContextActivate");
       
    62 _LIT(KSpudContextQoSSetLit, "KContextQoSSet");
       
    63 _LIT(KSpudContextTFTModifyLit, "KContextTFTModify");
       
    64 _LIT(KSpudGetNegQoSLit, "KGetNegQoS");
       
    65 _LIT(KSpudContextModifyActiveLit, "KContextModifyActive");
       
    66 _LIT(KInitialisePdpFsmLit, "KInitialisePdpFsm");
       
    67 
       
    68 
       
    69 static const TDesC *SpudGuQoSEventToText(TInt aEvent)
       
    70 	{
       
    71 	switch(aEvent)
       
    72 		{
       
    73 	case KSoIfControllerPlugIn:
       
    74 		return &KSpudSoIfControllerPlugInLit;
       
    75 	case KRegisterEventHandler:
       
    76 		return &KSpudLitKRegisterEventHandler;
       
    77 	case KContextSetEvents:
       
    78 		return &KSpudContextSetEventsLit;
       
    79 	case KNifSetDefaultQoS:
       
    80 		return &KSpudNifSetDefaultQoSLit;
       
    81 	case KContextCreate:
       
    82 		return &KSpudContextCreateLit;
       
    83 	case KContextDelete:
       
    84 		return &KSpudContextDeleteLit;
       
    85 	case KContextActivate:
       
    86 		return &KSpudContextActivateLit;
       
    87 	case KContextQoSSet:
       
    88 		return &KSpudContextQoSSetLit;
       
    89 	case KContextTFTModify:
       
    90 		return &KSpudContextTFTModifyLit;
       
    91 	case KGetNegQoS:
       
    92 		return &KSpudGetNegQoSLit;
       
    93 	case KContextModifyActive:
       
    94 		return &KSpudContextModifyActiveLit;
       
    95 	case KInitialisePdpFsm:
       
    96 		return &KInitialisePdpFsmLit;
       
    97 	default:
       
    98     	return &KSpudUnknownLit;
       
    99 		}
       
   100 	}
       
   101 	
       
   102 _LIT(KSpudContextDeleteEventLit, "KContextDeleteEvent");
       
   103 _LIT(KSpudContextActivateEventLit, "KContextActivateEvent");
       
   104 _LIT(KSpudContextParametersChangeEventLit, "KContextParametersChangeEvent");
       
   105 _LIT(KSpudContextBlockedEventLit, "KContextBlockedEvent");
       
   106 _LIT(KSpudContextUnblockedEventLit, "KContextUnblockedEvent");
       
   107 _LIT(KSpudNetworkStatusEventLit, "KNetworkStatusEvent");
       
   108 _LIT(KSpudContextQoSSetEventLit, "KContextQoSSetEvent");
       
   109 _LIT(KSpudContextTFTModifiedEventLit, "KContextTFTModifiedEvent");
       
   110 _LIT(KSpudPrimaryContextCreatedLit, "KPrimaryContextCreated");
       
   111 _LIT(KSpudSecondaryContextCreatedLit, "KSecondaryContextCreated");
       
   112 _LIT(KSpudGetNegQoSEventLit,"KGetNegQoSEvent");
       
   113 _LIT(KSpudContextModifyActiveEventLit, "KContextModifyActiveEvent");
       
   114 _LIT(KPdpFsmShuttingDownLit, "KPdpFsmShuttingDown");
       
   115 
       
   116 static const TDesC *SpudFsmEventToText(TInt aEvent)
       
   117 	{
       
   118 	switch(aEvent)
       
   119     	{
       
   120 	case KContextDeleteEvent:
       
   121 		return &KSpudContextDeleteEventLit;
       
   122 	case KContextActivateEvent:
       
   123 		return &KSpudContextActivateEventLit;
       
   124 	case KContextParametersChangeEvent:
       
   125 		return &KSpudContextParametersChangeEventLit;
       
   126 	case KContextBlockedEvent:
       
   127 		return &KSpudContextBlockedEventLit;
       
   128 	case KContextUnblockedEvent:
       
   129 		return &KSpudContextUnblockedEventLit;
       
   130 	case KNetworkStatusEvent:
       
   131 		return &KSpudNetworkStatusEventLit;
       
   132 	case KContextQoSSetEvent:
       
   133 		return &KSpudContextQoSSetEventLit;
       
   134 	case KContextTFTModifiedEvent:
       
   135 		return &KSpudContextTFTModifiedEventLit;
       
   136 	case KPrimaryContextCreated:
       
   137 		return &KSpudPrimaryContextCreatedLit;
       
   138 	case KSecondaryContextCreated:
       
   139 		return &KSpudSecondaryContextCreatedLit;
       
   140 	case KGetNegQoSEvent:
       
   141     		return &KSpudGetNegQoSEventLit;
       
   142     case KContextModifyActiveEvent:
       
   143     	return &KSpudContextModifyActiveEventLit;
       
   144    	case KPdpFsmShuttingDown:
       
   145     	return &KPdpFsmShuttingDownLit;
       
   146     default:
       
   147     	return &KSpudUnknownLit;
       
   148     	}
       
   149 	}
       
   150 
       
   151 _LIT(KSpudStateSpudInactiveLit, "ESpudInactive");
       
   152 _LIT(KSpudStateSpudHaveQosLit, "ESpudHaveQos");
       
   153 _LIT(KSpudStateSpudCreatingPrimary, "ESpudCreatingPrimary");
       
   154 _LIT(KSpudStateSpudStartingPrimaryLit, "ESpudStartingPrimary");
       
   155 _LIT(KSpudStateSpudStartingPrimaryLowerNifLit, "ESpudStartingPrimaryLowerNif");
       
   156 _LIT(KSpudStateSpudStartingSecondaryLit, "ESpudStartingSecondary");
       
   157 _LIT(KSpudStateSpudStartingSecondaryLowerNifLit, "ESpudStartingSecondaryLowerNif");
       
   158 _LIT(KSpudStateSpudGettingNegQoSLit, "ESpudGettingNegQoS");
       
   159 _LIT(KSpudStateSpudUpLit, "ESpudUp");
       
   160 _LIT(KSpudStateSpudFlowOffLit, "ESpudFlowOff");
       
   161 _LIT(KSpudStateSpudSuspendedLit, "ESpudSuspended");
       
   162 _LIT(KSpudStateSpudFlowOffAndSuspendedLit, "ESpudFlowOffAndSuspended");
       
   163 _LIT(KSpudStateSpudLinkDownLit, "ESpudLinkDown");
       
   164 _LIT(KSpudStateSpudContextDeleteLit, "ESpudContextDelete");
       
   165 _LIT(KSpudStateSpudWaitLinkDownLit, "ESpudWaitLinkDown");
       
   166 _LIT(KSpudStateSpudWaitBinderDeleteLit, "ESpudWaitBinderDelete");
       
   167 _LIT(KSpudStateUnknownLit, "Unknown spud state");
       
   168 	
       
   169 static const TDesC *SpudStateToText(TSpudContextStates aState)
       
   170 	{
       
   171 	switch(aState)
       
   172     	{
       
   173 	case ESpudInactive:
       
   174 		return &KSpudStateSpudInactiveLit;
       
   175 	case ESpudHaveQos:
       
   176 		return &KSpudStateSpudHaveQosLit;
       
   177 	case ESpudCreatingPrimary:
       
   178 		return &KSpudStateSpudCreatingPrimary;
       
   179 	case ESpudStartingPrimary:
       
   180 		return &KSpudStateSpudStartingPrimaryLit;
       
   181 	case ESpudStartingPrimaryLowerNif:
       
   182 		return &KSpudStateSpudStartingPrimaryLowerNifLit;
       
   183 	case ESpudStartingSecondary:
       
   184 		return &KSpudStateSpudStartingSecondaryLit;
       
   185 	case ESpudStartingSecondaryLowerNif:
       
   186 		return &KSpudStateSpudStartingSecondaryLowerNifLit;
       
   187 	case ESpudGettingNegQoS:
       
   188 		return &KSpudStateSpudGettingNegQoSLit;
       
   189 	case ESpudUp:
       
   190 		return &KSpudStateSpudUpLit;
       
   191 	case ESpudFlowOff:
       
   192 		return &KSpudStateSpudFlowOffLit;
       
   193 	case ESpudSuspended:
       
   194 		return &KSpudStateSpudSuspendedLit;
       
   195 	case ESpudFlowOffAndSuspended:
       
   196 		return &KSpudStateSpudFlowOffAndSuspendedLit;
       
   197 	case ESpudLinkDown:
       
   198 		return &KSpudStateSpudLinkDownLit;
       
   199 	case ESpudContextDelete:
       
   200 		return &KSpudStateSpudContextDeleteLit;
       
   201 	case ESpudWaitLinkDown:
       
   202 		return &KSpudStateSpudWaitLinkDownLit;
       
   203 	case ESpudWaitBinderDelete:
       
   204 		return &KSpudStateSpudWaitBinderDeleteLit;
       
   205 	default:
       
   206     	return &KSpudStateUnknownLit;
       
   207     	}
       
   208 	}
       
   209 
       
   210 #endif
       
   211 
       
   212 CSpudMan::CSpudMan(CNifIfFactory& aFactory, MNifIfNotify* aNotify)
       
   213 	: CNifIfLink(aFactory),
       
   214 	iContextStatusOverride(RPacketContext::EStatusUnknown)
       
   215 	{
       
   216     iNotify = aNotify;
       
   217     ASSERT(iNotify);
       
   218 	__FLOG_OPEN(KSpudFirstTag,KSpudLog);
       
   219     __FLOG_0(_L("CSpudMan::CSpudMan"));
       
   220 	}
       
   221 
       
   222 CSpudMan::~CSpudMan()
       
   223    {
       
   224    if (iBindMan)
       
   225       {
       
   226       // Only log if ConstructL() was called, where logger was initialized
       
   227       __FLOG_0(_L("CSpudMan::~CSpudMan"));
       
   228       }
       
   229    
       
   230    
       
   231    if (AreQoSEventsEnabled())
       
   232       {
       
   233       // Spud is being destroyed by Nifman. Tell GUQoS to stop bothering SPUD.
       
   234       // GUQoS returns the favour by turning off the NIF events within this very call.
       
   235       // *********************************************************************************************
       
   236       // N.B.: "DEF055691 	GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack
       
   237       // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event.
       
   238       // Because of this defect, we cannot signal KNetworkInterfaceDown from anywhere but here. Once it is fixed,
       
   239       // calls from the appropriate places will be enabled, and the line below will not be strictly necessary.
       
   240       SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached);
       
   241       // For safety, we should call this from here in any case.
       
   242       //**********************************************************************************************
       
   243       }
       
   244    
       
   245    delete iParkedDefaultQoS;
       
   246    delete iBinderSweeperNotifierCb;
       
   247    
       
   248    delete iBindMan;
       
   249    iPdpFsmInterface.Close();
       
   250    iSipServerAddr.Close();
       
   251    __FLOG_CLOSE;
       
   252    }
       
   253 
       
   254 /**
       
   255 Panics the current thread.
       
   256 
       
   257 @param aReason Panic reason code
       
   258 */
       
   259 void CSpudMan::Panic(TInt aReason) const
       
   260 	{
       
   261     __FLOG_1(_L("CSpudMan::Panic with reason %d"), aReason);
       
   262 	User::Panic(KSpudName, aReason);
       
   263 	}
       
   264 
       
   265 /**
       
   266 Construct the Link Protocol Object
       
   267 
       
   268 @param aBindMan Pointer to BindMan object (ownership is transferred)
       
   269 @leave leaves if could not allocate memory
       
   270 */
       
   271 void CSpudMan::ConstructL(CBindMan* aBindMan)
       
   272 	{
       
   273     __FLOG_1(_L("CSpudMan starting %x"), iNotify);
       
   274 
       
   275 
       
   276 	iBindMan = aBindMan;
       
   277 	ASSERT(iBindMan);
       
   278 	
       
   279 	// The lower NIF binder deletion & Nifman notification callback
       
   280 	iBinderSweeperNotifierCb = new (ELeave) CBinderSweeperNotifierCb(*this);
       
   281 	}
       
   282 
       
   283 
       
   284 /**
       
   285 Implements the Control method of CNifBase - used for retrieval of the P-CSCF (Sip Server) address
       
   286 */	
       
   287 TInt CSpudMan::Control(TUint aLevel,TUint aName,TDes8& aOption, TAny*)
       
   288 	{
       
   289 	if (aLevel == KCOLConfiguration && aName == KConnGetSipServerAddr)
       
   290 		{
       
   291 		if (aOption.Length() != sizeof (SSipServerAddr))
       
   292 			{
       
   293 			__FLOG(_L("CSpudMan::Control - Invalid Descriptior - Descriptor Must contain an SSipServerAddr"));
       
   294 			Panic();
       
   295 			}
       
   296 		SSipServerAddr* sipServerAddr = reinterpret_cast<SSipServerAddr*>(const_cast<TUint8*>(aOption.Ptr()));
       
   297 		if (sipServerAddr->index < 0 || sipServerAddr->index >= iSipServerAddr.Count())
       
   298 			{
       
   299 			__FLOG_1(_L("CSpudMan::Control - Index out of range : value = %d"), sipServerAddr->index);
       
   300 			return KErrNotFound;
       
   301 			}
       
   302 		sipServerAddr->address = iSipServerAddr[sipServerAddr->index];
       
   303 #ifdef __FLOG_ACTIVE
       
   304 		TBuf<KMaxInetAddrPrintSize> buf;
       
   305 		sipServerAddr->address.Output(buf);
       
   306 		__FLOG_2(_L("CSpudMan::Control Address %S returned for index %d"), &buf, sipServerAddr->index);
       
   307 #endif
       
   308 		return KErrNone;				
       
   309 		}
       
   310 	return KErrNotSupported;	
       
   311 	}
       
   312 
       
   313 
       
   314 /**
       
   315 Retrieve any GPRS settings required from CommDB
       
   316 
       
   317 @param aConfigGprs Context configuration parameters to be filled in
       
   318 */
       
   319 void CSpudMan::RetrieveGprsConfig(RPacketContext::TContextConfigGPRS& aConfigGprs) const
       
   320 	{
       
   321 	TUint32 pdpType(0);
       
   322 	Notify()->ReadInt(TPtrC(GPRS_PDP_TYPE), pdpType);
       
   323  	__FLOG_1(_L8("ReadInt GPRS_PDP_TYPE [%d]"), pdpType);
       
   324 	aConfigGprs.iPdpType = STATIC_CAST(RPacketContext::TProtocolType, pdpType);
       
   325 
       
   326 	Notify()->ReadDes(TPtrC(GPRS_APN), aConfigGprs.iAccessPointName);
       
   327   	__FLOG_1(_L8("ReadDes GPRS_APN [%S]"), &aConfigGprs.iAccessPointName);
       
   328 
       
   329 		
       
   330 	TBool fromServer;
       
   331 	aConfigGprs.iPdpAddress.SetLength(0);
       
   332 	Notify()->ReadBool(TPtrC(GPRS_IP_ADDR_FROM_SERVER), fromServer);
       
   333 	if (!fromServer)
       
   334 	    {
       
   335     	Notify()->ReadDes(TPtrC(GPRS_IP_ADDR), aConfigGprs.iPdpAddress);
       
   336 	    }
       
   337 	
       
   338 
       
   339     // We can only use IPv4 or IPv6 - we use the first one listed in the IfNetworks field
       
   340     TBuf<KCommsDbSvrMaxFieldLength> networks;
       
   341 	Notify()->ReadDes(TPtrC(LAN_IF_NETWORKS), networks);
       
   342 
       
   343 	ASSERT(networks.Length() > 0); // If the IfNetworks field is empty there is a serious misconfiguration
       
   344 	
       
   345 	TInt pos = networks.Find(_L(","));
       
   346 	if (pos == KErrNotFound)
       
   347 	    {
       
   348 	    pos = networks.Length();
       
   349 	    }
       
   350 	TPtrC protocol(networks.Ptr(), pos);
       
   351 	_LIT(KIp4, "ip");
       
   352 	_LIT(KIp6, "ip6");
       
   353 	if (protocol.CompareF(KIp4) == 0)
       
   354 	    {
       
   355 	    // IPv4 settings
       
   356     	Notify()->ReadBool(TPtrC(GPRS_IP_DNS_ADDR_FROM_SERVER), fromServer);
       
   357     	if (!fromServer)
       
   358     	    {
       
   359     	    Notify()->ReadDes(TPtrC(GPRS_IP_NAME_SERVER1), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iPrimaryDns);
       
   360     	    Notify()->ReadDes(TPtrC(GPRS_IP_NAME_SERVER2), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iSecondaryDns);
       
   361     	    }
       
   362 	    }
       
   363 	else if (protocol.CompareF(KIp6) == 0)
       
   364 	    {
       
   365 	    // IPv6 settings
       
   366     	Notify()->ReadBool(TPtrC(GPRS_IP6_DNS_ADDR_FROM_SERVER), fromServer);
       
   367     	if (!fromServer)
       
   368     	    {
       
   369     	    Notify()->ReadDes(TPtrC(GPRS_IP6_NAME_SERVER1), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iPrimaryDns);
       
   370     	    Notify()->ReadDes(TPtrC(GPRS_IP6_NAME_SERVER2), aConfigGprs.iProtocolConfigOption.iDnsAddresses.iSecondaryDns);
       
   371     	    }
       
   372 	    }
       
   373 	else
       
   374 	    {
       
   375 	    // Anything else is a serious misconfiguration
       
   376 	    ASSERT(0);
       
   377 	    }
       
   378 	
       
   379 	RetrieveGprsCompression(aConfigGprs.iPdpCompression);
       
   380 	 __FLOG_1(_L8("Read GprsCompression [%d]"), aConfigGprs.iPdpCompression);
       
   381 
       
   382 	RetrieveGprsAnonymousAccess(aConfigGprs.iAnonymousAccessReqd);
       
   383  	__FLOG_1(_L8("Read AnonymousAccess [%d]"), aConfigGprs.iAnonymousAccessReqd);
       
   384 
       
   385 	TBuf<KCommsDbSvrMaxUserIdPassLength> readBuf;
       
   386 	Notify()->ReadDes(TPtrC(SERVICE_IF_AUTH_NAME), readBuf);
       
   387 	aConfigGprs.iProtocolConfigOption.iAuthInfo.iUsername.Copy(readBuf);
       
   388 	readBuf.Zero();
       
   389 	Notify()->ReadDes(TPtrC(SERVICE_IF_AUTH_PASS), readBuf);
       
   390 	aConfigGprs.iProtocolConfigOption.iAuthInfo.iPassword.Copy(readBuf);
       
   391  	__FLOG_2(_L8("ReadDes SERVICE_IF_AUTH_NAME [%S] and SERVICE_IF_AUTH_PASS [%S]"), &aConfigGprs.iProtocolConfigOption.iAuthInfo.iUsername, 
       
   392 			 &aConfigGprs.iProtocolConfigOption.iAuthInfo.iPassword);
       
   393 
       
   394 	aConfigGprs.iUseEdge = EFalse;
       
   395 	}
       
   396 
       
   397 void CSpudMan::RetrieveGprsCompression(TUint& aCompression) const
       
   398 	{
       
   399 	aCompression = 0;
       
   400 	TBool isCompression = EFalse;
       
   401 	Notify()->ReadBool(TPtrC(GPRS_DATA_COMPRESSION), isCompression);
       
   402 	if (isCompression)
       
   403 		{
       
   404 		aCompression |= RPacketContext::KPdpDataCompression;
       
   405 		}
       
   406 
       
   407 	isCompression = EFalse;
       
   408 	Notify()->ReadBool(TPtrC(GPRS_HEADER_COMPRESSION), isCompression);
       
   409 	if (isCompression)
       
   410 		{
       
   411 		aCompression |= RPacketContext::KPdpHeaderCompression;
       
   412 		}
       
   413 	}
       
   414 
       
   415 void CSpudMan::RetrieveGprsAnonymousAccess(RPacketContext::TAnonymousAccess& aAnonymous) const
       
   416 	{	
       
   417 	TBool isAnonymous = EFalse;
       
   418 	Notify()->ReadBool(TPtrC(GPRS_ANONYMOUS_ACCESS),isAnonymous);
       
   419 	if (isAnonymous)
       
   420 		aAnonymous = RPacketContext::ERequired;
       
   421 	else
       
   422 		aAnonymous = RPacketContext::ENotRequired;
       
   423 	}
       
   424 
       
   425 
       
   426 
       
   427 /**
       
   428 Indicates whether QoS has been enabled or not.
       
   429 
       
   430 @return ETrue if QoS has been enabled for this NIF.
       
   431 */
       
   432 TBool CSpudMan::AreQoSEventsEnabled() const
       
   433 	{
       
   434 	return iQosEventHandler != NULL;
       
   435 	}
       
   436 
       
   437 
       
   438 /**
       
   439 Returns pointer to BindMan.
       
   440 
       
   441 @return Pointer to BindMan object
       
   442 */
       
   443 CBindMan* CSpudMan::BindMan() const
       
   444 	{
       
   445 	return iBindMan;
       
   446 	}
       
   447 
       
   448 /**
       
   449 Returns pointer to the MNifIfNotify object in NIFMAN.
       
   450 
       
   451 @return Pointer to MNifIfNotify object
       
   452 */
       
   453 MNifIfNotify* CSpudMan::Notify() const
       
   454 	{
       
   455 	ASSERT(iNotify);
       
   456 	return iNotify;
       
   457 	}
       
   458 
       
   459 /**
       
   460 Set default QoS parameters from the values in CommDb.
       
   461 
       
   462 @param aQos QoS parameters filled in on exit
       
   463 */
       
   464 void CSpudMan::ReadDefaultQoS(RPacketQoS::TQoSR99_R4Requested& aQos) const
       
   465 	{
       
   466 	TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName;
       
   467 	_LIT(KFormatText,"%s\\%s");
       
   468 
       
   469 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRAFFIC_CLASS);
       
   470 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTrafficClass));
       
   471 
       
   472 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_CLASS);
       
   473 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinTrafficClass));
       
   474 	
       
   475 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVERY_ORDER);
       
   476 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqDeliveryOrderReqd));
       
   477 
       
   478 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVERY_ORDER);
       
   479 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinDeliveryOrderReqd));
       
   480 	
       
   481 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_DELIVER_ERRONEOUS_SDU);
       
   482 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqDeliverErroneousSDU));
       
   483 
       
   484 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_DELIVER_ERRONEOUS_SDU);
       
   485 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinDeliverErroneousSDU));
       
   486 	
       
   487 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_SDUSIZE);
       
   488 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxSDUSize));
       
   489 
       
   490 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_ACCEPTABLE_MAX_SDU_SIZE);
       
   491 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxSDUSize));
       
   492 	
       
   493 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_UPLINK_RATE);
       
   494 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxRate.iUplinkRate));
       
   495 
       
   496 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_UPLINK_RATE);
       
   497 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxRate.iUplinkRate));
       
   498 	
       
   499 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MAX_DOWNLINK_RATE);
       
   500 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqMaxRate.iDownlinkRate));
       
   501 	
       
   502 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_MIN_DOWNLINK_RATE);
       
   503 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinAcceptableMaxRate.iDownlinkRate));
       
   504 	
       
   505 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_BER);
       
   506 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqBER));
       
   507 	
       
   508 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_BER);
       
   509 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxBER));
       
   510 	
       
   511 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_SDU_ERROR_RATIO);
       
   512 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqSDUErrorRatio));
       
   513 	
       
   514 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_SDU_ERROR_RATIO);
       
   515 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxSDUErrorRatio));
       
   516 
       
   517 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRAFFIC_HANDLING_PRIORITY);
       
   518 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTrafficHandlingPriority));
       
   519 	
       
   520 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_TRAFFIC_HANDLING_PRIORITY);
       
   521 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinTrafficHandlingPriority));
       
   522 
       
   523 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_TRANSFER_DELAY);
       
   524 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqTransferDelay));
       
   525 	
       
   526 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MAX_TRANSFER_DELAY);
       
   527 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMaxTransferDelay));
       
   528 
       
   529 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_UPLINK_RATE);
       
   530 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqGuaranteedRate.iUplinkRate));
       
   531 
       
   532 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_UPLINK_RATE);
       
   533 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinGuaranteedRate.iUplinkRate));
       
   534 
       
   535 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_REQ_GUARANTEED_DOWNLINK_RATE);
       
   536 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iReqGuaranteedRate.iDownlinkRate));
       
   537 
       
   538 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_MIN_GUARANTEED_DOWNLINK_RATE);
       
   539 	Notify()->ReadInt (columnName, reinterpret_cast<TUint32&>(aQos.iMinGuaranteedRate.iDownlinkRate));
       
   540 	}
       
   541 
       
   542 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
   543 /**
       
   544 Set default R5 QoS parameters from the values in CommDb.
       
   545 
       
   546 @param aQos R5 QoS parameters filled in on exit
       
   547 */
       
   548 void CSpudMan::ReadDefaultR5QoS(RPacketQoS::TQoSR5Requested& aQos) const
       
   549 	{
       
   550 	ReadDefaultQoS(aQos);
       
   551 	
       
   552 	TBuf<2*KCommsDbSvrMaxColumnNameLength+2> columnName;
       
   553 	_LIT(KFormatText,"%s\\%s");
       
   554 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_SIGNALLING_INDICATION);
       
   555 	Notify()->ReadBool (columnName, aQos.iSignallingIndication);
       
   556 	columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_SOURCE_STATISTICS_DESCRIPTOR);
       
   557 	Notify()->ReadInt(columnName, reinterpret_cast<TUint32&>(aQos.iSourceStatisticsDescriptor));
       
   558 	}
       
   559 #endif
       
   560 // SYMBIAN_NETWORKING_UMTSR5
       
   561 
       
   562 
       
   563 /**
       
   564 Reads TSY name from CommDb.
       
   565 
       
   566 @param aTsyName TSY name filled in on exit
       
   567 */
       
   568 void CSpudMan::ReadTsyName(TName& aTsyName) const
       
   569 	{
       
   570 	TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName;
       
   571 	_LIT(KFormatText,"%s\\%s");
       
   572 	columnName.Format(KFormatText,MODEM_BEARER,MODEM_TSY_NAME);
       
   573 	Notify()->ReadDes(columnName, aTsyName); // ignore error
       
   574 	}
       
   575 
       
   576 /**
       
   577 Sets the error code to use for termination, unless it is already set.
       
   578 
       
   579 @param aError Error code to use when notifying NIFMAN
       
   580 */
       
   581 void CSpudMan::SetTerminateError(TInt aError)
       
   582 	{
       
   583 	if (iTerminateError == KErrNone)
       
   584 		{
       
   585 		iTerminateError = aError;
       
   586 		__FLOG_1(_L("Set SPUD termination error to [%d]"), aError);
       
   587 		
       
   588 		// There is no specific context associated with this termination
       
   589 		// So prevent a later overwrite of the error by the ETel error
       
   590 		if (iETelTerminateError == KErrNone)
       
   591 			{
       
   592 			iETelTerminateError = aError;
       
   593 			}
       
   594 		}
       
   595 	}
       
   596 
       
   597 /**
       
   598 Sets the error code to use for termination, unless it is already set.
       
   599 
       
   600 @param aContextId context ID
       
   601 @param aError Error code to use when notifying NIFMAN
       
   602 */
       
   603 void CSpudMan::SetTerminateError(TContextId aContextId, TInt aError)
       
   604 	{
       
   605 	if (iTerminateError == KErrNone)
       
   606 		{
       
   607 		iTerminateError = aError;
       
   608 		
       
   609 		// Now check to see if ETel was the originator of this error
       
   610 		if (iETelTerminateError == KErrNone)
       
   611 			{
       
   612 			// ask for the last ETel error received - ignore return code
       
   613 			iPdpFsmInterface.GetLastErrorCause(aContextId, iETelTerminateError);
       
   614 			}
       
   615 
       
   616 		if (iETelTerminateError != KErrNone)
       
   617 			{
       
   618 			// Overwrite with the most likely original error code!
       
   619 			iTerminateError = iETelTerminateError;
       
   620 			}
       
   621 	
       
   622 		__FLOG_1(_L("Set SPUD termination error to [%d]"), iTerminateError);
       
   623 		}
       
   624 		
       
   625 	}
       
   626 
       
   627 //*****************************************************************************
       
   628 // Events receivers
       
   629 //*****************************************************************************
       
   630 
       
   631 /**
       
   632 Receives events from SpudFsm.
       
   633 
       
   634 @param aContextId context ID
       
   635 @param aEvent event ID
       
   636 @param aParam optional parameter to event
       
   637 */
       
   638 void CSpudMan::Input(TContextId aContextId, TInt aEvent, TInt aParam)
       
   639 	{
       
   640 	__FLOG_4(_L("SpudMan::Input: SpudFsm event %S(%d) param[%d] context[%d]"), SpudFsmEventToText(aEvent), aEvent, aParam, aContextId);
       
   641 	ASSERT(aContextId == KAllContexts || (aContextId >=0 && aContextId < KMaxPdpContexts));
       
   642 	
       
   643 	switch (aEvent)
       
   644 		{
       
   645 	case KPrimaryContextCreated:
       
   646 		{
       
   647 		HandlePrimaryContextCreatedEvent(aContextId, aParam);
       
   648 		break;
       
   649 		}
       
   650 	
       
   651 	case KContextDeleteEvent:
       
   652 		{
       
   653 		HandleContextDeleteEvent(aContextId, aParam);
       
   654 		break;
       
   655 		}
       
   656 
       
   657 	case KSecondaryContextCreated:
       
   658 		{
       
   659 		HandleSecondaryContextCreatedEvent(aContextId, aParam);
       
   660 		break;
       
   661 		}
       
   662 
       
   663 	case KContextActivateEvent:
       
   664 		{
       
   665 		HandleContextActivateEvent(aContextId, aParam);
       
   666 		break;
       
   667 		}
       
   668 
       
   669 	case KContextQoSSetEvent:
       
   670 		{
       
   671 		HandleContextQoSSetEvent(aContextId, aParam);
       
   672 		break;
       
   673 		}
       
   674 
       
   675 	case KContextTFTModifiedEvent:
       
   676 		{
       
   677 		HandleContextTFTModifiedEvent(aContextId, aParam);
       
   678 		break;
       
   679 		}
       
   680 
       
   681 	case KGetNegQoSEvent:
       
   682 		{
       
   683 		HandleGetNegQoSEvent(aContextId, aParam);
       
   684 		break;
       
   685 		}
       
   686 
       
   687 	case KContextModifyActiveEvent:
       
   688 		{
       
   689 		HandleContextModifyActiveEvent(aContextId, aParam);
       
   690 		break;
       
   691 		}
       
   692 
       
   693 	case KNetworkStatusEvent:
       
   694 		{
       
   695 		HandleNetworkStatusEvent();
       
   696 		break;
       
   697 		}
       
   698 
       
   699 	case KContextParametersChangeEvent:
       
   700 		{
       
   701 		HandleContextParametersChangeEvent(aContextId, aParam);
       
   702         break;
       
   703 		}
       
   704 
       
   705 	case KContextBlockedEvent:
       
   706 		{
       
   707 		HandleContextBlockedEvent(aContextId);
       
   708 		break;
       
   709 		}
       
   710 
       
   711 	case KContextUnblockedEvent:
       
   712 		{
       
   713 		HandleContextUnblockedEvent(aContextId);
       
   714 		break;
       
   715 		}
       
   716 
       
   717 
       
   718    case KPdpFsmShuttingDown:
       
   719       {
       
   720       __FLOG_0(_L("UmtsGprsSCPR has shutdown the PDP Fsm Interface"));
       
   721       iPdpFsmInterface.Close();
       
   722       break;
       
   723       }
       
   724 
       
   725 	default:
       
   726 		__FLOG_1(_L("Unhandled event %d"), aEvent);
       
   727 		ASSERT(EFalse);
       
   728 		break;
       
   729 		}
       
   730 	}
       
   731 	
       
   732 void CSpudMan::InitPdpFsmInterfaceL()
       
   733 	{
       
   734 	class XAssociatedNifConnectionProviderQuery : public MFactoryQuery
       
   735 	/**	Finds the connection provider associated with the specified Nif.
       
   736 	@internalTechnology
       
   737 	*/
       
   738 		{
       
   739 	public:
       
   740 		XAssociatedNifConnectionProviderQuery( const TDesC& aName, ::TMetaDes8& aNameBuffer ) : iNifName( aName ), iNifNameBuffer( aNameBuffer )
       
   741 			{
       
   742 			}
       
   743 
       
   744 		virtual TMatchResult Match( TFactoryObjectInfo& aObjectInfo )
       
   745 			{
       
   746 			TConnInterfaceName& name = *reinterpret_cast<TConnInterfaceName*>( const_cast<TUint8*>( iNifNameBuffer.iDes->Ptr() ) );
       
   747 			name.iIndex = 1;
       
   748 
       
   749 			TInt err = KErrNone;
       
   750 			TMatchResult result = EContinue;
       
   751 			
       
   752 			// Check each of the connection provider interfaces' names to see if it
       
   753 			// is associated with this NIF.
       
   754 			while( ETrue )
       
   755 				{
       
   756 		        TRAP( err, static_cast<CConnectionProviderBase*>( aObjectInfo.iInfo.iFactoryObject )->ControlL(KCOLProvider, KConnGetInterfaceName, iNifNameBuffer, NULL) );
       
   757 		        
       
   758 		        if( err == KErrNone )
       
   759 		        	{
       
   760 		        	if( name.iName == iNifName )
       
   761 			        	{
       
   762 				       	result = EMatch;
       
   763 				       	
       
   764 				       	break;
       
   765 			        	}
       
   766 			       	}
       
   767 			    else
       
   768 			    	{
       
   769 			    	break;
       
   770 			    	}
       
   771 
       
   772 				name.iIndex ++;
       
   773 				}
       
   774 	        	
       
   775 	        return result;
       
   776 			}
       
   777 			
       
   778 	private:
       
   779 		const TDesC& iNifName;
       
   780 		::TMetaDes8& iNifNameBuffer;
       
   781 		};
       
   782 
       
   783 	const TUint KShimConnectionProviderFactoryId = 0x10207104; //the same as CSubConnectionProviderFactoryShim
       
   784 
       
   785 	TSockManData* sockManData = SockManGlobals::Get();
       
   786 	ASSERT(sockManData);
       
   787 
       
   788 	CConnectionFactoryContainer* connectionFactories = sockManData->iConnectionFactories;
       
   789 	ASSERT(connectionFactories);
       
   790 
       
   791 	CConnectionProviderFactoryBase *factory = connectionFactories->FindFactory(KShimConnectionProviderFactoryId);
       
   792 	if(!factory)
       
   793 		{
       
   794 		User::Leave( KErrNotFound );
       
   795 		}
       
   796 		
       
   797 	CSpudMux* mux = iBindMan->SpudMux();
       
   798 
       
   799 	// Get the name of our SPUDMUX interface - it uniquely identifies this SPUD object assembly.
       
   800 	TNifIfInfo info;
       
   801 	mux->Info( info );
       
   802 
       
   803 	// Create a buffer to hold the name of each interface we check to see if the interface is our SPUDMUX.
       
   804 	TPckgBuf<TConnInterfaceName> name;
       
   805 	TPtrC8 desC( name );
       
   806 	::TMetaDes8* des = ::TMetaDes8::NewL( &desC );
       
   807 
       
   808 	XAssociatedNifConnectionProviderQuery connProviderQuery( info.iName, *des );
       
   809 	
       
   810 	// Find the connection provider associated with this NIF.
       
   811 	CConnectionProviderBase* connectionProvider = factory->FindProvider(connProviderQuery);
       
   812 	delete des;
       
   813 	if(!connectionProvider)
       
   814 		{
       
   815 		User::Leave( KErrNotFound );
       
   816 		}
       
   817 
       
   818 	CSubConnectionFactoryContainer* subConnectionFactories = sockManData->iSubConnectionFactories;
       
   819 	ASSERT(subConnectionFactories);
       
   820 
       
   821 	TDataClientQuery subConnProviderQuery(connectionProvider, ESubConnPlane, RSubConnection::EAttachToDefault);
       
   822 
       
   823 	// Find the default subconnection provider.
       
   824 	CSubConnectionProviderBase* subConnProvider = subConnectionFactories->FindOrCreateProviderL(connectionProvider->CanDoSubConnection(RSubConnection::EAttachToDefault), subConnProviderQuery);
       
   825 	if(!subConnProvider || subConnProvider->Factory().Id() != KUmtsGprsSubConnectionProviderFactoryId)
       
   826 		{
       
   827 		User::Leave( KErrNotFound );
       
   828 		}
       
   829 
       
   830 	// Initialise the PDP FSM interface.
       
   831 	TPckg<CNifIfBase*> nifPckg(mux);
       
   832 	User::LeaveIfError(subConnProvider->Control(KSOLInterface, KInitialisePdpFsm, nifPckg));
       
   833 	}
       
   834 
       
   835 void CSpudMan::HandlePrimaryContextCreatedEvent(TContextId aContextId, TInt aError)
       
   836 	{
       
   837 		
       
   838 	// Save the contextId for later
       
   839 	iPrimaryContextId = aContextId;
       
   840 	
       
   841 	// Primary context has been created; Start the lower NIF
       
   842 	CSpudBinderRef* ref = NULL;
       
   843 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
   844 	__FLOG_2(_L("Got lower NIF binder for context[%d] with error[%d]"), aContextId, rc);
       
   845 	if (rc == KErrNone)
       
   846 		{
       
   847 		// Make sure context was created successfully
       
   848 		rc = aError;
       
   849 		ASSERT(ref->IsBound());
       
   850 		__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
   851 		}
       
   852 
       
   853 	if (KErrNone == rc) // Context created successfully.
       
   854 		{
       
   855 			// Get the details of the P-CSCF 
       
   856 		RPacketContext::TContextConfigGPRS config;
       
   857 		
       
   858 		if (iPdpFsmInterface.Get(aContextId, config) == KErrNone)
       
   859 			{
       
   860 			TRAP(rc, SetSipServerAddrL(config.iProtocolConfigOption););
       
   861 				{
       
   862 				__FLOG_1(_L("CSpudMan::HandlePrimaryContextCreatedEvent -Error occurred extracting the sip server address: %d"),rc);
       
   863 				//rc is now non zero, therefore should fail gracefully
       
   864 				}	
       
   865 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
   866 			// Since the value or IMCN Signalling flag also comes in PCO IE buffer along with the SipAddress, we
       
   867 			// need to extract the value here and set it to Parameter Bundle of SCPR
       
   868 				TBool imcn = EFalse;		
       
   869 				TRAPD(err,imcn=GetIMCNSignallingFlagPcoL(config.iProtocolConfigOption););
       
   870 				__FLOG_1(_L("CSpudMan::GetIMCNSignallingFlagPcoL - returns eror=%d"),err);
       
   871 				if (err == KErrNone)
       
   872 					{
       
   873 					iPdpFsmInterface.SetIMCNSignalling(imcn); //imcn contains ETrue or Efalse
       
   874 #ifdef __FLOG_ACTIVE
       
   875 					if (imcn)
       
   876 						{
       
   877 						__FLOG_0(_L("CSpudMan::HandlePrimaryContextCreatedEvent - Network ACCEPTS the request for dedicated IMCN Signalling Flag "));
       
   878 						}
       
   879 					else
       
   880 						{
       
   881 						__FLOG_0(_L("CSpudMan::HandlePrimaryContextCreatedEvent - Network REJECTS the request for dedicated IMCN Signalling Flag "));				
       
   882 						}
       
   883 #endif 
       
   884 					}
       
   885 					else
       
   886 					{
       
   887 					
       
   888 #ifdef __FLOG_ACTIVE
       
   889 					__FLOG_1(_L("CSpudMan::HandlePrimaryContextCreatedEvent -Leave Error occurred  %d"),err);
       
   890 #endif
       
   891 					}			
       
   892 #endif // SYMBIAN_NETWORKING_UMTSR5
       
   893 			}
       
   894 		}
       
   895 		
       
   896 	if (KErrNone == rc) // Sip server address retrieved
       
   897 		{
       
   898 		ASSERT(ref->State() == ESpudCreatingPrimary);
       
   899 	    ref->SetState(ESpudStartingPrimary);
       
   900 	    // Start the lower NIF and wait for the LinkLayerUp call
       
   901 		rc = ref->NifLink()->Start(); 
       
   902 		if(KErrNone == rc)
       
   903 			{
       
   904 			ref->SetState(ESpudStartingPrimaryLowerNif);
       
   905 			}
       
   906 		// Lower NIF may still report failure to Start by signalling LinkLayerDown with error.
       
   907 		// E.G. PPP negotiation may fail.
       
   908 		__FLOG_2(_L("Lower NIF for Primary Context[%d] started with error[%d]."), aContextId, rc);
       
   909 		}
       
   910 
       
   911 		
       
   912 	// Catch-all error handling: Could not create context, or could not start lower NIF.	
       
   913 	if(KErrNone != rc) 
       
   914 		{			
       
   915 		SetTerminateError(rc);	
       
   916 		
       
   917 	    SendPrimaryContextCreated(aContextId, rc); // Notify GUQoS of error
       
   918 
       
   919  		if(ESpudStartingPrimary == ref->State()) // Context created 
       
   920  			{
       
   921  			ref->SetState(ESpudWaitLinkDown); // We've just notified GUQoS.
       
   922  			// Delete context via SpudFsm
       
   923 			__FLOG_2(_L("Failed to start lower NIF for Primary PDP context[%d] due to error[%d]. Deleting Primary via SpudFsm."), aContextId, rc);
       
   924 			rc = iPdpFsmInterface.Input(aContextId, EContextDelete);
       
   925 			ASSERT(rc == KErrNone);
       
   926  			}
       
   927  		else 	// Context was not created, else we would not be here. There is nothing to stop and delete.
       
   928  			{
       
   929  			__FLOG_1(_L("Failed to create Primary context[%d]. Spud will shut down."), aContextId);
       
   930 			
       
   931  			if (AreQoSEventsEnabled())
       
   932 				{
       
   933 				// At this point we know that SPUD is about to shut down, because we are
       
   934 				// deleting the last context. We want to indicate to the upper layers early that
       
   935 				// data can no longer be sent to SPUD.
       
   936 									
       
   937 				// Tell GUQoS to stop bothering SPUD.
       
   938 				// GUQoS returns the favour by turning off the NIF events within this very call.
       
   939 				// This means we won't send KNetworkInterfaceDown, even if we try.
       
   940 		   		// *********************************************************************************************
       
   941 				// N.B.: "DEF055691 	GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack
       
   942     			// closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event.
       
   943     			// As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only
       
   944     			// from the destructor. Once this defect is fixed, the following line must be uncommented: 
       
   945     			// SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached);
       
   946 				//**********************************************************************************************
       
   947 		   		}
       
   948 			// We are about to delete the primary context NIF: this will notify Nifman that SPUD is finished.
       
   949  			DisposeOfBinder(ref);
       
   950  			}
       
   951  		}		
       
   952 	}
       
   953 
       
   954 void CSpudMan::HandleContextDeleteEvent(TContextId aContextId, TInt aError)
       
   955 	{
       
   956 	aError = aError; // suppress compiler warning
       
   957 	// Ignore error on delete--nothing we can do, anyway
       
   958 	// For the upper layers, we treat this event as KErrDisconnected, because the network has torn down an 
       
   959 	// existing context.
       
   960 	CSpudBinderRef* ref = NULL;
       
   961 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
   962 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
   963 	ASSERT(ref->IsBound());
       
   964 	__FLOG_4(_L("Network deleted context %d, in state %S(%d). Deletion error=%d"),
       
   965 		aContextId, SpudStateToText(ref->State()), ref->State(), aError);
       
   966 	
       
   967 	// Are we about to shut down after this context is deleted?
       
   968 	TBool shutdownStarted(BindMan()->IsLastContext(aContextId));
       
   969 	// We must determine this before we make any state transitions. But we can act on this
       
   970 	// only after we've done all GUQoS notifications to make sure shutdown is graceful.
       
   971 	
       
   972 	switch (ref->State()) 
       
   973 		{
       
   974 	case ESpudUp:
       
   975 	case ESpudFlowOff:
       
   976 	case ESpudSuspended:
       
   977 	case ESpudFlowOffAndSuspended:
       
   978 		ref->SetState(ESpudWaitLinkDown);
       
   979 		SendContextDeleteEvent(aContextId);
       
   980 		ref->NifLink()->Stop(KErrConnectionTerminated, MNifIfNotify::EDisconnect);
       
   981         break;
       
   982         
       
   983     case ESpudStartingPrimaryLowerNif:
       
   984     	ref->SetState(ESpudWaitLinkDown);
       
   985     	SendPrimaryContextCreated(aContextId, KErrDisconnected);
       
   986     	SendContextDeleteEvent(aContextId);
       
   987     	ref->NifLink()->Stop(KErrConnectionTerminated, MNifIfNotify::EDisconnect);
       
   988         break;
       
   989         	        
       
   990 	case ESpudGettingNegQoS: // Context was activated. It is assumed that QoS retrieval would be cancelled by deletion.
       
   991 	case ESpudStartingSecondaryLowerNif:
       
   992 		ref->SetState(ESpudStartingSecondary);
       
   993 		FillInContextConfig(iTempContextConfig, aContextId);
       
   994 		SendContextActivateEvent(aContextId, iTempContextConfig, KErrDisconnected);
       
   995 		SendContextDeleteEvent(aContextId);
       
   996 		ref->NifLink()->Stop(KErrConnectionTerminated, MNifIfNotify::EDisconnect);
       
   997         break;
       
   998 		
       
   999 	case ESpudStartingPrimary: 
       
  1000 		// this should never happen
       
  1001 		SendPrimaryContextCreated(aContextId, KErrDisconnected);
       
  1002 		SendContextDeleteEvent(aContextId);
       
  1003 		DisposeOfBinder(ref);
       
  1004 		break;
       
  1005 	
       
  1006 	case ESpudStartingSecondary:
       
  1007 		// This should never happen, and may cause problems if it does because there could be
       
  1008 		// another outstanding request from GUQoS that never gets completed.
       
  1009 		__FLOG_0(_L("Network should not have deleted context in ESpudStartingSecondary state!"));
       
  1010 		// Fall through and treat the same as ESpudLinkDown
       
  1011 		
       
  1012 	case ESpudLinkDown:
       
  1013 		SendContextDeleteEvent(aContextId);
       
  1014 		DisposeOfBinder(ref);
       
  1015 		break;
       
  1016 	
       
  1017 	case ESpudWaitLinkDown:	
       
  1018 		DisposeOfBinder(ref);
       
  1019 		break;
       
  1020 		
       
  1021 	
       
  1022 	default:
       
  1023 		__FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State());
       
  1024 		ASSERT(EFalse);
       
  1025 		break;
       
  1026 		}
       
  1027 	
       
  1028 	if(shutdownStarted) // Additional steps if we are shutting down as as result of this deletion.
       
  1029 		{
       
  1030 		SetTerminateError(KErrDisconnected); 
       
  1031 		// We don't reuse errorForGuqos, because we may want to keep Nifman errors and GUQoS errors separate.	
       
  1032 		if (AreQoSEventsEnabled())
       
  1033 			{
       
  1034 			// At this point we know that SPUD is about to shut down, because the last context 
       
  1035 			// was just deleted. We want to indicate to the upper layers early that
       
  1036 			// data can no longer be sent to SPUD.
       
  1037 								
       
  1038 			// Tell GUQoS to stop bothering SPUD.
       
  1039 			// GUQoS returns the favour by turning off the NIF events within this very call.
       
  1040 			// This means we send KNetworkInterfaceDown only once.
       
  1041 			// *******************************************************************************************
       
  1042 			// N.B.: "DEF055691 	GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack
       
  1043     		// closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event.
       
  1044     		// As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only
       
  1045     		// from the destructor. Once this defect is fixed, the following line must be uncommented: 
       
  1046     		// SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached);
       
  1047 			//**********************************************************************************************
       
  1048 			}	
       
  1049 		}	
       
  1050 	}
       
  1051 
       
  1052 void CSpudMan::HandleSecondaryContextCreatedEvent(TContextId aContextId, TInt aError)
       
  1053 	{
       
  1054 	CSpudBinderRef* ref = NULL;
       
  1055 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1056 	if (rc == KErrNone)
       
  1057 		{
       
  1058 		ASSERT(ref->IsBound());
       
  1059 		__FLOG_4(_L("Network created secondary context[%d] in state %S(%d). Creation error=%d "),aContextId, SpudStateToText(ref->State()), ref->State(), aError);
       
  1060 		if (ref->State() != ESpudStartingSecondary)
       
  1061 			{
       
  1062 			__FLOG_3(_L("KSecondaryContextCreated context %d is in unexpected state %S(%d)"),
       
  1063 			         aContextId, SpudStateToText(ref->State()), ref->State());
       
  1064 			}
       
  1065 		ref = ref;	// Eliminate compiler warning in release builds
       
  1066 		
       
  1067 		// Make sure context was created successfully
       
  1068 		rc = aError;
       
  1069 		if(KErrNone != rc) // Creation failed: we don't have the context, only the binder. Delete it.
       
  1070 			{
       
  1071 			DisposeOfBinder(ref);
       
  1072 			}
       
  1073 		}
       
  1074 	SendSecondaryContextCreated(aContextId, rc);
       
  1075 	}
       
  1076 
       
  1077 void CSpudMan::HandleContextActivateEvent(TContextId aContextId, TInt aError)
       
  1078 	{
       
  1079 	CSpudBinderRef* ref = NULL;
       
  1080 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1081 	if (rc == KErrNone)
       
  1082 		{
       
  1083 		// Make sure context was activated successfully
       
  1084 		rc = aError;
       
  1085 	
       
  1086 		ASSERT(ref->IsBound());
       
  1087 		__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1088 		}
       
  1089 
       
  1090 	if (rc == KErrNone)
       
  1091 		{
       
  1092 		ASSERT(ref->State() == ESpudStartingSecondary);
       
  1093 		// Start the lower NIF
       
  1094 		rc = ref->NifLink()->Start(); 
       
  1095 		// Even if we get KErrNone here, we may still get LinkLayerDown with error later.
       
  1096 		__FLOG_2(_L("KContextActivateEvent: Start on lower NIF returned for Context[%d] returned error[%d]"),aContextId, rc);
       
  1097 		}
       
  1098 	
       
  1099 	if(KErrNone == rc) // Start OK.
       
  1100 		{
       
  1101 		
       
  1102 		ref->SetState(ESpudStartingSecondaryLowerNif);
       
  1103 		}
       
  1104 	else
       
  1105 		{
       
  1106 		// Error activating PDP context
       
  1107 		FillInContextConfig(iTempContextConfig, aContextId);
       
  1108 		SendContextActivateEvent(aContextId, iTempContextConfig, rc);
       
  1109 		}
       
  1110 	}
       
  1111 
       
  1112 void CSpudMan::HandleContextQoSSetEvent(TContextId aContextId, TInt aError)
       
  1113 	{
       
  1114 	// Notify GUQoS of success or failure
       
  1115     SendContextQoSSetEvent(aContextId, aError);
       
  1116 	}
       
  1117 
       
  1118 void CSpudMan::HandleContextTFTModifiedEvent(TContextId aContextId, TInt aError)
       
  1119 	{
       
  1120 	CSpudBinderRef* ref = NULL;
       
  1121 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1122 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1123 	ASSERT(ref->IsBound());
       
  1124 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1125 	ref = ref;	// Eliminate compiler warning in release builds
       
  1126 
       
  1127 	// Notify GUQoS of success or failure
       
  1128 	TTFTOperationCode opCode;
       
  1129     iPdpFsmInterface.Get(aContextId, opCode);
       
  1130     SendContextTFTModifiedEvent(aContextId, opCode, aError);
       
  1131 	}
       
  1132 
       
  1133 void CSpudMan::HandleGetNegQoSEvent(TContextId aContextId, TInt aError)
       
  1134 	{
       
  1135 	CSpudBinderRef* ref = NULL;
       
  1136 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1137 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1138 	
       
  1139 	ASSERT(ref->IsBound());
       
  1140 	__FLOG_4(_L("CSpudMan: Retrieved Negotiated QoS, error=%d: context %d is in state %S(%d)"), aError, aContextId, SpudStateToText(ref->State()), ref->State());
       
  1141 	if (ref->State() == ESpudGettingNegQoS)
       
  1142 		{
       
  1143 		// Negotiated QoS retrieved successfully. At this point the ctx is up both on control and data paths.
       
  1144 		if(KErrNone == aError) 
       
  1145 			{
       
  1146 			// Context is now fully up. Notify GUQoS.
       
  1147 			ref->SetState(ESpudUp);
       
  1148 			// Notify GUQoS of success or failure
       
  1149 			FillInContextConfig(iTempContextConfig, aContextId);
       
  1150     		SendContextActivateEvent(aContextId, iTempContextConfig, aError);
       
  1151 			
       
  1152 			if(ref->State() == ESpudUp) // GUQoS can delete the context from the activation notification.
       
  1153 				{
       
  1154 				BindMan()->SpudProtocol()->DoStartSending();
       
  1155 				SendContextUnblockedEvent(aContextId);	
       
  1156 				}
       
  1157 			}
       
  1158 		// If the QoS could not be retrieved, we remain in ESpudGettingNegQoS and wait for 
       
  1159 		// the network to delete the context. The rest would be handled from the deletion event.
       
  1160 		
       
  1161 		// N.B. CRITICAL ASSUMPTION: 
       
  1162 		// The network / TSY will delete the ctx if the negotiated QoS could not be retrieved.
       
  1163 		// (The idea is that if QoS negotiation is errored out, then everything is errored out.
       
  1164 		// So we either do not get to this point at all, or will be errored out soon after this handler completes.)
       
  1165 		// This leaves the issue of internal ETel/TSY errors such as OOM conditions.)
       
  1166 		// At this point Spud is idle (no requests outstanding), so nothing will drive us
       
  1167 		// forward to clean up this failure. GUQoS does NOT time out on PDP context creation failure.
       
  1168 		}
       
  1169 	else
       
  1170 		{
       
  1171 		// If we are not getting negotiated QoS, but we receive this notification, then:
       
  1172 		// - ETel has sent us a stray notification totally uncalled for, i.e. it's a bug in ETel or more likely a TSY.
       
  1173 		if(KErrNone == aError)
       
  1174 			{
       
  1175 			__FLOG(_L("WARNING! Negotiated QoS retrieval completed successfully, but totally out of order! See the comments in the code.)"));
       
  1176 			}
       
  1177 		// We don't assert, because it can be a race condition outside of ETel's control:
       
  1178 		// - ETel, lower NIF, GUQoS, Nifman has errored the context out (e.g. ctx deleted by network), so there was a 
       
  1179 		// state transition as a result of that, and now the QoS retrieval has completed after that with KErrNone.
       
  1180 		}
       
  1181 	}
       
  1182 
       
  1183 
       
  1184 void CSpudMan::HandleContextModifyActiveEvent(TContextId aContextId, TInt aError)
       
  1185 	{
       
  1186 	// Notify GUQoS of success or failure
       
  1187 	FillInContextConfig(iTempContextConfig, aContextId);
       
  1188     SendContextModifyActiveEvent(aContextId, iTempContextConfig, aError);
       
  1189 	}
       
  1190 
       
  1191 void CSpudMan::HandleNetworkStatusEvent()
       
  1192 	{
       
  1193 	// This is a network status change
       
  1194 	RPacketService::TStatus status;
       
  1195 	iPdpFsmInterface.Get(status);
       
  1196 	
       
  1197 	// Assume that anything other than EStatusUnattached means the network
       
  1198 	// is still up, so just ignore this event.
       
  1199 	if (status == RPacketService::EStatusUnattached)
       
  1200 		{
       
  1201 		// Notify GUQoS
       
  1202 		SendNetworkStatusEvent(KNetworkConnectionLost, status);
       
  1203 		}
       
  1204 	else
       
  1205 		{
       
  1206 		__FLOG_1(_L("Ignoring KNetworkStatusEvent with status %d (NOT EStatusUnattached)"),
       
  1207 				 status);
       
  1208 		}
       
  1209 	}
       
  1210 
       
  1211 void CSpudMan::HandleContextParametersChangeEvent(TContextId aContextId, TInt aError)
       
  1212 	{
       
  1213 	// This is a status change on an individual context
       
  1214 	CSpudBinderRef* ref = NULL;
       
  1215 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1216 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1217 	ASSERT(ref->IsBound());
       
  1218 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1219 	if (ref->State() == ESpudGettingNegQoS || ref->State() == ESpudUp || ref->State() == ESpudFlowOff || ref->State() == ESpudSuspended || ref->State() == ESpudFlowOffAndSuspended)
       
  1220 		{
       
  1221 		// Only pass on context changes while the context is up
       
  1222 		FillInContextConfig(iTempContextConfig, aContextId);
       
  1223 		SendContextParametersChangeEvent(aContextId, iTempContextConfig, aError);
       
  1224 		}
       
  1225 	else
       
  1226 		{
       
  1227 		__FLOG_3(_L("KContextParametersChangeEvent ignored on context %d because of nonoperational state %S(%d)"),
       
  1228 				 aContextId, SpudStateToText(ref->State()), ref->State());
       
  1229         SetTerminateError(aContextId, aError);
       
  1230 		}
       
  1231 	}
       
  1232 
       
  1233 void CSpudMan::HandleContextBlockedEvent(TContextId aContextId)
       
  1234 	{
       
  1235 	// Context is suspended (see StopSending)
       
  1236 	CSpudBinderRef* ref = NULL;
       
  1237 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1238 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1239 	ASSERT(ref->IsBound());
       
  1240 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1241 	switch (ref->State())
       
  1242 		{
       
  1243 	case ESpudUp:
       
  1244 		{
       
  1245 		ref->SetState(ESpudSuspended);
       
  1246 		if (AreQoSEventsEnabled())
       
  1247 			{
       
  1248 			SendContextBlockedEvent(aContextId);
       
  1249 			}
       
  1250 			
       
  1251 		// Send an IfProgress to Nifman so that RConnection::ProgressNotification reports the blockage etc.
       
  1252 		Notify()->IfProgress(KDataTransferTemporarilyBlocked, KErrNone);
       
  1253 		break;
       
  1254 		}
       
  1255 
       
  1256 	case ESpudFlowOff:
       
  1257 		ref->SetState(ESpudFlowOffAndSuspended);
       
  1258 			
       
  1259 		// Send an IfProgress to Nifman so that RConnection::ProgressNotification reports the blockage etc.
       
  1260 		Notify()->IfProgress(KDataTransferTemporarilyBlocked, KErrNone);
       
  1261 		break;
       
  1262 
       
  1263 	case ESpudSuspended:
       
  1264 	case ESpudFlowOffAndSuspended:
       
  1265 		// Ignore this since we're already suspended
       
  1266 		break;
       
  1267 
       
  1268 	default:
       
  1269 		// Ignore this since we're still starting up or shutting down
       
  1270 		__FLOG_1(_L("Can't send blocked event now on context %d"), aContextId);
       
  1271 		break;
       
  1272 		}
       
  1273 		
       
  1274 	// TODO: Probably need to send IfProgress here where aStage==KDataTransferTemporarilyBlocked
       
  1275 	// or Notification with aEvent=EAgentToNifEventTypeDisableTimers
       
  1276 	//
       
  1277 	// NOTE: The IfProgress has now been implemented so that callers of RConnection::ProgressNotification
       
  1278 	// expecting to receive KDataTransferTemporarilyBlocked actually get it if the PDP context is
       
  1279 	// suspended (details of problem in INC107930).
       
  1280 	}
       
  1281 
       
  1282 void CSpudMan::HandleContextUnblockedEvent(TContextId aContextId)
       
  1283 	{
       
  1284 	// Context is suspended (see StartSending)
       
  1285 	CSpudBinderRef* ref = NULL;
       
  1286 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1287 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1288 	ASSERT(ref->IsBound());
       
  1289 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1290 	switch (ref->State())
       
  1291 		{
       
  1292 	case ESpudUp:
       
  1293 	case ESpudFlowOff:
       
  1294 		// Ignore this since we're already in an unsuspended state
       
  1295 		break;
       
  1296 
       
  1297 	case ESpudSuspended:
       
  1298 		{
       
  1299 		ref->SetState(ESpudUp);
       
  1300 
       
  1301 		BindMan()->SpudProtocol()->DoStartSending();
       
  1302 
       
  1303 		if (AreQoSEventsEnabled())
       
  1304 			{
       
  1305 			SendContextUnblockedEvent(aContextId);
       
  1306 			}
       
  1307 		Notify()->IfProgress(KLinkLayerOpen, KErrNone);
       
  1308 		break;
       
  1309 		}
       
  1310 
       
  1311 	case ESpudFlowOffAndSuspended:
       
  1312 		{
       
  1313 		ref->SetState(ESpudFlowOff);
       
  1314 		Notify()->IfProgress(KLinkLayerOpen, KErrNone);
       
  1315 		break;
       
  1316 		}
       
  1317 
       
  1318 	default:
       
  1319 		// Ignore this since we're still starting up or shutting down
       
  1320 		__FLOG_1(_L("Can't send unblocked event now on context %d; this may cause problems"), aContextId);
       
  1321 		break;
       
  1322 		}
       
  1323 	}
       
  1324 
       
  1325 /**
       
  1326 Receives event from GUQoS.
       
  1327 
       
  1328 @param aName event identification
       
  1329 @param aOption optional data associated with event
       
  1330 @return error code
       
  1331 */
       
  1332 TInt CSpudMan::GuqosInput(TUint aName, TDes8& aOption)
       
  1333 	{
       
  1334 	__FLOG_2(_L("SpudMan::GuqosInput: GUQoS event %S(%d)"), SpudGuQoSEventToText(aName), aName);
       
  1335 	switch (aName)
       
  1336 		{
       
  1337 	case KSoIfControllerPlugIn:
       
  1338         {
       
  1339         // Indicate that we want GUQoS
       
  1340         TSoIfControllerInfo& opt = *reinterpret_cast<TSoIfControllerInfo*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1341         _LIT(KQosPlugInName, "guqos");
       
  1342         opt.iPlugIn = KQosPlugInName;
       
  1343         opt.iProtocolId = KQosPlugInProtocolId;
       
  1344         return KErrNone;
       
  1345         }
       
  1346 
       
  1347     case KRegisterEventHandler:
       
  1348         {
       
  1349         // GUQoS has passed a pointer to its event handler
       
  1350         const TEvent *handler = reinterpret_cast<const TEvent *>(aOption.Ptr());
       
  1351         iQosEventHandler = static_cast<MNifEvent *>(handler->iEvent);
       
  1352         ASSERT(iQosEventHandler);
       
  1353         return KErrNone;
       
  1354         }
       
  1355 
       
  1356 	case KContextSetEvents:
       
  1357 		{
       
  1358         if (!AreQoSEventsEnabled())
       
  1359         	{
       
  1360         	// Event handler must be registered first
       
  1361             return KErrGeneral;
       
  1362         	}
       
  1363         const TBool* eventsEnabledPtr = reinterpret_cast<const TBool *>(aOption.Ptr());
       
  1364         ASSERT(eventsEnabledPtr);
       
  1365         iQosEventsEnabled = *eventsEnabledPtr;
       
  1366 
       
  1367         // Has a primary PDP context has already been created?
       
  1368        	CSpudBinderRef* ref = NULL;
       
  1369 		TRAPD(rc, ref = BindMan()->GetAnyRefL());
       
  1370 		const TBool havePrimary(rc == KErrNone && (ref->State() == ESpudUp || ref->State() == ESpudFlowOff || ref->State() == ESpudSuspended || ref->State() == ESpudFlowOffAndSuspended));
       
  1371 
       
  1372         if (iQosEventsEnabled && havePrimary)
       
  1373         	{
       
  1374         	// iPrimaryContextId == KPrimaryContextId == 0 at startup
       
  1375             SendPrimaryContextCreated(iPrimaryContextId, KErrNone);
       
  1376             }
       
  1377         return KErrNone;
       
  1378 		}
       
  1379 
       
  1380 	case KNifSetDefaultQoS:
       
  1381 		{
       
  1382          ASSERT(aOption.Ptr());
       
  1383          const TContextParameters& opt = *reinterpret_cast<const TContextParameters*>(aOption.Ptr());
       
  1384 
       
  1385          if (!iPdpFsmInterface.IsInitialised()) 
       
  1386             {
       
  1387             __FLOG_0(_L("CSpudMan::GuqosInput: iPdpFsmInterface not initialised, parking KNifSetDefaultQoS."));
       
  1388             
       
  1389             if (iParkedDefaultQoS == NULL)
       
  1390                {
       
  1391                TRAPD(err, iParkedDefaultQoS = HBufC8::NewL (sizeof (TContextParameters)));
       
  1392                if (err != KErrNone)
       
  1393                   {
       
  1394                   __FLOG_0(_L("CSpudMan::GuqosInput: Failed to park default QoS."));
       
  1395                   return err;
       
  1396                   }
       
  1397                }
       
  1398                
       
  1399             iParkedDefaultQoS->Des().Copy (aOption);
       
  1400 
       
  1401             return KErrNone;
       
  1402             }
       
  1403          
       
  1404        	CSpudBinderRef* ref = NULL;
       
  1405        	// Lower NIF for primary context has already been loaded by factory
       
  1406 		TRAPD(rc, ref = BindMan()->GetRefL(iPrimaryContextId));
       
  1407 		__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1408 		ASSERT(ref->IsBound());
       
  1409 		
       
  1410 		ASSERT(ref->State() == ESpudInactive);
       
  1411         ref->SetState(ESpudHaveQos);
       
  1412         	
       
  1413 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  1414 		// Store R5 QoS parameters
       
  1415 			RPacketQoS::TQoSR5Requested qos;
       
  1416 #else
       
  1417 		// Store QoS parameters
       
  1418 			RPacketQoS::TQoSR99_R4Requested qos;
       
  1419 #endif 
       
  1420 // SYMBIAN_NETWORKING_UMTSR5
       
  1421 		
       
  1422 		opt.iContextConfig.GetUMTSQoSReq(qos); 
       
  1423 		rc = iPdpFsmInterface.Set(iPrimaryContextId, qos);	
       
  1424 
       
  1425         if (rc != KErrNone)
       
  1426 			{
       
  1427 			__FLOG_1(_L("Setting default QoS on primary context failed with error [%d]. SPUD will shut down."), rc);
       
  1428 			SetTerminateError(iPrimaryContextId, rc); 
       
  1429 			
       
  1430 			SendPrimaryContextCreated(iPrimaryContextId, rc); // Notify GUQoS of error
       
  1431 			
       
  1432 			// At this point we know that SPUD is about to shut down, because we could not bring the 
       
  1433 	 		// primary context UP.
       
  1434 	
       
  1435 			//**********************************************************************************************
       
  1436 			// Tell GUQoS to stop bothering SPUD.
       
  1437 			// GUQoS returns the favour by turning off the NIF events within this very call.
       
  1438 	        // N.B.: "DEF055691 	GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack
       
  1439 	        // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event.
       
  1440 	        // As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only
       
  1441 	        // from the destructor. Once this defect is fixed, the following line must be uncommented: 
       
  1442 	        // SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached);
       
  1443 			//**********************************************************************************************
       
  1444 			
       
  1445 			__FLOG_1(_L("Setting default QoS on primary context failed: mark lower NIF binder for context[%d] for async deletion."), iPrimaryContextId);
       
  1446 			// We are about to delete the primary context NIF: this will notify Nifman that SPUD is finished.
       
  1447 			DisposeOfBinder(ref);
       
  1448 			}
       
  1449 			
       
  1450         return KErrNone;
       
  1451 		}
       
  1452 
       
  1453 	case KContextCreate:
       
  1454 		{
       
  1455         ASSERT(aOption.Ptr());
       
  1456 		TContextParameters& opt=*reinterpret_cast<TContextParameters*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1457 		ASSERT(opt.iContextType == ESecondaryContext);
       
  1458 
       
  1459 		TContextId id(KAllContexts);	// placeholder context ID
       
  1460 		CSpudBinderRef* ref = NULL;
       
  1461 		TRAPD(rc, ref = BindMan()->GetNewRefForSecondaryL(id););
       
  1462 		if(KErrNone != rc)
       
  1463 			{
       
  1464 			__FLOG_1(_L("Error %d creating a binder for the lower NIF"), rc);
       
  1465 			opt.iReasonCode = rc;  // The error code is the only argument we can pass to GUQoS, because there is no context.
       
  1466     		return KErrNone;
       
  1467     		}
       
  1468 
       
  1469 
       
  1470 		TRAP(rc, BindMan()->LoadNifL(iName, *ref);)
       
  1471 		if (rc != KErrNone)
       
  1472 			{
       
  1473 			__FLOG_1(_L("Error %d loading the lower NIF"), rc);
       
  1474 			FillInParameters(opt, id, rc);
       
  1475 			return KErrNone;
       
  1476 			}
       
  1477 
       
  1478 		ASSERT(ref->IsBound());
       
  1479         ref->SetState(ESpudStartingSecondary);
       
  1480 
       
  1481 
       
  1482 		// Reset the default QoS and TFT here. KContextQoSSet should arrive soon
       
  1483 		// with the proper values.
       
  1484 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  1485 			RPacketQoS::TQoSR5Requested qos;
       
  1486 #else
       
  1487 			RPacketQoS::TQoSR99_R4Requested qos;
       
  1488 #endif 
       
  1489 // SYMBIAN_NETWORKING_UMTSR5 
       
  1490 		rc = iPdpFsmInterface.Set(id, qos);
       
  1491 
       
  1492 		TTFTInfo tft;
       
  1493         rc = iPdpFsmInterface.Set(id, tft);
       
  1494 		
       
  1495 		// Pass in the new context ID to SpudFsm to use for the new context
       
  1496 
       
  1497 		// Notify SpudFsm
       
  1498 		__FLOG_1(_L("Sending SpudFsm event ECreateSecondaryPDPContext context %d"), id);
       
  1499 		rc = iPdpFsmInterface.Input(id, ECreateSecondaryPDPContext);
       
  1500 
       
  1501 		// Set up the synchronous response
       
  1502 		FillInParameters(opt, id, rc);
       
  1503     	return KErrNone;
       
  1504 		}
       
  1505 		
       
  1506 	case KContextDelete:
       
  1507 		{
       
  1508         ASSERT(aOption.Ptr());
       
  1509         TContextParameters& opt = *reinterpret_cast<TContextParameters*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1510        	CSpudBinderRef* ref = NULL;
       
  1511 		TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId));
       
  1512 		if (rc != KErrNone)
       
  1513 			{
       
  1514 			__FLOG_1(_L("Error: KContextDelete specifies context %d which does not exist"), opt.iContextInfo.iContextId);
       
  1515 			opt.iReasonCode = rc;  // The error code is the only argument we can pass to GUQoS, because there is no context.
       
  1516     		return KErrNone;
       
  1517 			}
       
  1518 		
       
  1519 		ASSERT(ref->IsBound());
       
  1520 		__FLOG_3(_L("KContextDelete context[%d] in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State());
       
  1521 
       
  1522 		switch (ref->State())
       
  1523 			{
       
  1524 		// NIF is up: need to stop the NIF first, then delete the binder.	
       
  1525 		case ESpudGettingNegQoS:
       
  1526 		case ESpudStartingSecondaryLowerNif: 
       
  1527 		// Assumption: GUQoS will never delete primary context.
       
  1528 		case ESpudUp:
       
  1529 		case ESpudFlowOff:
       
  1530 		case ESpudSuspended:
       
  1531 		case ESpudFlowOffAndSuspended:
       
  1532 	        ref->SetState(ESpudContextDelete);
       
  1533 	        
       
  1534 	        if(BindMan()->IsLastContext(opt.iContextInfo.iContextId)) // Are we about to shutdown after this?
       
  1535 	        	{
       
  1536 	           	SetTerminateError(KErrCancel); // KErrCancel is normally used to indicate "graceful" 
       
  1537 	        	}							   // user-initiated shutdown.
       
  1538 		   
       
  1539 	        // GUQoS ordered the shutdown: Network is still OK: initiate graceful shutdown of the lower NIF.
       
  1540 	        ref->NifLink()->Stop(KErrCancel, MNifIfNotify::EDisconnect);
       
  1541 	        break;
       
  1542 	    
       
  1543 	    case ESpudStartingSecondary:  // NIF not started: need to delete the context.
       
  1544 			ref->SetState(ESpudWaitLinkDown); 
       
  1545 
       
  1546 			// Delete context via SpudFsm
       
  1547 			__FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), opt.iContextInfo.iContextId);
       
  1548 			rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextDelete);
       
  1549 			ASSERT(rc == KErrNone);
       
  1550 			break;
       
  1551 
       
  1552 		case ESpudWaitLinkDown:
       
  1553 			// We're in the middle of deleting. Ignore this request.
       
  1554 			break;
       
  1555 
       
  1556 		case ESpudLinkDown:
       
  1557 			// We're in the middle of deleting, but we no longer need to notify
       
  1558 			// GUQoS when done.
       
  1559 			ref->SetState(ESpudWaitLinkDown);
       
  1560 			break;
       
  1561 	
       
  1562 		case ESpudWaitBinderDelete: // context deleted, NIF about to be deleted: ignore.
       
  1563 			break;
       
  1564 			
       
  1565 		default:
       
  1566 			__FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State());
       
  1567 	    	ASSERT(EFalse);
       
  1568 	    	break;
       
  1569 			}
       
  1570 
       
  1571 		FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1572         return KErrNone;
       
  1573 		}
       
  1574 		
       
  1575 	case KContextActivate:
       
  1576 		{
       
  1577         ASSERT(aOption.Ptr());
       
  1578 		TContextParameters& opt=*reinterpret_cast<TContextParameters*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1579        	CSpudBinderRef* ref = NULL;
       
  1580 		// Validate context ID
       
  1581 		TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId));
       
  1582 		if (KErrNone != rc)
       
  1583 			{
       
  1584 			opt.iReasonCode = rc; // Can supply error code only, as the context does not exist.
       
  1585 			__FLOG_1(_L("Error: KContextActivate specifies context %d which does not exist."), opt.iContextInfo.iContextId);
       
  1586 			return KErrNone;
       
  1587 			}
       
  1588 		
       
  1589 		if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete)
       
  1590 			{
       
  1591 			__FLOG_1(_L("Error: KContextActivate specifies context %d which is not bound to lower NIF."), opt.iContextInfo.iContextId);
       
  1592 			rc = KErrNotReady; // that's what the GuQoS docs say
       
  1593 			FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1594 			return KErrNone;
       
  1595 			}
       
  1596 			
       
  1597 		__FLOG_3(_L("KContextActivate context %d in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State());
       
  1598 
       
  1599         ASSERT(ref->State() == ESpudStartingSecondary || ref->State() == ESpudUp);
       
  1600 
       
  1601 
       
  1602 		// Notify SpudFsm
       
  1603 		__FLOG_1(_L("Sending SpudFsm event EContextActivate context %d"), opt.iContextInfo.iContextId);
       
  1604 		rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextActivate);
       
  1605 		// Set up the synchronous response
       
  1606 		FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1607         return KErrNone;
       
  1608 		}
       
  1609 
       
  1610 	case KContextQoSSet:
       
  1611 		{
       
  1612 		TContextParameters& opt=*reinterpret_cast<TContextParameters*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1613        	CSpudBinderRef* ref = NULL;
       
  1614 		// Validate context ID
       
  1615 		TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId));
       
  1616 		if (KErrNone != rc)
       
  1617 			{
       
  1618 			__FLOG_1(_L("Error: KContextQoSSet specifies context %d which does not exist"), opt.iContextInfo.iContextId);
       
  1619 			opt.iReasonCode = rc; // Can only supply error code, as the context does not exist.
       
  1620 			return KErrNone;
       
  1621 			}		
       
  1622 		
       
  1623 		if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete)
       
  1624 			{
       
  1625 			__FLOG_1(_L("Error: KContextQoSSet specifies context %d which is not bound to the lower NIF."), opt.iContextInfo.iContextId);
       
  1626 			rc = KErrNotReady; // that's what the GuQoS docs say
       
  1627 			FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1628 			return KErrNone;
       
  1629 			}
       
  1630 		__FLOG_3(_L("KContextQoSSet context %d in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State());
       
  1631 
       
  1632 		ASSERT(ref->State() == ESpudStartingSecondary
       
  1633             || ref->State() == ESpudUp
       
  1634             || ref->State() == ESpudFlowOff
       
  1635             || ref->State() == ESpudSuspended
       
  1636             || ref->State() == ESpudFlowOffAndSuspended
       
  1637             || ref->State() == ESpudLinkDown );
       
  1638 		
       
  1639 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  1640         RPacketQoS::TQoSR5Requested qos;
       
  1641 #else
       
  1642     RPacketQoS::TQoSR99_R4Requested qos;
       
  1643 #endif 
       
  1644 // SYMBIAN_NETWORKING_UMTSR5 
       
  1645 
       
  1646 		// Store QoS parameters
       
  1647         opt.iContextConfig.GetUMTSQoSReq(qos); 
       
  1648 		rc = iPdpFsmInterface.Set(opt.iContextInfo.iContextId, qos);
       
  1649 
       
  1650 		// Notify SpudFsm
       
  1651 		if (rc == KErrNone)
       
  1652 			{
       
  1653 			__FLOG_1(_L("Sending SpudFsm event EContextQoSSet context %d"), opt.iContextInfo.iContextId);
       
  1654 			rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextQoSSet);
       
  1655 			}
       
  1656 		FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1657         return KErrNone;
       
  1658 		}
       
  1659 
       
  1660 	case KContextTFTModify:
       
  1661 		{
       
  1662 		TContextParameters& opt=*reinterpret_cast<TContextParameters*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1663        	CSpudBinderRef* ref = NULL;
       
  1664 		// Validate context ID
       
  1665 		TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId));
       
  1666 		if (KErrNone != rc)
       
  1667 			{
       
  1668 			__FLOG_1(_L("Error: KContextTFTModify specifies context %d which does not exist"), opt.iContextInfo.iContextId);
       
  1669 			opt.iReasonCode = rc; // Can only supply error code as the context does not exist.
       
  1670 			return KErrNone;
       
  1671 			}
       
  1672 
       
  1673 		// keep local reference to Primary Context up to date
       
  1674 		if (opt.iContextType == EPrimaryContext) 
       
  1675 			{
       
  1676 			iPrimaryContextId = opt.iContextInfo.iContextId;
       
  1677 			}
       
  1678 			
       
  1679 		if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete)
       
  1680 			{
       
  1681 			__FLOG_1(_L("Error: KContextTFTModify specifies context %d which is not bound to the lower NIF."), opt.iContextInfo.iContextId);
       
  1682 			rc = KErrNotReady; // that's what the GuQoS docs say
       
  1683 			FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1684 			return KErrNone;
       
  1685 			}
       
  1686 		__FLOG_3(_L("KContextTFTModify context %d in state %S(%d)"), opt.iContextInfo.iContextId, SpudStateToText(ref->State()), ref->State());
       
  1687 
       
  1688 		ASSERT(ref->State() == ESpudStartingSecondary || 
       
  1689 			   ref->State() == ESpudUp ||
       
  1690 		       ref->State() == ESpudWaitLinkDown  ||
       
  1691 		       ref->State() == ESpudLinkDown ||
       
  1692 		       ref->State() == ESpudGettingNegQoS);
       
  1693 		// It is assumed that the TFT can be modified before the ctx reported activation 
       
  1694 
       
  1695 		// Store TFT parameters
       
  1696 		TTFTInfo tft;
       
  1697         opt.iContextConfig.GetTFTInfo(tft); 
       
  1698 
       
  1699         rc = iPdpFsmInterface.Set(opt.iContextInfo.iContextId, tft);
       
  1700 		if (rc != KErrNone)
       
  1701 			{
       
  1702 			__FLOG_1(_L("Error %d setting TFT"), rc);
       
  1703 			FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1704 			return KErrNone;
       
  1705 			}
       
  1706         rc = iPdpFsmInterface.Set(opt.iContextInfo.iContextId, opt.iTFTOperationCode);
       
  1707 		if (rc != KErrNone)
       
  1708 			{
       
  1709 			__FLOG_1(_L("Error %d setting TFT operation code"), rc);
       
  1710 			FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1711 			return KErrNone;
       
  1712 			}
       
  1713 
       
  1714 		// Notify SpudFsm
       
  1715 		__FLOG_1(_L("Sending SpudFsm event EContextTFTModify context %d"), opt.iContextInfo.iContextId);
       
  1716 		rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextTFTModify);
       
  1717 
       
  1718 		FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1719         return KErrNone;
       
  1720 		}
       
  1721 
       
  1722 	case KContextModifyActive:
       
  1723 		{
       
  1724 		TContextParameters& opt=*reinterpret_cast<TContextParameters*>(const_cast<TUint8*>(aOption.Ptr()));
       
  1725        	CSpudBinderRef* ref = NULL;
       
  1726 		// Validate context ID
       
  1727 		TRAPD(rc, ref = BindMan()->GetRefL(opt.iContextInfo.iContextId));
       
  1728 		if (KErrNone != rc)
       
  1729 			{
       
  1730 			__FLOG_1(_L("Error: KContextModifyActive specifies context %d which does not exist"), opt.iContextInfo.iContextId);
       
  1731 			opt.iReasonCode = rc;
       
  1732 			return KErrNone;
       
  1733 			}
       
  1734 			
       
  1735 		if(!ref->IsBound() || ref->State() == ESpudWaitBinderDelete)
       
  1736 			{
       
  1737 			__FLOG_1(_L("Error: KContextModifyActive specifies context %d which is not bound to the lower NIF."), opt.iContextInfo.iContextId);
       
  1738 			rc = KErrNotReady; // that's what the GuQoS docs say
       
  1739 			FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1740 			return KErrNone;
       
  1741 			}
       
  1742 
       
  1743 		// Notify SpudFsm
       
  1744 		__FLOG_1(_L("Sending SpudFsm event EContextModifyActive context %d"), opt.iContextInfo.iContextId);
       
  1745 		rc = iPdpFsmInterface.Input(opt.iContextInfo.iContextId, EContextModifyActive);
       
  1746 
       
  1747 		FillInParameters(opt, opt.iContextInfo.iContextId, rc);
       
  1748         return KErrNone;
       
  1749 		}
       
  1750 		
       
  1751 	case KInitialisePdpFsm:
       
  1752       {
       
  1753       MPdpFsmInterface* pdpFsm = *reinterpret_cast<MPdpFsmInterface**>(const_cast<TUint8*>(aOption.Ptr()));
       
  1754       iPdpFsmInterface.Init(pdpFsm);
       
  1755       return KErrNone;
       
  1756       }
       
  1757 
       
  1758 	default:
       
  1759 		__FLOG_1(_L("Unhandled event %d"), aName);
       
  1760 		break;
       
  1761 		}
       
  1762 	return KErrNotSupported;
       
  1763 	}
       
  1764 
       
  1765 /**
       
  1766 Receives link up indication from a lower NIF.
       
  1767 
       
  1768 @param aContextId PDP context ID of the associated lower NIF
       
  1769 */
       
  1770 void CSpudMan::LinkLayerUp(TContextId aContextId)
       
  1771 	{
       
  1772 	CSpudBinderRef* ref = NULL;
       
  1773 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1774 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1775 	ASSERT(ref->IsBound() && ref->State() != ESpudWaitBinderDelete);
       
  1776 	
       
  1777 	__FLOG_3(_L("Lower NIF LinkLayerUp on context[%d], in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1778 	switch (ref->State())
       
  1779 		{
       
  1780 	case ESpudStartingPrimaryLowerNif:
       
  1781 		{
       
  1782 	    ref->SetState(ESpudUp);
       
  1783 		if (AreQoSEventsEnabled())
       
  1784 			{
       
  1785 			SendPrimaryContextCreated(aContextId, KErrNone);
       
  1786 			}
       
  1787 		// If QoS is not yet enabled, SendPrimaryContextCreated() will be called when it is
       
  1788 
       
  1789 		Notify()->LinkLayerUp();
       
  1790 
       
  1791 		// If mobile IP is enabled, this progress notification should not be sent here.
       
  1792 		// This will need to be addressed if MIP is ever enabled for UMTS.
       
  1793 		Notify()->IfProgress(KLinkLayerOpen, KErrNone);
       
  1794 		}
       
  1795 		break;
       
  1796 
       
  1797 	case ESpudStartingSecondaryLowerNif:
       
  1798 		{
       
  1799 		// lower nif is up, now get the Negotiated QoS
       
  1800 	    ref->SetState(ESpudGettingNegQoS);
       
  1801 		
       
  1802 		TInt rc = iPdpFsmInterface.Input(aContextId, EGetNegQoS);
       
  1803 		ASSERT(rc == KErrNone);
       
  1804 		// Now wait for retrieval of negotiated QoS.
       
  1805 		// The following 2 functions will be fired from CSpudMan::HandleGetNegQoSEvent():
       
  1806 		//    FillInContextConfig(iTempContextConfig, aContextId);
       
  1807 		//    SendContextActivateEvent(aContextId, iTempContextConfig, KErrNone);
       
  1808 		}
       
  1809 		break;
       
  1810 		
       
  1811 	default:
       
  1812 		__FLOG_3(_L("Lower NIF LinkLayerUp on context[%d], in unexpected state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1813 		ASSERT(EFalse);
       
  1814 		}
       
  1815 	}
       
  1816 
       
  1817 /**
       
  1818 Receives link down indication from a lower NIF.
       
  1819 
       
  1820 @param aContextId Valid PDP context ID of the associated lower NIF
       
  1821 @param aReason A Symbian OS error code indicating the reason for the link closing down
       
  1822 @param aAction The action that should be taken as a result of link layer down being signalled
       
  1823 */
       
  1824 void CSpudMan::LinkLayerDown(TContextId aContextId, TInt aReason, MNifIfNotify::TAction aAction)
       
  1825 	{
       
  1826 	__FLOG_3(_L("CSpudMan::LinkLayerDown: context %d reason %d action %d"), aContextId, aReason, aAction);
       
  1827 
       
  1828 	if (aAction == MNifIfNotify::ENoAction)
       
  1829 		{
       
  1830 		// This call indicates a renegotiation of the lower link, not that the link has
       
  1831 		// actually gone down. This is of no interest to SPUD.
       
  1832 		__FLOG_0(_L("Ignoring MNifIfNotify::ENoAction"));
       
  1833 		return;
       
  1834 		}
       
  1835 
       
  1836 	CSpudBinderRef* ref = NULL;
       
  1837 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1838 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1839 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1840 
       
  1841 	
       
  1842 	TBool isUpperFlowOn = EFalse; // Can GUQoS attempt to send on this PDP context?
       
  1843 	
       
  1844 	switch (ref->State())
       
  1845 		{
       
  1846 	case ESpudUp:
       
  1847 		isUpperFlowOn = ETrue; // ESpudUp is the only state where GUQoS is allowed to send on us.
       
  1848 		// Fall through
       
  1849 	case ESpudFlowOff:// NIF & context were activated succcessfully.
       
  1850 	case ESpudSuspended:
       
  1851 	case ESpudFlowOffAndSuspended:
       
  1852 		ref->SetState(ESpudLinkDown); // Must Notify GUQoS that context is down.
       
  1853 		
       
  1854 		// Must inform upper layers they can no longer send on this context.
       
  1855 		if (isUpperFlowOn && AreQoSEventsEnabled()) 
       
  1856 			{
       
  1857 			// At this point the context status does not indicate to GUQoS that the context is about to go down.
       
  1858 			// Most likely, the status is EStatusActive, indicating that the context can handle requests.
       
  1859 			// Since the lower NIF is down, we are about to delete the context, so logically, this context
       
  1860 			// is EStatusDeactivating.(From spudman's PoV, a context is a union of lower NIF and ETel's RPacketContext)
       
  1861 			// GUQoS does not know this, it may try to issue requests,  
       
  1862 			// such as send packets on this context, modify TFT, modify QoS, etc.
       
  1863 			// Note: this does not seem to happen, but it is feasible.
       
  1864 			
       
  1865 			// N.B. Ideally, we should signal context change status in not just in EStateUp, but in 
       
  1866 			// EStateFlowOff etc, i.e. any state in which the context is alive. Unfortunately, GUQoS 
       
  1867 			// does not allow us to do this - there is no pure "ContextStatusChange" upcall on GUQoS.
       
  1868 			// Context Parameters Change upcall should not be used, because GUQoS interprets it as a
       
  1869 			// QoS parameters change, and sends QoSEventAdapt to the QoS framework. This is wrong.
       
  1870 			//
       
  1871 			// We could send ContextBlocked in FlowOff / Suspended states, however, this is problematic,
       
  1872 			// because GUQoS has already received one of these notifications. We could "trick" it and cycle
       
  1873 			// the state (send Flow On / Resume, then Flow Off / Suspend again), but this hackery should be
       
  1874 			// avoided unless absolutely necessary. So far, GUQoS does not seem to do anything beside sending
       
  1875 			// a packet on a deactivaing context, so we only worry about it.
       
  1876 			
       
  1877 			// N.B. SpudFSM is asynchronous, it will not issue a an actual deletion request on ETel until this RunL
       
  1878 			// returns. This means that the context status will not be updated to EStatusDeactiving in ETel 
       
  1879 			// until then, so when we fill in context paramters, the status is going to be EStatusActive.
       
  1880 			// We "sneak in" the correct status by overriding it. Doing it in SpudFSM would be wrong, because
       
  1881 			// SpudFSM reflects the ETel side of the context, so overriding the status there is misleading,
       
  1882 			// because it can be used internally by SpudFSM / SpudTel.
       
  1883 			
       
  1884 			__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."));
       
  1885 			iContextStatusOverride = RPacketContext::EStatusDeactivating; 
       
  1886 			SendContextBlockedEvent(aContextId); // resets the override
       
  1887 			isUpperFlowOn = EFalse; 
       
  1888 			}
       
  1889 		
       
  1890 		// The only way we can notify GUQoS once the context has been activated is
       
  1891 		// to delete it via the SpudFsm
       
  1892 		__FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), aContextId);
       
  1893 		rc = iPdpFsmInterface.Input(aContextId, EContextDelete);
       
  1894 		__FLOG_1(_L("SpudFsm::Input() returned status %d"), rc);
       
  1895 		if (rc == KErrNotReady) //This is becuase the FSM has been shut down via UMTSGPRSSCPR
       
  1896 			{
       
  1897 			HandleContextDeleteEvent(aContextId, aReason); //Just pretend that the fsm returned something sensible
       
  1898 			}
       
  1899 		ASSERT(rc == KErrNone || rc == KErrNotReady);
       
  1900 		break;
       
  1901 
       
  1902 	case ESpudGettingNegQoS: // CNifIfLink::Stop will handle this just as if the NIF was still being CNifIfLink::Start'ed.
       
  1903 	case ESpudStartingSecondaryLowerNif: // Attempt to bring up the lower NIF was made.
       
  1904 		ref->SetState(ESpudStartingSecondary); // GUQoS should delete us later. 
       
  1905 		// Notify GUQoS that Activation failed. It will take the control from here, most likely deleting the context.
       
  1906 		FillInContextConfig(iTempContextConfig, aContextId);
       
  1907 		if(ref->Error() != KErrNone)
       
  1908 			{
       
  1909 			SendContextActivateEvent(aContextId, iTempContextConfig, ref->Error());
       
  1910 			}
       
  1911 		else
       
  1912 			{
       
  1913 			SendContextActivateEvent(aContextId, iTempContextConfig, aReason);
       
  1914 			}
       
  1915 		break;
       
  1916 	
       
  1917 	case ESpudContextDelete:
       
  1918 		ref->SetState(ESpudWaitLinkDown); // GUQoS triggered us: don't need to notify it.
       
  1919 
       
  1920 		// Delete context via SpudFsm
       
  1921 		__FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), aContextId);
       
  1922 		rc = iPdpFsmInterface.Input(aContextId, EContextDelete);
       
  1923 		__FLOG_1(_L("SpudFsm::Input() returned status %d"), rc);
       
  1924 		ASSERT(rc == KErrNone);
       
  1925 		break;
       
  1926 		
       
  1927 	case ESpudStartingSecondary:
       
  1928 	case ESpudLinkDown: // Added for INC066156.
       
  1929 	case ESpudWaitLinkDown:
       
  1930 		// Link has finally gone down. Context is already deleted.
       
  1931     	__FLOG_1(_L("Lower NIF reported LinkLayerDown: mark the binder for context[%d] for async deletion"), aContextId);
       
  1932 		DisposeOfBinder(ref);
       
  1933 		break;
       
  1934 	
       
  1935 	case ESpudStartingPrimaryLowerNif:
       
  1936 		{
       
  1937 		SetTerminateError(aContextId, aReason); // SPUD is going to terminate.
       
  1938 		SetTerminateError(KErrCouldNotConnect);
       
  1939 		
       
  1940 		// The primary context is managed by SPUD. We delete it ourselves.
       
  1941 		__FLOG_1(_L("Sending SpudFsm event EContextDelete context %d"), aContextId);
       
  1942 		ref->SetState(ESpudWaitLinkDown);
       
  1943 		rc = iPdpFsmInterface.Input(aContextId, EContextDelete);
       
  1944 		__FLOG_1(_L("SpudFsm::Input() returned status %d"), rc);
       
  1945 		ASSERT(rc == KErrNone);
       
  1946 		
       
  1947 		// Meanwhile, notify GUQoS about the failed primary creation
       
  1948 		if (AreQoSEventsEnabled())
       
  1949 			{
       
  1950 			SendPrimaryContextCreated(aContextId, aReason);
       
  1951 			}
       
  1952 		break;
       
  1953 		}	
       
  1954 			
       
  1955 	default:
       
  1956 		__FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State());
       
  1957 		ASSERT(EFalse);
       
  1958 		break;
       
  1959 		}
       
  1960 	}
       
  1961 
       
  1962 /**
       
  1963 Receives flow off indication from a lower NIF.
       
  1964 
       
  1965 @param aContextId Valid PDP context ID of the associated lower NIF
       
  1966 */
       
  1967 void CSpudMan::StopSending(TContextId aContextId)
       
  1968 	{
       
  1969 	__FLOG_1(_L("CSpudMan::StopSending context %d"), aContextId);
       
  1970 	CSpudBinderRef* ref = NULL;
       
  1971 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  1972 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  1973 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  1974 	switch (ref->State())
       
  1975 		{
       
  1976 	case ESpudUp:
       
  1977 		ref->SetState(ESpudFlowOff);
       
  1978 		if (AreQoSEventsEnabled())
       
  1979 			{
       
  1980 			SendContextBlockedEvent(aContextId);
       
  1981 			}
       
  1982 		break;
       
  1983 
       
  1984 	case ESpudSuspended:
       
  1985 		ref->SetState(ESpudFlowOffAndSuspended);
       
  1986 		break;
       
  1987 
       
  1988 	case ESpudContextDelete:
       
  1989 	case ESpudWaitLinkDown:
       
  1990 	case ESpudLinkDown: //sometimes this leaks in
       
  1991 		// ignore
       
  1992 		break;	
       
  1993 	
       
  1994 	default:
       
  1995 		// error
       
  1996 		__FLOG_2(_L("Unexpected state %S(%d)"), SpudStateToText(ref->State()), ref->State());
       
  1997 		ASSERT(EFalse);
       
  1998 		break;
       
  1999 		}
       
  2000 	}
       
  2001 
       
  2002 /**
       
  2003 Receives flow on indication from a lower NIF.
       
  2004 
       
  2005 @param aContextId Valid PDP context ID of the associated lower NIF
       
  2006 */
       
  2007 void CSpudMan::StartSending(TContextId aContextId)
       
  2008 	{
       
  2009 	__FLOG_1(_L("CSpudMan::StartSending context %d"), aContextId);
       
  2010 	CSpudBinderRef* ref = NULL;
       
  2011 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  2012 	__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  2013 	__FLOG_3(_L("context %d is in state %S(%d)"), aContextId, SpudStateToText(ref->State()), ref->State());
       
  2014 	switch (ref->State())
       
  2015 		{
       
  2016 	case ESpudGettingNegQoS: // Lower NIF for the 2ndary ctx is up, waiting for negotiated QoS.
       
  2017 		break; // GUQoS, TCP/IP stack will be notified when negotiated QoS is retrieved. 
       
  2018 		// Notes: 
       
  2019 		// 1.there is a *potential* race condition where the negotiated QoS is retrived before lower NIF signals StartSending.
       
  2020 		// 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.
       
  2021 		// 2. Theoretically, the lower NIF may report LinkLayerUp (triggering retrieval of negotiated QoS), then signal 
       
  2022 		// StartSending much later (e.g.  a PPP implementation singalling LinkLayerUp from LCP, but StartSending from NCP).
       
  2023 		// SPUD CANNOT HANDLE THIS.
       
  2024 		// Existing Raw IP and PPP NIFs signal StartSending immediately after LinkLayerUp, so this has no consequences.
       
  2025 
       
  2026 	case ESpudUp:
       
  2027 		// This can happen for the initial StartSending after the lower NIF comes up
       
  2028 		// Treat it the same as ESpudFlowOff and fall through.
       
  2029 	case ESpudFlowOff:
       
  2030 		ref->SetState(ESpudUp);
       
  2031 
       
  2032 		// This must only be done AFTER the KPrimaryContextCreated event is sent (which in this state it is)
       
  2033 		// It's not clear if StartSending is needed/allowed in addition to the GUQoS event.
       
  2034 	    BindMan()->SpudProtocol()->DoStartSending();
       
  2035 
       
  2036 		if (AreQoSEventsEnabled())
       
  2037 			{
       
  2038 			SendContextUnblockedEvent(aContextId);
       
  2039 			}
       
  2040 		break;
       
  2041 
       
  2042 	case ESpudFlowOffAndSuspended:
       
  2043 		ref->SetState(ESpudSuspended);
       
  2044 		break;
       
  2045 
       
  2046 	case ESpudSuspended:
       
  2047 	case ESpudContextDelete:
       
  2048 	case ESpudWaitLinkDown:
       
  2049 		// ignore
       
  2050 		__FLOG_1(_L("Ignored StartSending on context %d (this should be OK)"), aContextId);
       
  2051 		break;	
       
  2052 	
       
  2053 	default:
       
  2054 		// We have encountered a serious problem. If we get StartSending before reaching the ESpudUp
       
  2055 		// state, we'll lose it and the upper networking protocol will never be notified.
       
  2056 		// As long as the lower NIF calls LinkLayerUp before StartSending, we'll be fine.
       
  2057 		__FLOG_1(_L("Can't send unblocked event now on context %d; this may cause problems"), aContextId);
       
  2058 		ASSERT(EFalse);
       
  2059 		break;
       
  2060 		}
       
  2061 	}
       
  2062 
       
  2063 
       
  2064 //*****************************************************************************
       
  2065 // Event senders to GUQoS
       
  2066 //*****************************************************************************
       
  2067 
       
  2068 /**
       
  2069 Sends event to GUQoS.
       
  2070 
       
  2071 @param aName event identifier
       
  2072 @param aOption TPckg<> event data
       
  2073 */
       
  2074 void CSpudMan::RaiseEvent(TUint aName, TDes8& aOption) const
       
  2075 	{
       
  2076 	__FLOG_2(_L("Sending event %S(%d) to GUQoS"), SpudFsmEventToText(aName), aName);
       
  2077 	iQosEventHandler->Event(reinterpret_cast<CProtocolBase*>(iBindMan->SpudMux()), aName, aOption); 
       
  2078 	}
       
  2079 
       
  2080 /**
       
  2081 Fills in common event parameters for the given context.
       
  2082 
       
  2083 @param aParams parameter structure
       
  2084 @param aContextId Valid PDP context ID
       
  2085 */
       
  2086 void CSpudMan::FillInParameters(TContextParameters& aParams, TContextId aContextId, TInt aError) const
       
  2087 	{
       
  2088    	CSpudBinderRef* ref = NULL;
       
  2089 	TRAPD(rc, ref = BindMan()->GetRefL(aContextId));
       
  2090 	ASSERT(rc == KErrNone);
       
  2091 	
       
  2092 	TContextType type(EContextTypeUnknown);
       
  2093 	if (rc == KErrNone)
       
  2094 		{
       
  2095 		switch (ref->State())
       
  2096 			{
       
  2097 		case ESpudHaveQos:
       
  2098 		case ESpudCreatingPrimary:
       
  2099 		case ESpudStartingPrimary:
       
  2100 			type = EPrimaryContext;
       
  2101 			break;
       
  2102 			
       
  2103 		case ESpudStartingSecondary:
       
  2104 			type = ESecondaryContext;
       
  2105 			break;
       
  2106 		
       
  2107 		default:
       
  2108 			type = (aContextId == iPrimaryContextId) ? EPrimaryContext : ESecondaryContext;;
       
  2109 			break;
       
  2110 			}
       
  2111 		}
       
  2112     aParams.iContextType = type; // Context type
       
  2113     aParams.iReasonCode = aError;  // Error code
       
  2114     //aParams.iContextInfo.iStatus = StateToStatus(*ref);
       
  2115     iPdpFsmInterface.Get(aContextId, aParams.iContextInfo.iStatus);
       
  2116     aParams.iContextInfo.iContextId = aContextId;
       
  2117 	}
       
  2118 
       
  2119 /**
       
  2120 Fill in context configuration parameter structure using SpudFsm's parameters.
       
  2121 
       
  2122 @param aConfig parameter structure
       
  2123 @param aContextId PDP context ID
       
  2124 */
       
  2125 void CSpudMan::FillInContextConfig(TContextConfig& aConfig, TContextId aContextId) const
       
  2126 	{
       
  2127 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  2128 		RPacketQoS::TQoSR5Negotiated qos;
       
  2129 #else
       
  2130 		RPacketQoS::TQoSR99_R4Negotiated qos;
       
  2131 #endif 
       
  2132 // SYMBIAN_NETWORKING_UMTSR5 
       
  2133 
       
  2134 	iPdpFsmInterface.Get(aContextId, qos);
       
  2135 	aConfig.SetUMTSQoSNeg(qos);
       
  2136 
       
  2137 	iPdpFsmInterface.Get(aContextId, iTempTftInfo);
       
  2138 	aConfig.SetTFTInfo(iTempTftInfo);
       
  2139 
       
  2140 	iPdpFsmInterface.Get(aContextId, iTempGprsContext);
       
  2141 	aConfig.SetContextConfig(iTempGprsContext);
       
  2142 	}
       
  2143 
       
  2144 /**
       
  2145 Sends KPrimaryContextCreated event to GUQoS.
       
  2146 */
       
  2147 void CSpudMan::SendPrimaryContextCreated(TContextId aContextId, TInt aError)
       
  2148 	{
       
  2149 	__FLOG_2(_L("SendPrimaryContextCreated context %d error %d"), aContextId, aError);
       
  2150 
       
  2151 	if (!iQosEventsEnabled)
       
  2152 		{
       
  2153 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2154 		return;
       
  2155 		}
       
  2156 	// We make this assumption in various places
       
  2157 	ASSERT(aContextId == 0);
       
  2158 
       
  2159 	TContextParameters primaryContextCreatedEvent;
       
  2160 	FillInParameters(primaryContextCreatedEvent, aContextId, aError);
       
  2161 	TPckg<TContextParameters> event(primaryContextCreatedEvent);
       
  2162 	RaiseEvent(KPrimaryContextCreated, event);
       
  2163 	}
       
  2164 
       
  2165 
       
  2166 /**
       
  2167 Sends KSecondaryContextCreated event to GUQoS.
       
  2168 
       
  2169 @param aContextId Context ID
       
  2170 @param aError error code
       
  2171 */
       
  2172 void CSpudMan::SendSecondaryContextCreated(TContextId aContextId, TInt aError)
       
  2173 	{
       
  2174 	__FLOG_2(_L("SendSecondaryContextCreated context %d error %d"), aContextId, aError);
       
  2175 
       
  2176 	if (!iQosEventsEnabled)
       
  2177 		{
       
  2178 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2179 		return;
       
  2180 		}
       
  2181 
       
  2182 	// We make this assumption in various places
       
  2183 	ASSERT(aContextId != 0);
       
  2184 	
       
  2185 	TContextParameters event;
       
  2186 	FillInParameters(event, aContextId, aError);
       
  2187 	TPckg<TContextParameters> eventPckg(event);
       
  2188 	RaiseEvent(KSecondaryContextCreated, eventPckg);
       
  2189 	}
       
  2190 
       
  2191 
       
  2192 /**
       
  2193 Sends KContextBlockedEvent event to GUQoS.
       
  2194 */
       
  2195 void CSpudMan::SendContextBlockedEvent(TContextId aContextId)
       
  2196 	{
       
  2197 	__FLOG_2(_L("SendContextBlockedEvent context %d error %d"), aContextId, KErrNone);
       
  2198 	
       
  2199 	if (!iQosEventsEnabled)
       
  2200 		{
       
  2201 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2202 		return;
       
  2203 		}
       
  2204 
       
  2205 	TContextParameters event;
       
  2206 	FillInParameters(event, aContextId);
       
  2207 	
       
  2208 	/** The status we want to signal to GUQoS may be different from the context status we get from SpudFSM
       
  2209 	E.g., if we are about to deactivate the context, the logical status of the context is EStatusDeactivating, rather than
       
  2210 	EStatusActive, even though that's what SpudFSM will tell us */
       
  2211 	if(RPacketContext::EStatusUnknown != iContextStatusOverride)
       
  2212 		{
       
  2213 		__FLOG_2(_L("SendContextBlockedEvent: context status overriden to %d, original: %d."), 
       
  2214 			iContextStatusOverride, event.iContextInfo.iStatus);
       
  2215 			
       
  2216 		event.iContextInfo.iStatus = iContextStatusOverride;			
       
  2217 		iContextStatusOverride = RPacketContext::EStatusUnknown; 
       
  2218 		}
       
  2219 	
       
  2220 	TPckg<TContextParameters> eventPckg(event);
       
  2221 	RaiseEvent(KContextBlockedEvent, eventPckg);
       
  2222 	}
       
  2223 
       
  2224 /**
       
  2225 Sends KContextUnblockedEvent event to GUQoS.
       
  2226 */
       
  2227 void CSpudMan::SendContextUnblockedEvent(TContextId aContextId)
       
  2228 	{
       
  2229 	__FLOG_2(_L("SendContextUnblockedEvent context %d error %d"), aContextId, KErrNone);
       
  2230 
       
  2231 	if (!iQosEventsEnabled)
       
  2232 		{
       
  2233 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2234 		return;
       
  2235 		}
       
  2236 	
       
  2237 	TContextParameters event;
       
  2238 	FillInParameters(event, aContextId);
       
  2239 	TPckg<TContextParameters> eventPckg(event);
       
  2240 	RaiseEvent(KContextUnblockedEvent, eventPckg);
       
  2241 	}
       
  2242 
       
  2243 /**
       
  2244 Sends KContextQoSSetEvent event to GUQoS.
       
  2245 
       
  2246 @param aContextId Context ID
       
  2247 @param aError error code
       
  2248 */
       
  2249 void CSpudMan::SendContextQoSSetEvent(TContextId aContextId, TInt aError)
       
  2250 	{
       
  2251 	__FLOG_2(_L("SendContextQoSSetEvent context %d error %d"), aContextId, aError);
       
  2252 
       
  2253 	if (!iQosEventsEnabled)
       
  2254 		{
       
  2255 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2256 		return;
       
  2257 		}
       
  2258 	
       
  2259 	TContextParameters event;
       
  2260 	FillInParameters(event, aContextId, aError);
       
  2261 	TPckg<TContextParameters> eventPckg(event);
       
  2262 	RaiseEvent(KContextQoSSetEvent, eventPckg);
       
  2263 	}
       
  2264 
       
  2265 /**
       
  2266 Sends KContextTFTModifiedEvent event to GUQoS.
       
  2267 
       
  2268 @param aContextId Context ID
       
  2269 #param aTFTOperationCode TFT operation code
       
  2270 @param aError error code
       
  2271 */
       
  2272 void CSpudMan::SendContextTFTModifiedEvent(TContextId aContextId, TTFTOperationCode aTFTOperationCode, TInt aError)
       
  2273 	{
       
  2274 	__FLOG_2(_L("SendContextTFTModifiedEvent context %d error %d"), aContextId, aError);
       
  2275 
       
  2276 	if (!iQosEventsEnabled)
       
  2277 		{
       
  2278 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2279 		return;
       
  2280 		}
       
  2281 	
       
  2282 	TContextParameters event;
       
  2283 	FillInParameters(event, aContextId, aError);
       
  2284 	// Also need to fill in TTFTOperationCode, an undocumented requirement
       
  2285 	event.iTFTOperationCode = aTFTOperationCode;
       
  2286 	TPckg<TContextParameters> eventPckg(event);
       
  2287 	RaiseEvent(KContextTFTModifiedEvent, eventPckg);
       
  2288 	}
       
  2289 
       
  2290 /**
       
  2291 Sends KContextModifyActiveEvent event to GUQoS.
       
  2292 
       
  2293 @param aContextId Context ID
       
  2294 @param aContextConfig Configuration parameters for this context
       
  2295 @param aError error code
       
  2296 */
       
  2297 void CSpudMan::SendContextModifyActiveEvent(TContextId aContextId, TContextConfig& aContextConfig, TInt aError)
       
  2298 	{
       
  2299 	__FLOG_2(_L("SendContextModifyActiveEvent context %d error %d"), aContextId, aError);
       
  2300 
       
  2301 	if (!iQosEventsEnabled)
       
  2302 		{
       
  2303 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2304 		return;
       
  2305 		}
       
  2306 	
       
  2307 	TContextParameters event;
       
  2308 	FillInParameters(event, aContextId, aError);
       
  2309 	event.iContextConfig = aContextConfig;
       
  2310 	TPckg<TContextParameters> eventPckg(event);
       
  2311 	RaiseEvent(KContextModifyActiveEvent, eventPckg);
       
  2312 	}
       
  2313 
       
  2314 /**
       
  2315 Sends KContextActivateEvent event to GUQoS.
       
  2316 
       
  2317 @param aContextId Context ID
       
  2318 @param aContextConfig Configuration parameters for this context
       
  2319 @param aError error code
       
  2320 */
       
  2321 void CSpudMan::SendContextActivateEvent(TContextId aContextId, TContextConfig& aContextConfig, TInt aError)
       
  2322 	{
       
  2323 	__FLOG_2(_L("SendContextActivateEvent context %d error %d"), aContextId, aError);
       
  2324 
       
  2325 	if (!iQosEventsEnabled)
       
  2326 		{
       
  2327 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2328 		return;
       
  2329 		}
       
  2330 	
       
  2331 	TContextParameters event;
       
  2332 	FillInParameters(event, aContextId, aError);
       
  2333 	event.iContextConfig = aContextConfig;
       
  2334 	TPckg<TContextParameters> eventPckg(event);
       
  2335 	RaiseEvent(KContextActivateEvent, eventPckg);
       
  2336 	}
       
  2337 
       
  2338 /**
       
  2339 Sends KContextParametersChangeEvent event to GUQoS.
       
  2340 
       
  2341 @param aContextId Context ID
       
  2342 @param aContextConfig Configuration parameters for this context
       
  2343 @param aError error code
       
  2344 */
       
  2345 void CSpudMan::SendContextParametersChangeEvent(TContextId aContextId, TContextConfig& aContextConfig, TInt aError)
       
  2346 	{
       
  2347 	__FLOG_2(_L("SendContextParametersChangeEvent context %d error %d"), aContextId, aError);
       
  2348 
       
  2349 	if (!iQosEventsEnabled)
       
  2350 		{
       
  2351 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2352 		return;
       
  2353 		}
       
  2354 	
       
  2355 	TContextParameters event;
       
  2356 	FillInParameters(event, aContextId, aError);
       
  2357 	event.iContextConfig = aContextConfig;
       
  2358 	TPckg<TContextParameters> eventPckg(event);
       
  2359 	RaiseEvent(KContextParametersChangeEvent, eventPckg);
       
  2360 	}
       
  2361 
       
  2362 /**
       
  2363 Sends KContextDeleteEvent event to GUQoS.
       
  2364 
       
  2365 @param aContextId Context ID
       
  2366 */
       
  2367 void CSpudMan::SendContextDeleteEvent(TContextId aContextId)
       
  2368 	{
       
  2369 	__FLOG_2(_L("SendContextDeleteEvent context %d error %d"), aContextId, KErrNone);
       
  2370 
       
  2371 	if (!iQosEventsEnabled)
       
  2372 		{
       
  2373 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2374 		return;
       
  2375 		}
       
  2376 	
       
  2377 	TContextParameters event;
       
  2378 	FillInParameters(event, aContextId);
       
  2379 	TPckg<TContextParameters> eventPckg(event);
       
  2380 	RaiseEvent(KContextDeleteEvent, eventPckg);
       
  2381 	}
       
  2382 
       
  2383 /**
       
  2384 Sends KNetworkStatusEvent event to GUQoS.
       
  2385 
       
  2386 @param aEventCode Event code
       
  2387 @param aStatus Network status
       
  2388 */
       
  2389 void CSpudMan::SendNetworkStatusEvent(TNetworkEventCode aEventCode, RPacketService::TStatus aStatus)
       
  2390 	{
       
  2391 	__FLOG_2(_L("SendNetworkStatusEvent event code %d status %d"), aEventCode, aStatus);
       
  2392 
       
  2393 	if (!iQosEventsEnabled) // QoS events not turned on yet, or have been turned off by GUQoS
       
  2394 		{
       
  2395 		__FLOG_0(_L("Error: sending events is disabled - GuQoS not present ?"));
       
  2396 		return;
       
  2397 		}
       
  2398 	
       
  2399 	TNetworkParameters event;
       
  2400 	event.iNetworkEventCode = aEventCode;
       
  2401 	event.iNetworkStatus = aStatus;
       
  2402 	TPckg<TNetworkParameters> eventPckg(event);
       
  2403 	RaiseEvent(KNetworkStatusEvent, eventPckg);
       
  2404 	}
       
  2405 
       
  2406 
       
  2407 //*****************************************************************************
       
  2408 // CNifIfLink methods
       
  2409 //*****************************************************************************
       
  2410 
       
  2411 
       
  2412 /**
       
  2413 Return the link protocol handler object.
       
  2414 
       
  2415 @param aName Protocol name desired
       
  2416 @return Pointer to link protocol handler (ownership is transferred)
       
  2417 */
       
  2418 CNifIfBase* CSpudMan::GetBinderL(const TDesC& aName)
       
  2419 	{
       
  2420     __FLOG_1(_L("CSpudMan::GetBinderL %S"), &aName);
       
  2421     iName = aName;
       
  2422 	return static_cast<CNifIfBase*>(iBindMan->TransferSpudMux());
       
  2423 	}
       
  2424 
       
  2425 /**
       
  2426 Return information about the SPUD NIF.
       
  2427 
       
  2428 @param aInfo Receives the NIF interface info
       
  2429 */
       
  2430 void CSpudMan::Info(TNifIfInfo& aInfo) const
       
  2431 	{
       
  2432 	CSpudBinderRef* ref = NULL;
       
  2433 	// Get the binder for the first (default) lower NIF.
       
  2434 	TRAPD(err, ref = iBindMan->GetAnyRefL());
       
  2435 	if (err == KErrNone)
       
  2436 		{
       
  2437 		// Read the protocol supported value from the lower NIF
       
  2438 		ref->NifLink()->Info(aInfo);
       
  2439 		ASSERT(aInfo.iFlags == (KNifIfIsBase | KNifIfUsesNotify | KNifIfIsLink | KNifIfCreatedByFactory | KNifIfCreatesBinder));
       
  2440 		}
       
  2441 	else
       
  2442 		{
       
  2443 		aInfo.iProtocolSupported=KProtocolUnknown;
       
  2444 		}
       
  2445 	
       
  2446 	aInfo.iVersion = TVersion(KSpudMajorVersionNumber, KSpudMinorVersionNumber, KSpudBuildVersionNumber);
       
  2447 	aInfo.iFlags = KNifIfIsBase | 
       
  2448                    KNifIfUsesNotify | 
       
  2449                    KNifIfIsLink | 
       
  2450                    KNifIfCreatedByFactory | 
       
  2451                    KNifIfCreatesBinder;
       
  2452 	aInfo.iName = KSpudName;
       
  2453 	}
       
  2454 
       
  2455 /**
       
  2456 Processes notifications from Agent
       
  2457 
       
  2458 @param aEvent Event type
       
  2459 @param aInfo Data relating to event
       
  2460 
       
  2461 @return Error code
       
  2462 */
       
  2463 TInt CSpudMan::Notification(TAgentToNifEventType aEvent, void * aInfo)
       
  2464 	{
       
  2465 	__FLOG_1(_L("CSpudMan::Notification event %d"), aEvent);
       
  2466 	TInt rc = KErrNotSupported;
       
  2467 	switch (aEvent)
       
  2468 		{
       
  2469 	case EAgentToNifEventTypeModifyInitialTimer:
       
  2470 	case EAgentToNifEventTypeDisableTimers:
       
  2471 	case EAgentToNifEventTypeEnableTimers:
       
  2472 	case EAgentToNifEventTsyConfig:
       
  2473 	case EAgentToNifEventTsyConnectionSpeed:
       
  2474 		// Send notification to all lower NIFs
       
  2475 		rc = KErrNotReady;
       
  2476 		TContextId i;
       
  2477 		for (i=0; i < KMaxPdpContexts; ++i)
       
  2478 			{
       
  2479 			CSpudBinderRef* ref = NULL;
       
  2480 			TRAP(rc, ref = iBindMan->GetRefL(i));
       
  2481 			if (rc == KErrNone)
       
  2482 				{
       
  2483 				rc = ref->NifLink()->Notification(aEvent, aInfo);
       
  2484 				}
       
  2485 			}
       
  2486 		break;
       
  2487 
       
  2488 	case EAgentToNifEventTypeGetDataTransfer:
       
  2489 		{
       
  2490 		TPckg<RPacketContext::TDataVolume>* totalDataPackage = (TPckg<RPacketContext::TDataVolume>*) aInfo;
       
  2491 		RPacketContext::TDataVolume& totalData = (*totalDataPackage)();
       
  2492 		totalData.iBytesSent = 0;
       
  2493 		totalData.iOverflowCounterSent = 0;
       
  2494 		totalData.iBytesReceived = 0;
       
  2495 		totalData.iOverflowCounterReceived = 0;
       
  2496 
       
  2497 		RPacketContext::TDataVolume data;
       
  2498 		TPckg<RPacketContext::TDataVolume> dataPackage(data);
       
  2499 
       
  2500 		// Add up data reported by all NIFs
       
  2501 		rc = KErrNotReady;
       
  2502 		TContextId i;
       
  2503 		for (i=0; i < KMaxPdpContexts; ++i)
       
  2504 			{
       
  2505 			CSpudBinderRef* ref = NULL;
       
  2506 			TRAP(rc, ref = iBindMan->GetRefL(i));
       
  2507 			if (rc == KErrNone)
       
  2508 				{
       
  2509 				rc = ref->NifLink()->Notification(aEvent, &dataPackage);
       
  2510 				if (rc == KErrNone)
       
  2511 					{
       
  2512 					totalData.iBytesSent += data.iBytesSent;
       
  2513 					totalData.iOverflowCounterSent += data.iOverflowCounterSent;
       
  2514 					totalData.iBytesReceived += data.iBytesReceived;
       
  2515 					totalData.iOverflowCounterReceived += data.iOverflowCounterReceived;
       
  2516 					}
       
  2517 				}
       
  2518 			}
       
  2519 		break;
       
  2520 		}
       
  2521 
       
  2522 	case EAgentToNifEventTypeDisableConnection:
       
  2523 		// TODO: what to do with this?
       
  2524 	default:
       
  2525 		__FLOG_1(_L("Notification event %d was ignored"), aEvent);
       
  2526 		break;
       
  2527 		}
       
  2528 
       
  2529 	return rc;
       
  2530 	}
       
  2531 
       
  2532 
       
  2533 /**
       
  2534 Start the link.
       
  2535 At this point only the primary PDP context is valid.
       
  2536 
       
  2537 @return Error code
       
  2538 */
       
  2539 TInt CSpudMan::Start()
       
  2540 	{
       
  2541 	__FLOG_1(_L("CSpudMan::Start(0x%x)"), this);
       
  2542 
       
  2543 	// SpudTel needs TSY name from CommDb
       
  2544 	TName tsyName;
       
  2545 	ReadTsyName(tsyName);
       
  2546 	
       
  2547 	// Initialise SpudFsm
       
  2548 	TRAPD(err, InitPdpFsmInterfaceL());
       
  2549 	if (err != KErrNone)
       
  2550 	  {
       
  2551 	  __FLOG_1(_L("CSpudMan::Start: Failed to initialise the PDP Fsm Interface,Error = %d"),err);
       
  2552 	  return err;
       
  2553      }
       
  2554 
       
  2555 	// Open SpudFsm
       
  2556 	TRAP(err, iPdpFsmInterface.OpenL(this, tsyName));
       
  2557 	if (err != KErrNone)
       
  2558 	  {
       
  2559 	  __FLOG_1(_L("CSpudMan::Start: Failed to open the PDP Fsm Interface,Error = %d"),err);
       
  2560 	  return err;
       
  2561      }
       
  2562 
       
  2563 
       
  2564 	// re-initialise the temporary data structure before retrieving 
       
  2565 	// GPRS config parameters from CommDB
       
  2566    __FLOG_0(_L("CSpudMan::Start: Getting default GPRS settings from Commdb"));
       
  2567 	RetrieveGprsConfig(iTempGprsContext);
       
  2568 	
       
  2569 	TRAP(err, SetupSipServerAddrRetrievalL(iTempGprsContext.iProtocolConfigOption););
       
  2570 	
       
  2571 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  2572 	// Add the IMCN Signalling Status flag. IM CN status flag is retrieved from the Database
       
  2573 	// Request For the status of IM CN dedicated signalling context
       
  2574 	TRAP(err,SetIMCNSignallingFlagPcoL(iTempGprsContext.iProtocolConfigOption));
       
  2575 	
       
  2576 	// Not sure what can be done after trapping the error, because its not an error condition for starting of 
       
  2577 	// Primary PDP context.
       
  2578 #ifdef __FLOG_ACTIVE
       
  2579 	if(err != KErrNone)
       
  2580 		{
       
  2581 		__FLOG_1(_L("CSpudMan::Start: Failed to set IM CN signalling Flag.Error = %d"),err);
       
  2582 		}
       
  2583 #endif
       
  2584 #endif // SYMBIAN_NETWORKING_UMTSR5
       
  2585 	
       
  2586 	iPdpFsmInterface.Set(iPrimaryContextId, iTempGprsContext);
       
  2587 	if (err != KErrNone)
       
  2588         {
       
  2589         __FLOG_1(_L("CSpudMan::Start: Setup sip server address retrieval. Failed with %d"),err);
       
  2590         return err;
       
  2591         }
       
  2592         
       
  2593 	if (iParkedDefaultQoS != NULL) 
       
  2594         {
       
  2595         __FLOG_0(_L("CSpudMan::Start: Found parked QoS settings from GuQoS"));
       
  2596         
       
  2597         TPtr8 qos(iParkedDefaultQoS->Des());
       
  2598         GuqosInput (KNifSetDefaultQoS, qos);
       
  2599         
       
  2600         delete iParkedDefaultQoS;
       
  2601         iParkedDefaultQoS = NULL;
       
  2602         }
       
  2603 
       
  2604 	CSpudBinderRef* ref = NULL;
       
  2605 	// Get the binder for the first (default) lower NIF.
       
  2606 	TRAP(err, ref = iBindMan->GetRefL(iPrimaryContextId));
       
  2607 	if (err != KErrNone)
       
  2608 		{
       
  2609 		__FLOG_0(_L("CSpudMan::Start: Error - no context could be found"));
       
  2610 		return err;
       
  2611 		}
       
  2612 
       
  2613     ASSERT(ref->State() == ESpudInactive || ref->State() == ESpudHaveQos);
       
  2614     ASSERT(ref->State() != ESpudWaitBinderDelete);
       
  2615     
       
  2616     if (ref->State() == ESpudWaitBinderDelete)
       
  2617     	{
       
  2618 	    return KErrNotReady;
       
  2619     	}
       
  2620     
       
  2621 	if (ref->State() != ESpudHaveQos)
       
  2622 		{
       
  2623 		__FLOG_0(_L("CSpudMan::Start: No QoS parameters have been set - is GuQoS present?"));
       
  2624 	
       
  2625 		// Sets default QoS parameters because either
       
  2626       //    1) they weren't supplied by GUQoS - this shouldn't happen
       
  2627       //    2) or GuQoS has been configured out
       
  2628 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  2629 		// Sets default R5 QoS parameters because they weren't supplied by GUQoS.
       
  2630 			RPacketQoS::TQoSR5Requested qos;
       
  2631 			ReadDefaultR5QoS(qos);
       
  2632 #else
       
  2633 			RPacketQoS::TQoSR99_R4Requested qos;
       
  2634 			ReadDefaultQoS(qos);
       
  2635 #endif 
       
  2636 // SYMBIAN_NETWORKING_UMTSR5 		
       
  2637 			iPdpFsmInterface.Set(iPrimaryContextId, qos); // ignore any error
       
  2638 		
       
  2639 		}
       
  2640 
       
  2641 	// Set default TFT
       
  2642 	TTFTInfo tft;
       
  2643     iPdpFsmInterface.Set(iPrimaryContextId, tft); // ignore any error
       
  2644     
       
  2645 
       
  2646 	// Have Etel create a context
       
  2647 	ref->SetState(ESpudCreatingPrimary);
       
  2648 	__FLOG_1(_L("CSpudMan::Start: Sending SpudFsm event ECreatePrimaryPDPContext context %d"), iPrimaryContextId);
       
  2649 	TInt rc = iPdpFsmInterface.Input(iPrimaryContextId, ECreatePrimaryPDPContext);
       
  2650 	// TODO: handle errors properly
       
  2651 	ASSERT(rc == KErrNone);
       
  2652 	rc = rc; // Eliminate compiler warning in release builds
       
  2653 
       
  2654 	return KErrNone;
       
  2655     }
       
  2656 
       
  2657 /**
       
  2658 Cleanly stop the link.
       
  2659 
       
  2660 @param aReason The reason the link is going down
       
  2661 @param aAction The action to take once the link is down
       
  2662 */
       
  2663 void CSpudMan::Stop(TInt aReason, MNifIfNotify::TAction aAction)
       
  2664 	{
       
  2665 	__FLOG_3(_L("CSpudMan::Stop: reason %d action %d. %d contexts exist."), aReason, aAction, BindMan()->NumContexts());
       
  2666 	ASSERT(BindMan()->NumContexts()); // Primary PDP context is created in the factory.
       
  2667 	
       
  2668 	SetTerminateError(aReason); // Store this error code for use when the SPUD goes down
       
  2669 	if (AreQoSEventsEnabled())
       
  2670 		{
       
  2671 		// Spud was administratively stopped. It can be some time before SPUD signals LinkLayerDown.
       
  2672 		// In the meanwhile, we can receive requests from GUQoS that can interfere with the shutdown.
       
  2673 		// To prevent this, we tell GUQoS to stop bothering SPUD.
       
  2674 		// GUQoS returns the favour by turning off the NIF events within this very call.
       
  2675 		// This means we will not send KNetworkInterfaceDown again, even though we'll try.
       
  2676 		// *********************************************************************************************
       
  2677 		// N.B.: "DEF055691 	GUQoS crashes at shutdown": This defect results in GUQoS crash if the stack
       
  2678 	    // closes flows after the NIF proxy was deleted by GUQoS, as a result of KNetworkInterfaceDown event.
       
  2679 	    // As a temporary workaround, this call is disabled, and KNetworkInterfaceDown event is signalled only
       
  2680 	    // from the destructor. Once this defect is fixed, the following line must be uncommented: 
       
  2681 	    // SendNetworkStatusEvent(KNetworkInterfaceDown, RPacketService::EStatusUnattached);
       
  2682 		//**********************************************************************************************
       
  2683 		}
       
  2684 		
       
  2685 	
       
  2686 	// Send Stop to all lower NIFs that were started but not stopped yet
       
  2687 	TContextId i;
       
  2688 	for (i=0; i < KMaxPdpContexts; ++i)
       
  2689 		{
       
  2690 		StopContext(i, aReason, aAction);
       
  2691 		}		
       
  2692 	// Eventually, the last lower NIF will call LinkLayerDown to trigger the final cleanup
       
  2693     }
       
  2694 
       
  2695 /**
       
  2696 Cleanly stop a context.
       
  2697 
       
  2698 @param aReason The reason the link is going down
       
  2699 @param aAction The action to take once the link is down
       
  2700 @param aContextId context
       
  2701 */
       
  2702 void CSpudMan::StopContext(TContextId aContextId, TInt aReason, MNifIfNotify::TAction aAction)
       
  2703 	{
       
  2704 	CSpudBinderRef* ref = NULL;
       
  2705 	TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  2706 	if (rc == KErrNone && // Binder exists
       
  2707 		ref->IsBound()) // Is bound to a lower NIF.
       
  2708 		{
       
  2709 		
       
  2710 		// Save the Context failure reason
       
  2711         if (ref->Error() == KErrNone) 
       
  2712         	{
       
  2713         	ref->SetError(aReason);
       
  2714 			}
       
  2715 
       
  2716 		switch(ref->State()) // NIFs in some states are not eligible for Stop.
       
  2717 			{
       
  2718 			// Context created and NIF started.
       
  2719 			case ESpudStartingPrimaryLowerNif: // Waiting for LinkLayerUp/Down
       
  2720 			case ESpudStartingSecondaryLowerNif:// Waiting for LinkLayerUp/Down
       
  2721 			case ESpudGettingNegQoS: // Waiting for retrieval of negotiated QoS, context activated
       
  2722 			case ESpudUp: // LinkLayerUp received, NIF is up.
       
  2723 			case ESpudFlowOff: // LinkLayerUp received, NIF is up.
       
  2724 			case ESpudSuspended: // LinkLayerUp received, NIF is up.
       
  2725 			case ESpudFlowOffAndSuspended: // LinkLayerUp received, NIF is up.
       
  2726 				__FLOG_2(_L("Lower NIF binder for context[%d] is in state[%S]: Stopping lower NIF."),aContextId,SpudStateToText(ref->State()));
       
  2727 				// Stop the NIF and delete the context via SpudFsm: 
       
  2728 				ref->NifLink()->Stop(aReason, aAction);
       
  2729 				// stay in the Up state so that that GUQoS is notified.
       
  2730 				break;
       
  2731 				
       
  2732 			// Context is being created
       
  2733 			case ESpudCreatingPrimary:
       
  2734 				// SpudFsm will clean up the context and generate a context created event with an error
       
  2735 				rc = iPdpFsmInterface.Input(aContextId, ECancelContextCreate);
       
  2736 				break;
       
  2737 				
       
  2738 			// Context created, but NIF not started
       
  2739 			case ESpudStartingPrimary: 
       
  2740 				ref->SetState(ESpudWaitLinkDown);
       
  2741 				// Any outstanding  SpudFsm request will be cancelled by this delete request.
       
  2742 				rc = iPdpFsmInterface.Input(aContextId, EContextDelete);
       
  2743 				aReason = (KErrNone != aReason) ? aReason : KErrCancel; // Must not be KErrNone.
       
  2744 				SendPrimaryContextCreated(aContextId, aReason);
       
  2745 				break;
       
  2746 				
       
  2747 			case ESpudStartingSecondary: 	
       
  2748 				// Delete the context via SpudFsm
       
  2749 				ref->SetState(ESpudLinkDown); // We'll notify GUQoS from deletion event handler.
       
  2750 				__FLOG_1(_L("Context[%d] created: Sending SpudFsm event EContextDelete"), aContextId);
       
  2751 					
       
  2752 				// Any outstanding  SpudFsm request will be cancelled by this delete request.
       
  2753 				rc = iPdpFsmInterface.Input(aContextId, EContextDelete);
       
  2754 				ASSERT(rc == KErrNone);
       
  2755 				break;
       
  2756 				
       
  2757 			// Can't call Stop: the NIF either not started, or stopped already
       
  2758 			case ESpudContextDelete: // Context deleted by GUQoS, Stop was called.
       
  2759 			case ESpudWaitLinkDown: // Stop was called, waiting for LinkLayerDown
       
  2760 			case ESpudWaitBinderDelete: // LinkLayerDown received, queued for deletion
       
  2761 			case ESpudLinkDown:	    // LinkLayerDown received, not queued for deletion.
       
  2762 				__FLOG_2(_L("Lower NIF binder for context[%d] is in state[%S], and is not eligible for Stop."),aContextId,SpudStateToText(ref->State()));
       
  2763 				break;
       
  2764 				
       
  2765 			case ESpudHaveQos:
       
  2766 			default:
       
  2767 				__FLOG_2(_L("Lower NIF binder for context[%d] is in unexpected state[%S]."),aContextId,SpudStateToText(ref->State()));
       
  2768 				ASSERT(EFalse);
       
  2769 				break;		
       
  2770 			}
       
  2771 		}
       
  2772 	}
       
  2773 
       
  2774 /**
       
  2775 Send a packet across the link.
       
  2776 This function should not be called; the Mux is the one that should get the data.
       
  2777 
       
  2778 @param aPacket MBuf chain containing packet (ignored)
       
  2779 @param aSource (ignored)
       
  2780 
       
  2781 @return Error code, or 1 if packet was queued,
       
  2782         or KErrNone to flow off sender
       
  2783 */
       
  2784 TInt CSpudMan::Send(RMBufChain& /*aPacket*/, TAny* /*aSource*/)
       
  2785 	{
       
  2786     _LIT(KPanicMsg, "CSpudMan");
       
  2787     User::Panic(KPanicMsg, KErrNotSupported);
       
  2788 	return KErrNotSupported;	// never reached
       
  2789     }
       
  2790 
       
  2791 
       
  2792 /**
       
  2793 Receives notification from NIFMAN that the authenticate data is ready.
       
  2794 */
       
  2795 void CSpudMan::AuthenticateComplete(TInt aResult)
       
  2796 	{
       
  2797 	// Send AuthenticateComplete to all lower NIFs
       
  2798 	TContextId i;
       
  2799 	for (i=0; i < KMaxPdpContexts; ++i)
       
  2800 		{
       
  2801 		CSpudBinderRef* ref = NULL;
       
  2802 		TRAPD(rc, ref = iBindMan->GetRefL(i));
       
  2803 		if (rc == KErrNone)
       
  2804 			{
       
  2805 			ref->NifLink()->AuthenticateComplete(aResult);
       
  2806 			}
       
  2807 		}
       
  2808 	}
       
  2809 
       
  2810 void CSpudMan::Restart(CNifIfBase* /*aIf*/)
       
  2811 	{
       
  2812 	// TODO: Is it safe to simply ignore this?
       
  2813 	__FLOG_0(_L("CSpudMan::Restart. Ignored."));
       
  2814     ASSERT(EFalse);
       
  2815 	}
       
  2816 
       
  2817 
       
  2818 //*****************************************************************************
       
  2819 // SPUD methods
       
  2820 //*****************************************************************************
       
  2821 
       
  2822 /**
       
  2823 Receives progress notifications from lower NIF.
       
  2824 
       
  2825 @param aContextId Context ID of lower NIF
       
  2826 @param aStage Progress stage
       
  2827 @param aError Error code
       
  2828 */
       
  2829 void CSpudMan::IfProgress(TContextId aContextId, TInt aStage, TInt aError)
       
  2830 	{
       
  2831 	__FLOG_3(_L("CSpudMan::IfProgress context ID %d received stage %d error %d"),
       
  2832 			 aContextId, aStage, aError);
       
  2833  	// Eliminate compiler warnings in release builds
       
  2834 	aContextId = aContextId;
       
  2835 	aStage = aStage;
       
  2836 	aError = aError;
       
  2837 	
       
  2838     // Drop all progress indications from lower NIFs on the floor because they'll just confuse NIFMAN.
       
  2839     // SpudMan generates its own progress notifications.
       
  2840     }
       
  2841 
       
  2842 /**
       
  2843 Receives progress notifications from lower NIF.
       
  2844 
       
  2845 @param aContextId Context ID of lower NIF
       
  2846 @param aSubConnectionUniqueId Subconnection ID
       
  2847 @param aStage Progress stage
       
  2848 @param aError Error code
       
  2849 */
       
  2850 void CSpudMan::IfProgress(TContextId aContextId, TSubConnectionUniqueId aSubConnectionUniqueId, TInt aStage, TInt aError)
       
  2851 	{
       
  2852 	__FLOG_4(_L("CSpudMan::IfProgress context ID %d subconnection ID %d received stage %d error %d"),
       
  2853 			 aContextId, aSubConnectionUniqueId, aStage, aError);
       
  2854  	// Eliminate compiler warnings in release builds
       
  2855 	aContextId = aContextId;
       
  2856 	aSubConnectionUniqueId = aSubConnectionUniqueId;
       
  2857 	aStage = aStage;
       
  2858 	aError = aError;
       
  2859 
       
  2860     // Drop all progress indications from lower NIFs on the floor because they'll just confuse NIFMAN.
       
  2861     // SpudMan generates its own progress notifications.
       
  2862     }
       
  2863 
       
  2864 /**
       
  2865 Receives notifications from lower NIF to agent.
       
  2866 
       
  2867 @param aContextId Valid context ID of lower NIF
       
  2868 @param aEvent Event type
       
  2869 @param aInfo Additional information for event (ignored)
       
  2870 @return KErrNone on success, or KErrNotSupported
       
  2871 */
       
  2872 TInt CSpudMan::Notification(TContextId aContextId, TNifToAgentEventType aEvent, void* /*aInfo*/)
       
  2873 	{
       
  2874 	__FLOG_2(_L("CSpudMan::Notification context ID %d event ID %d"), aContextId, aEvent);
       
  2875 	switch (aEvent)
       
  2876 		{
       
  2877 	case ENifToAgentEventTsyConfig:
       
  2878 		{
       
  2879 		// Return GPRS context structure to lower NIF
       
  2880 		CSpudBinderRef* ref = NULL;
       
  2881 		TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  2882 		__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  2883 		ASSERT(ref->IsBound());
       
  2884 
       
  2885 	    iPdpFsmInterface.Get(aContextId, iTempGprsContext);
       
  2886         ref->NifLink()->Notification(EAgentToNifEventTsyConfig, reinterpret_cast<void*>(&iTempGprsContext));
       
  2887 	    return KErrNone;
       
  2888 		}
       
  2889 
       
  2890 	case ENifToAgentEventTsyConnectionSpeed:
       
  2891 		{
       
  2892 		// Return connection speed to lower NIF
       
  2893 		CSpudBinderRef* ref = NULL;
       
  2894 		TRAPD(rc, ref = iBindMan->GetRefL(aContextId));
       
  2895 		__ASSERT_ALWAYS(rc == KErrNone, Panic());
       
  2896 		ASSERT(ref->IsBound());
       
  2897 
       
  2898 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  2899 		RPacketQoS::TQoSR5Negotiated params;
       
  2900 #else
       
  2901 		RPacketQoS::TQoSR99_R4Negotiated params;
       
  2902 #endif 
       
  2903 // SYMBIAN_NETWORKING_UMTSR5 
       
  2904 
       
  2905 		iPdpFsmInterface.Get(aContextId, params);
       
  2906 		ref->NifLink()->Notification(EAgentToNifEventTsyConnectionSpeed,
       
  2907 	    						 reinterpret_cast<void*>(static_cast<TUint>(params.iMaxRate.iUplinkRate)));
       
  2908 
       
  2909 	    return KErrNone;
       
  2910 		}
       
  2911 
       
  2912 	default:
       
  2913 		// Just ignore all the other notifications
       
  2914 		__FLOG_0(_L("Ignoring notification"));
       
  2915 		break;
       
  2916 		}
       
  2917 
       
  2918 	return KErrNotSupported;
       
  2919 	}
       
  2920 
       
  2921 /**
       
  2922 Read a boolean field from the connection settings provider.
       
  2923 Intercepts reads of CommPort and returns the correct value.
       
  2924 
       
  2925 @param aContextId Valid context ID of lower NIF
       
  2926 @param aField The name of the field to read
       
  2927 @param aValue On return, contains the value of the field read
       
  2928 @return KErrNone, if successful; otherwise one of the standard Symbian OS error codes
       
  2929 */
       
  2930 TInt CSpudMan::ReadInt(TContextId aContextId, const TDesC& aField, TUint32& aValue)
       
  2931 	{
       
  2932 	
       
  2933 	//This fix is needed to ensure that multiple PPP channels can be used for different PDP contexts. 
       
  2934 	//The returned value of ECommDbCdmaNaiMobileIp will cause PPP to skip external IP configuration (NCPIP).
       
  2935 	if ( (TPtrC(CDMA_NAI_TYPE) == aField) && (iPrimaryContextId != aContextId) )
       
  2936 		{
       
  2937 		__FLOG_2(_L("CSpudMan::ReadInt context ID %d field  = CDMA_NAI_TYPE - Therefore explicitly setting Value to ECommDbCdmaNaiMobileIp"),
       
  2938 			aContextId, &aField);
       
  2939 		__FLOG(_L("No call to AgentRef Will be make"));
       
  2940 		// Lower NIF is requesting the NAI type
       
  2941 		aValue = ECommDbCdmaNaiMobileIp;
       
  2942 		return KErrNone;
       
  2943 		}
       
  2944 	__FLOG_2(_L("CSpudMan::ReadInt context ID %d field %S"), aContextId, &aField);
       
  2945 	// Read CommDB normally
       
  2946 	return Notify()->ReadInt(aField, aValue);
       
  2947 	}
       
  2948 
       
  2949 /**
       
  2950 Read a 8-bit descriptor field from the connection settings provider.
       
  2951 Intercepts reads of CommPort and returns the value returned from ETel.
       
  2952 
       
  2953 @param aContextId Valid context ID of lower NIF
       
  2954 @param aField The name of the field to read
       
  2955 @param aValue On return, contains the value of the field read
       
  2956 @return KErrNone, if successful; otherwise one of the standard Symbian OS error codes
       
  2957 */
       
  2958 TInt CSpudMan::ReadDes(TContextId aContextId, const TDesC& aField, TDes8& aValue)
       
  2959 	{
       
  2960 	__FLOG_2(_L("CSpudMan::ReadDes context ID %d field %S"), aContextId, &aField);
       
  2961 	TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName;
       
  2962 	_LIT(KFormatText,"%s\\%s");
       
  2963 
       
  2964 	columnName.Format(KFormatText,MODEM_BEARER,MODEM_PORT_NAME);
       
  2965 	if (columnName == aField)
       
  2966 		{
       
  2967 		// Lower NIF is requesting the CSY port name
       
  2968 		// Use the TDes16 version of ReadDes to retrieve the data
       
  2969 		TBuf16<KCommsDbSvrMaxFieldLength> data;
       
  2970 		TInt rc(ReadDes(aContextId, aField, data));
       
  2971 		aValue.Copy(data);
       
  2972 		return rc;
       
  2973 		}
       
  2974 
       
  2975 	columnName.Format(KFormatText,MODEM_BEARER,MODEM_CSY_NAME);
       
  2976 	if (columnName == aField)
       
  2977 		{
       
  2978 		// Lower NIF is requesting the CSY file name
       
  2979 		// Use the TDes16 version of ReadDes to retrieve the data
       
  2980 		TBuf16<KCommsDbSvrMaxFieldLength> data;
       
  2981 		TInt rc(ReadDes(aContextId, aField, data));
       
  2982 		aValue.Copy(data);
       
  2983 		return rc;
       
  2984 		}
       
  2985 
       
  2986 	// Read CommDB normally
       
  2987 	return Notify()->ReadDes(aField, aValue);
       
  2988 	}
       
  2989 
       
  2990 /**
       
  2991 Read a 16-bit descriptor field from the connection settings provider.
       
  2992 Intercepts reads of CommPort and returns the value returned from ETel.
       
  2993 
       
  2994 @param aContextId Valid context ID of lower NIF
       
  2995 @param aField The name of the field to read
       
  2996 @param aValue On return, contains the value of the field read
       
  2997 @return KErrNone, if successful; otherwise one of the standard Symbian OS error codes
       
  2998 */
       
  2999 TInt CSpudMan::ReadDes(TContextId aContextId, const TDesC& aField, TDes16& aValue)
       
  3000     {
       
  3001 	__FLOG_2(_L("CSpudMan::ReadDes context ID %d field %S"), aContextId, &aField);
       
  3002 	TBuf<2*KCommsDbSvrMaxColumnNameLength+1> columnName;
       
  3003 	_LIT(KFormatText,"%s\\%s");
       
  3004 
       
  3005 	columnName.Format(KFormatText,MODEM_BEARER,MODEM_PORT_NAME);
       
  3006 	if (columnName == aField)
       
  3007 		{
       
  3008 		// Lower NIF is requesting the CSY port name
       
  3009 	    iPdpFsmInterface.Get(aContextId, iTempDataChannelV2);
       
  3010 		__FLOG_1(_L("Returning ETel port name %S"), &iTempDataChannelV2.iPort);
       
  3011 		aValue.Copy(iTempDataChannelV2.iPort);
       
  3012 		return KErrNone;
       
  3013 		}
       
  3014 
       
  3015 	columnName.Format(KFormatText,MODEM_BEARER,MODEM_CSY_NAME);
       
  3016 	if (columnName == aField)
       
  3017 		{
       
  3018 		// Lower NIF is requesting the CSY file name
       
  3019 	    iPdpFsmInterface.Get(aContextId, iTempDataChannelV2);
       
  3020 		__FLOG_1(_L("Returning ETel CSY name %S"), &iTempDataChannelV2.iCsy);
       
  3021 		aValue.Copy(iTempDataChannelV2.iCsy);
       
  3022 		return KErrNone;
       
  3023 		}
       
  3024 
       
  3025 	return Notify()->ReadDes(aField, aValue);
       
  3026     }
       
  3027 
       
  3028 /**
       
  3029 Marks the binder to the lower NIF for asynchronous deletion 
       
  3030 
       
  3031 @param aRef the binder
       
  3032 @pre the binder must be bound the lower NIF.
       
  3033 */
       
  3034 void CSpudMan::DisposeOfBinder(CSpudBinderRef* aRef)
       
  3035 	{
       
  3036 	ASSERT(aRef);
       
  3037 	ASSERT(aRef->IsBound()); // We can only mark - sweep bound instances
       
  3038 	ASSERT(aRef->State() != ESpudWaitBinderDelete);
       
  3039 	aRef->SetState(ESpudWaitBinderDelete);
       
  3040 	iBinderSweeperNotifierCb->Call(); // Queue deletion of marked binders & optional Nifman notification.
       
  3041 	}
       
  3042 
       
  3043 /**
       
  3044 Sweeps the set of lower NIF binding, deleting the marked ones. If no contexts remain after,
       
  3045 notifies Nifman that SPUD has gone down.
       
  3046 
       
  3047 @param aContextId The ID of the context to delete
       
  3048 @param aReason error code that is passed to Nifman
       
  3049 */
       
  3050 void CSpudMan::SweepBindersAndNotify()
       
  3051 	{
       
  3052 	const TUint KNumContextsRemaining(BindMan()->SweepBinders());
       
  3053 	if (0 == KNumContextsRemaining)
       
  3054 		{
       
  3055 		SetTerminateError(KErrAbort); // This is a last ditched effort to provide termination
       
  3056 		// error code. We cannot determine in all cases what has caused SPUD to terminate.
       
  3057 		// E.g. if several secondary contexts were deleted by the network, which  of them caused SPUD termination?
       
  3058 		// In such case we say that SPUD is shutting down due to internal event (namely, last context deletion).
       
  3059 		
       
  3060 		__FLOG_3(_L("Last lower NIF has been deleted: Notifying Nifman with action EDisconnect[%d], progress KLinkLayerClosed[%d], reason[%d]"),	
       
  3061 		MNifIfNotify::EDisconnect, KLinkLayerClosed, iTerminateError);
       
  3062 		
       
  3063 		// Once we've notified LinkLayerDown & IfProgress, we are finished. Nifman will delete us any moment after
       
  3064 		// the RunL we are working from returns.
       
  3065 		__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."));
       
  3066 
       
  3067 		// Tell Nifman clients that SPUD is finished.
       
  3068 		Notify()->LinkLayerDown(iTerminateError, MNifIfNotify::EDisconnect); 
       
  3069 		Notify()->IfProgress(KLinkLayerClosed, iTerminateError);
       
  3070 		}
       
  3071 	else
       
  3072 		{
       
  3073 		__FLOG_1(_L("There are [%d] contexts remaining."), KNumContextsRemaining);
       
  3074 		}
       
  3075 	}
       
  3076 
       
  3077 void CSpudMan::SetupSipServerAddrRetrievalL(RPacketContext::TProtocolConfigOptionV2& aPco)
       
  3078 	{
       
  3079 	__FLOG(_L("CSpudMan::SetupSipServerAddrRetrieval - Requesting the P-CSCF address from the PCO buffer"));
       
  3080 	
       
  3081 	TPtr8 pcoPtr(const_cast<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
       
  3082 	
       
  3083 	// attach TTlv to the buffer
       
  3084 	TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
       
  3085 	tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktPCSCFAddressRequest), 
       
  3086 		TPtr8(static_cast<TUint8*>(NULL), 0, 0));
       
  3087 	aPco.iMiscBuffer.SetLength(pcoPtr.Length());
       
  3088 	}
       
  3089 	
       
  3090 
       
  3091 #ifdef SYMBIAN_NETWORKING_UMTSR5
       
  3092 	
       
  3093 void CSpudMan::SetIMCNSignallingFlagPcoL(RPacketContext::TProtocolConfigOptionV2& aPco)
       
  3094 /**
       
  3095 Put the value for IMCN Signalling flag in the pco buffer if it is set in database
       
  3096 
       
  3097 @param PCO IE Buffer
       
  3098 */
       
  3099 	{
       
  3100 	TBool imcn=EFalse;
       
  3101 	TBuf<2*KCommsDbSvrMaxColumnNameLength+2> columnName;
       
  3102     _LIT(KFormatText,"%s\\%s");
       
  3103     columnName.Format(KFormatText,QOS_UMTS_R99_AND_ON_TABLE,GPRS_QOS_IM_CN_SIGNALLING_INDICATOR);
       
  3104     TRAPD(ret, Notify()->ReadBool(columnName,imcn););
       
  3105 	__FLOG_1(_L("CSpudMan::SetIMCNSignallingFlagPcoL - Requesting IMCN Signalling status from Database: error = %d"),ret);
       
  3106 
       
  3107 	 if (imcn && ret==KErrNone )
       
  3108 
       
  3109 	 {
       
  3110 	  TPtr8 pcoPtr(const_cast<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
       
  3111 	  TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
       
  3112 	  tlv.AppendItemL(RPacketContext::TPcoId(RPacketContext::EEtelPcktIMCNMSSubsystemSignallingFlag ), 
       
  3113 	  TPtr8(static_cast<TUint8*>(NULL), 0, 0));
       
  3114 	  aPco.iMiscBuffer.SetLength(pcoPtr.Length());
       
  3115 	 }
       
  3116 	}
       
  3117 TBool CSpudMan::GetIMCNSignallingFlagPcoL(RPacketContext::TProtocolConfigOptionV2& aPco)
       
  3118 /**
       
  3119 Get the value for IMCN Signalling from the network pco buffer
       
  3120 
       
  3121 @param PCO IE Buffer
       
  3122 */
       
  3123 	{
       
  3124 	
       
  3125 	__FLOG(_L("CSpudMan::GetIMCNSignallingFlagPcoL - Retrieving the IMCN signalling Flag from the PCO buffer"));
       
  3126 	
       
  3127 	TPtr8 pcoPtr(const_cast<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
       
  3128 	TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> tlv(pcoPtr,0);
       
  3129 	tlv.ResetCursorPos();
       
  3130 
       
  3131 	TInt err = tlv.NextItemL(RPacketContext::EEtelPcktIMCNNetworkSubsystemSignallingFlag,pcoPtr);
       
  3132 	return (err == KErrNone);
       
  3133 	
       
  3134 	}
       
  3135 
       
  3136 #endif // SYMBIAN_NETWORKING_UMTSR5
       
  3137 	
       
  3138 	
       
  3139 void CSpudMan::SetSipServerAddrL(const RPacketContext::TProtocolConfigOptionV2& aPco)
       
  3140 	{
       
  3141 	__FLOG(_L("CSpudMan::SetSipServerAddr - Retrieving the P-CSCF address from the PCO buffer"));
       
  3142 	iSipServerAddr.Reset(); //Free all existing entries
       
  3143 	TPtr8 pcoPtr(const_cast<TUint8*>(aPco.iMiscBuffer.Ptr()),aPco.iMiscBuffer.Length(),aPco.iMiscBuffer.MaxLength());
       
  3144 	TTlvStruct<RPacketContext::TPcoId,RPacketContext::TPcoItemDataLength> 
       
  3145 		tlv(pcoPtr,0);
       
  3146 		
       
  3147 	tlv.ResetCursorPos();
       
  3148 	TIp6Addr addr;
       
  3149 	TPtr8 addrPtr(NULL, 0);
       
  3150 	TPckg<TIp6Addr> addrPckg(addr);
       
  3151 		
       
  3152 	while (tlv.NextItemL(RPacketContext::EEtelPcktPCSCFAddress,addrPtr) == KErrNone)
       
  3153 		{
       
  3154 		TInetAddr inetAddr;
       
  3155 		addrPckg.Copy(addrPtr);
       
  3156 		inetAddr.SetAddress(addr);
       
  3157 		TBuf<KMaxInetAddrPrintSize> testbuf;
       
  3158 		inetAddr.Output(testbuf);
       
  3159 		__FLOG_1(_L("CSpudMan::SetSipServerAddr - P-CSCF address ---> %S"),&testbuf);
       
  3160 		if (testbuf.Length()) //ie the address is invalid
       
  3161 			{
       
  3162 			iSipServerAddr.AppendL(inetAddr);
       
  3163 			}
       
  3164 		}
       
  3165 	}
       
  3166 	
       
  3167 void CSpudMan::SetContextTerminationErrorAndStop(TContextId aContextId, TInt aErrorCode)
       
  3168 	{
       
  3169 	__FLOG_2(_L("SetContextTerminateError on StatusEvent: aContextId[%d], aErrorCode[%d]"),	
       
  3170 		aContextId, aErrorCode);
       
  3171 	
       
  3172 	// If there is no error then simply return
       
  3173 	if (KErrNone == aErrorCode) return;
       
  3174 	
       
  3175     // If secondary context, store error code in individual contexts reference
       
  3176     // and stop the secondary context
       
  3177     if(aContextId != iPrimaryContextId)
       
  3178         {
       
  3179 			StopContext(aContextId, aErrorCode, MNifIfNotify::EDisconnect);
       
  3180         }
       
  3181     else
       
  3182         {
       
  3183         // This is a problem with the Primary context so stop and disconnect
       
  3184         // Now save the termination error code if not already set
       
  3185    		if (iTerminateError == KErrNone)
       
  3186 			{
       
  3187 			iTerminateError = aErrorCode;
       
  3188 			}
       
  3189 
       
  3190 		// This may be the first ETel error code so save it
       
  3191 		if (iETelTerminateError == KErrNone)
       
  3192 			{
       
  3193 			iETelTerminateError = aErrorCode;
       
  3194 			}
       
  3195 
       
  3196         // Primary context has a problem so disconnect
       
  3197         Stop(aErrorCode, MNifIfNotify::EDisconnect);
       
  3198         }
       
  3199 	}
       
  3200 		
       
  3201 //*************************************************************************
       
  3202 // CLowerNifBinderDeletionCb
       
  3203 // Asynchronous deletion of CSpudBinderRefs and notification to Nifman
       
  3204 //*************************************************************************
       
  3205 // Use Spudman's logging.
       
  3206 // Because we are owned by Spudman, we don't have to worry about the logger being deleted.
       
  3207 #ifdef __FLOG_ACTIVE
       
  3208 #define BINDER_SWEEPER_LOG(x) iSpudMan.x
       
  3209 #else
       
  3210 #define BINDER_SWEEPER_LOG(x)
       
  3211 #endif
       
  3212 
       
  3213 // Construct a High-Priority AO that calls into the SPUD
       
  3214 // This will work with any priority AO, but because we are releasing memory and 
       
  3215 // potentially notifying Nifman, we want to run ASAP.
       
  3216 CBinderSweeperNotifierCb::CBinderSweeperNotifierCb(CSpudMan& aSpudMan)
       
  3217 	:
       
  3218 	CAsyncOneShot(CActive::EPriorityHigh), 
       
  3219 	iSpudMan(aSpudMan)
       
  3220 	{
       
  3221 	}
       
  3222 
       
  3223 // Queues the deletion callback 
       
  3224 void CBinderSweeperNotifierCb::Call()
       
  3225 	{
       
  3226 	if(!IsActive()) // We can be called again before we had a chance to run.
       
  3227 		{
       
  3228 		BINDER_SWEEPER_LOG(__FLOG(_L("CBinderSweeperNotifierCb: Queueing async deletion of dead lower NIF bindings."));)
       
  3229 		CAsyncOneShot::Call();
       
  3230 		return;
       
  3231 		}
       
  3232 	BINDER_SWEEPER_LOG(__FLOG(_L("CBinderSweeperNotifierCb: Async deletion of dead lower NIF bindings is already queued."));)
       
  3233 	}
       
  3234 
       
  3235 
       
  3236 // Called by ActiveScheduler.
       
  3237 //
       
  3238 // If the lower NIF deletion is attempted after Nifman deletes the SPUD 
       
  3239 // (from CNifAgentRef::DisconnectionComplete), the lower NIF deletion AO is corrupted in the 
       
  3240 // ActiveScheduler, causing ESock thread to crash. To prevent this, lower NIFs are deleted 
       
  3241 // before signalling LinkLayerDown to Nifman. When a lower NIF signals LinkLayerDown, a callback into Spudman is queued.
       
  3242 // This callback deletes the lower NIFs that are eligible for deletion, and notifies Nifman, if necessary.	*/	
       
  3243 void CBinderSweeperNotifierCb::RunL()
       
  3244 	{
       
  3245 	iSpudMan.SweepBindersAndNotify();
       
  3246 	}
       
  3247