telephonyprotocols/gprsumtsqosprt/src/iface.cpp
changeset 0 3553901f7fa8
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2007-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 //
       
    15 
       
    16 #include <in_iface.h>
       
    17 
       
    18 #include "context.h"
       
    19 #include "async_request.h"
       
    20 #include "iface.h"
       
    21 #include "tc.h"
       
    22 #include "guqos.h"
       
    23 #include "guqos_log.h"
       
    24 
       
    25 CNif* CNif::NewL(CNifIfBase& aInterface, CModuleGuqos& aModule)
       
    26 	{
       
    27 	CNif* nif = new (ELeave) CNif(aInterface, aModule);
       
    28 	CleanupStack::PushL(nif);
       
    29 	nif->ConstructL();
       
    30 	CleanupStack::Pop();
       
    31 	return nif;
       
    32 	}
       
    33 
       
    34 //	XNifTimeoutLinkage
       
    35 //	******************
       
    36 //	Glue to bind timeout callback from the timeout manager into Timeout() call
       
    37 //	on the CPdpContext
       
    38 //
       
    39 //	*NOTE*
       
    40 //		This kludgery is all static and compile time, and only used in the constructor
       
    41 //		of CPdpContext.
       
    42 //
       
    43 
       
    44 // This ungainly manoevure is forced on us because the offset is not evaluated early enough by GCC3.4 to be
       
    45 // passed as a template parameter
       
    46 #if defined(__X86GCC__) || defined(__GCCE__)
       
    47 #define KNifTimeoutOffset 2144
       
    48 __ASSERT_COMPILE(KNifTimeoutOffset == _FOFF(CNif, iTimeout));
       
    49 #else
       
    50 #define KNifTimeoutOffset _FOFF(CNif, iTimeout)
       
    51 #endif
       
    52 
       
    53 class XNifTimeoutLinkage : public TimeoutLinkage<CNif, KNifTimeoutOffset>
       
    54 	{
       
    55 public:
       
    56 	static void Timeout(RTimeout &aLink, const TTime & /*aNow*/, TAny * /*aPtr*/)
       
    57 		{
       
    58 		Object(aLink)->RunPendingRequests();
       
    59 		}
       
    60 	};
       
    61 
       
    62 CNif::CNif(CNifIfBase& aNif, CModuleGuqos& aModule) : iNif(aNif), iModule(aModule), iTimeout(XNifTimeoutLinkage::Timeout)
       
    63 	{
       
    64 	LOG(Log::Printf(_L("new\tCNif[%u] size=%d"), (TInt)this, sizeof(*this)));
       
    65 	iContexts.SetOffset(_FOFF(CPdpContext, iNext));
       
    66 	iPending.SetOffset(_FOFF(CRequestBase, iLink));
       
    67 	}
       
    68 
       
    69 void CNif::ConstructL()
       
    70 	{
       
    71 	// The instance for the primary context exists always for CNif
       
    72 	iPrimary = CPdpContext::NewL(*this, EPrimaryContext, 0);
       
    73 	AddContext(*iPrimary);
       
    74 
       
    75 	User::LeaveIfError(RegisterEventHandler());
       
    76 
       
    77 	// Get IapId from Nif
       
    78 	TSoIfConnectionInfo netinfo;
       
    79 	TPckg<TSoIfConnectionInfo> option(netinfo);
       
    80 	if (iNif.Control(KSOLInterface, KSoIfGetConnectionInfo, option) == KErrNone)
       
    81 		iIapId = netinfo.iIAPId;
       
    82 	}
       
    83 
       
    84 CNif::~CNif()
       
    85 	{
       
    86 	LOG(Log::Printf(_L("~\tCNif[%u] Start"), (TInt)this));
       
    87 	// No upcalls from NIF, we are in destructor!
       
    88 	CloseInterface();
       
    89 
       
    90 	// Unconditionallly terminate all request activities
       
    91 
       
    92 	// Note: CompleteAndDestruct ends up calling "CloseRequest",
       
    93 	// which may attempt to activate the next request in queue. To avoid
       
    94 	// this, set iCurrentRequest to NULL.
       
    95 	iCurrentRequest = NULL;
       
    96 	while (!iPending.IsEmpty())
       
    97 		{
       
    98 		CRequestBase* request = iPending.First();
       
    99 		request->CompleteAndDestruct(KErrDied, NULL);
       
   100 		}
       
   101 
       
   102 	// Remove all PDP Contexts from NIF and GUQOS
       
   103 	while (!iContexts.IsEmpty())
       
   104 		{
       
   105 		CPdpContext *context = iContexts.First();
       
   106 		// Remove context from iContexts list before
       
   107 		// giving control out (to NIF) After this
       
   108 		// the context instance is no more "reachable"
       
   109 		// from anywhere else.
       
   110 		RemoveContext(*context);
       
   111 		context->Delete();	// Delete context from NIF
       
   112 		delete context;
       
   113 		}
       
   114 	iContexts.Reset();
       
   115 	iTimeout.Cancel();
       
   116 	LOG(Log::Printf(_L("\tCNif[%u] Destruction Completed"), (TInt)this));
       
   117 	}
       
   118 
       
   119 // Initialize the iParameters and return reference
       
   120 TContextParameters& CNif::ContextParameters()
       
   121 	{
       
   122 	//?? Hope this doesn't generate a memory leak?
       
   123 	//?? is iParameters.iContextConfig.Reset() required instead?
       
   124 	iParameters = TContextParameters();
       
   125 	return iParameters;
       
   126 	}
       
   127 
       
   128 
       
   129 CPdpContext* CNif::FindContext(TInt aContextId)
       
   130 	{
       
   131 	TContextIter iter(iContexts);
       
   132 	CPdpContext *context;
       
   133 
       
   134 	while ((context = iter++) != NULL)
       
   135 		if (context->ContextId() == aContextId)
       
   136 			return context;
       
   137 	return NULL;
       
   138 	}
       
   139 	
       
   140 CPdpContext* CNif::FindChannel(TInt aChannelId)
       
   141 	{
       
   142 	TContextIter iter(iContexts);
       
   143 	CPdpContext *context;
       
   144 
       
   145 	while ((context = iter++) != NULL)
       
   146 		if (context->ChannelId() == aChannelId)
       
   147 			return context;
       
   148 	return NULL;
       
   149 	}
       
   150 
       
   151 
       
   152 // Choose new default Pdp context with the highest QoS profile (according to TS 23.107).
       
   153 //
       
   154 // *Note*
       
   155 //		Because in 3GPP there can be only ONE Context without any TFT's, this code
       
   156 //		assumes that the lower layer (NIF) has already deleted the current primary
       
   157 //		context. If this is not true, the TFT removal will fail at 3GPP level!
       
   158 void CNif::SelectNewDefaultContext()
       
   159 	{
       
   160 	TContextIter iter(iContexts);
       
   161 	CPdpContext* context;
       
   162 	CPdpContext* highestQoS=NULL;
       
   163 
       
   164 	while ((context = iter++) != NULL)
       
   165 		{
       
   166 		if (context == DefaultPdpContext())
       
   167 			continue;	// Exclude the current default from the search.
       
   168 
       
   169 		//lint -e{961} would want terminating 'else' (we don't)
       
   170 		if (!highestQoS)
       
   171 			highestQoS = context;
       
   172 		else if (context->GetQoSRanking() < highestQoS->GetQoSRanking())
       
   173 			highestQoS = context;
       
   174 		}
       
   175 	if (highestQoS == NULL)
       
   176 		{
       
   177 		// No other contexts available, cannot delete or change the primary!
       
   178 		LOG(Log::Printf(_L("\tOnly primary context available -- cannot be deleted")));
       
   179 		return;
       
   180 		}
       
   181 	//
       
   182 	// Assign the new default context!
       
   183 	// (iPrimary pointer is only additional reference, it does not "own" the
       
   184 	// pointed object, thus just overwriting it is ok -- all contexts are in
       
   185 	// iContexts list).
       
   186 	iPrimary = highestQoS;
       
   187 	LOG(Log::Printf(_L("\tContext %d (channel=%d) is the new default context"), iPrimary->ContextId(), iPrimary->ChannelId()));
       
   188 	// Use the CClose request to clean out all TFT filters
       
   189 	// from the context (when context is primary, the RemoveFilters
       
   190 	// removes all, regardless of how many flows are connected).
       
   191 	CClose* request = CClose::New(*highestQoS);
       
   192 	if (request)
       
   193 		{
       
   194 		highestQoS->Nif().AddRequest(*request);
       
   195 		}
       
   196 	else
       
   197 		{
       
   198 		// If allocation of the request fails, there is not much that can
       
   199 		// be done, the filters will be left there and packets not matching
       
   200 		// them will be dropped. However, the cleanup will be attempted
       
   201 		// again any time the context is modified in such way that filters
       
   202 		// need to be removed.
       
   203 		LOG(Log::Printf(_L("\tCould not remove TFTs from new default context -- no room for request")));
       
   204 		}
       
   205 	}
       
   206 
       
   207 // delete PDP context, and bind flows using this context to default PDP context
       
   208 void CNif::DeletePdpContext(CPdpContext* aContext)
       
   209 	{
       
   210 
       
   211 	if (DefaultPdpContext() == aContext)
       
   212 		{
       
   213 		// Attempt to select a new default context (may fail)
       
   214 		SelectNewDefaultContext();
       
   215 		}
       
   216 
       
   217 	CPdpContext *pdpDefault = DefaultPdpContext();
       
   218 	if (pdpDefault != aContext)
       
   219 		{
       
   220 		while (!aContext->Flows().IsEmpty())
       
   221 			{
       
   222 			CFlowData* flow = aContext->Flows().First();
       
   223 			// The SetContext will remove the flow from old
       
   224 			// context, and eventually the aContext->Flows()
       
   225 			// *MUST* become empty
       
   226 			// (because aContext != pdpContext)
       
   227 			flow->SetContext(pdpDefault);
       
   228 			}
       
   229 		RemoveContext(*aContext);
       
   230 		delete aContext;
       
   231 		}
       
   232 	else
       
   233 		{
       
   234 		// Cannot delete the default context, just block flows (as the
       
   235 		// context is not actually existing any more).
       
   236 		aContext->Block();
       
   237 		}
       
   238 	}
       
   239 
       
   240 TInt CNif::RegisterEventHandler()
       
   241 	{
       
   242 	TPckgBuf<TEvent> opt;
       
   243 	opt().iEvent = this;
       
   244 	LOG(Log::Printf(_L("\tcall NIF Control(KRegisterEventHandler)")));
       
   245 	return iNif.Control(KSOLInterface, KRegisterEventHandler, opt);
       
   246 	}
       
   247 
       
   248 TInt CNif::SetEvents(TBool aValue)
       
   249 	{
       
   250 	TPckgBuf<TBool> opt;
       
   251 	opt() = aValue;
       
   252 	LOG(Log::Printf(_L("\tcall NIF Control(KContextSetEvents. %d)"), aValue));
       
   253 	return iNif.Control(KSOLInterface, KContextSetEvents, opt);
       
   254 	}
       
   255 
       
   256 
       
   257 // event received from Nif when the Network status changes
       
   258 TInt CNif::NetworkStatusEvent(const TNetworkParameters& aNetworkEvent)
       
   259 	{
       
   260 	switch(aNetworkEvent.iNetworkEventCode)
       
   261 		{
       
   262 
       
   263 	case KNetworkConnectionLost:
       
   264 		break;
       
   265 
       
   266 	case KNetworkInterfaceDown:
       
   267 		iModule.IfManager()->DeleteNif(this);
       
   268 		break;
       
   269 
       
   270 	default:
       
   271 		return KErrNotSupported;
       
   272 		}
       
   273 
       
   274 	return KErrNone;
       
   275 	}
       
   276 
       
   277 
       
   278 // Receive events from umtsnif
       
   279 TInt CNif::Event(CProtocolBase* aProtocol, TUint aName, TDes8& aOption, TAny* /*aSource*/)
       
   280 	{
       
   281 	LOG(Log::Printf(_L("")));	// just make empty line into log
       
   282 #ifdef _LOG
       
   283 	TBuf<40> name;
       
   284 
       
   285 	switch(aName)
       
   286 		{
       
   287 		case KContextDeleteEvent:				name.Append(_L("KContextDeleteEvent"));				break;
       
   288 		case KContextActivateEvent:				name.Append(_L("KContextActivateEvent"));			break;
       
   289 		case KContextParametersChangeEvent:		name.Append(_L("KContextParametersChangeEvent"));	break;
       
   290 		case KContextBlockedEvent:				name.Append(_L("KContextBlockedEvent"));			break;
       
   291 		case KContextUnblockedEvent:			name.Append(_L("KContextUnblockedEvent"));			break;
       
   292 		case KNetworkStatusEvent:				name.Append(_L("KNetworkStatusEvent"));				break;
       
   293 		case KContextQoSSetEvent:				name.Append(_L("KContextQoSSetEvent"));				break;
       
   294 		case KContextTFTModifiedEvent:			name.Append(_L("KContextTFTModifiedEvent"));		break;
       
   295 		case KPrimaryContextCreated:			name.Append(_L("KPrimaryContextCreated"));			break;
       
   296 		case KSecondaryContextCreated:			name.Append(_L("KSecondaryContextCreated"));		break;
       
   297 		case KContextModifyActiveEvent:			name.Append(_L("KContextModifyActiveEvent"));		break;
       
   298 		case KGetNegQoSEvent:					name.Append(_L("KGetNegQoSEvent"));					break;
       
   299 		default:								name.Append(_L("error"));							break;
       
   300 		}
       
   301 
       
   302 	LOG(Log::Printf(_L("CNif::Event,aName: %d, name: {%S}"), aName, &name));
       
   303 #else
       
   304 	LOG(Log::Printf(_L("CNif::Event(name=%d)"), aName));
       
   305 #endif
       
   306 
       
   307 #ifndef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   308 //PREQ399 had to disable this check because in the new architecture, in order to
       
   309 //plug UmtsIf capable CFProtos (formerly Nifs) they need to be below IProto,
       
   310 //and hence aProtocol will never match the iNif reference that we have here.
       
   311 	if ((CNifIfBase *)aProtocol != &iNif)
       
   312 		{
       
   313 		LOG(Log::Printf(_L("\tThe CNifIfBase[%u] parameter does not match my CNifIBase[%u]"), (TInt)aProtocol, (TInt)&iNif));
       
   314 		return KErrNotFound;	// Not called from what we expect! (invalid use of API)
       
   315 		}
       
   316 #else
       
   317     (void)aProtocol;
       
   318 #endif
       
   319 	// Handle KNetworkStatusEvent first.
       
   320 	if (aName == KNetworkStatusEvent)
       
   321 		{
       
   322 		if (aOption.Length() >= (TInt)sizeof(TNetworkParameters))
       
   323 			{
       
   324 			const TNetworkParameters& opt = *(TNetworkParameters*)aOption.Ptr();
       
   325 			NetworkStatusEvent(opt);
       
   326 			return KErrNone;
       
   327 			}
       
   328 		LOG(Log::Printf(_L("\tThe aOption length=%d is too short for TNetworkParameters (size=%d)"),
       
   329 			aOption.Length(), (TInt)sizeof(TNetworkParameters)));
       
   330 		return KErrArgument;
       
   331 		}
       
   332 
       
   333 	// All remaining valid events use TContextParameters, do the shared
       
   334 	// checking and preprocess before the switch...
       
   335 	if (aOption.Length() != (TInt)sizeof(TContextParameters))
       
   336 		{
       
   337 		LOG(Log::Printf(_L("\tThe aOption length=%d does not match TContextParamaters (size=%d)"),
       
   338 			aOption.Length(), (TInt)sizeof(TContextParameters)));
       
   339 		return KErrArgument;
       
   340 		}
       
   341 	const TContextParameters& opt = *(TContextParameters*)aOption.Ptr();
       
   342 
       
   343 	// PrimaryContextCreated/SecondaryContextCreated do not have the context
       
   344 	// id in opt yet, handle those separately here (because searching PDP
       
   345 	// context by id would fail.
       
   346 	if (aName == KPrimaryContextCreated)
       
   347 		{
       
   348 		return PrimaryContextCreated(opt);
       
   349 		}
       
   350 	else if (aName == KSecondaryContextCreated)
       
   351 		{
       
   352 		SecondaryContextCreated(opt);
       
   353 		return KErrNone;
       
   354 		}
       
   355 
       
   356 	// Even if the aOption is not TContextParameters, nothing bad happens.
       
   357 	// In that case teh context is searced with random id, which either is
       
   358 	// found or not.
       
   359 	CPdpContext *context = FindContext(opt.iContextInfo.iContextId);
       
   360 	if (context == NULL)
       
   361 		{
       
   362 		return KErrNotFound;	// Context does not exist any more
       
   363 		}
       
   364 
       
   365 	switch (aName)
       
   366 		{
       
   367 	case KContextUnblockedEvent:
       
   368 		// independent of any request pending
       
   369 		// NOTE: NIF *MUST* always provide the correct context status for Unblock
       
   370 		context->SetContextStatus(opt.iContextInfo.iStatus);
       
   371 		context->UnBlock();
       
   372 		return KErrNone;
       
   373 
       
   374 	case KContextBlockedEvent:
       
   375 		// independent of any request pending
       
   376 		// NOTE: NIF *MUST* always provide the correct context status for Block
       
   377 		context->SetContextStatus(opt.iContextInfo.iStatus);
       
   378 		context->Block();
       
   379 		return KErrNone;
       
   380 
       
   381 	case KContextDeleteEvent:
       
   382 		// independent of any request pending
       
   383 		context->SetContextStatus(opt.iContextInfo.iStatus);
       
   384 				
       
   385 		// qos framework has to be notified!!!
       
   386 		context->DeleteEvent(opt);
       
   387 		DeletePdpContext(context);
       
   388 		return KErrNone;
       
   389 
       
   390 	case KContextParametersChangeEvent:
       
   391 		// independent of any request pending
       
   392 		context->ParametersChangedEvent(opt);
       
   393 		return KErrNone;
       
   394 
       
   395 	case KContextQoSSetEvent:
       
   396 		context->SetQoSReply(iCurrentRequest, opt);
       
   397 		return KErrNone;
       
   398 
       
   399 	case KContextTFTModifiedEvent:
       
   400 		context->ModifyTftReply(iCurrentRequest, opt);
       
   401 		return KErrNone;
       
   402 
       
   403 
       
   404 	case KContextActivateEvent:
       
   405 		context->ActivateReply(iCurrentRequest, opt);
       
   406 		return KErrNone;
       
   407 
       
   408 	case KContextModifyActiveEvent:
       
   409 		context->ModifyActiveReply(iCurrentRequest, opt);
       
   410 		return KErrNone;
       
   411 
       
   412 	default:
       
   413 		break;
       
   414 		}
       
   415 	return KErrNotSupported;
       
   416 	}
       
   417 
       
   418 
       
   419 void CNif::SetDefaultQoS()
       
   420 	{
       
   421 	LOG(Log::Printf(_L("\tSetDefaultQoS -- begin")));
       
   422 	TQoSRequested policy;
       
   423 	TInt ret = iModule.GetDefaultParameters(policy, iIapId);
       
   424 	if (ret == KErrNone)
       
   425 		{
       
   426 		TContextParameters& parameters(ContextParameters());
       
   427 		parameters.iContextConfig.SetUMTSQoSReq(policy);
       
   428 		TPckg<TContextParameters> opt(parameters);
       
   429 		LOG(Log::Printf(_L("\tcall NIF Control(KNifSetDefaultQoS)")));
       
   430 		iNif.Control(KSOLInterface, KNifSetDefaultQoS, opt);
       
   431 		}
       
   432 	LOG(Log::Printf(_L("\tSetDefaultQoS -- end")));
       
   433 	}
       
   434 
       
   435 void CNif::AddContext(CPdpContext& aContext)
       
   436 	{
       
   437 	iContexts.AddLast(aContext);
       
   438 	}
       
   439 
       
   440 TInt CNif::PrimaryContextCreated(const TContextParameters& aParams)
       
   441 	{
       
   442 	TNifIfInfo info;
       
   443 	iNif.Info(info);
       
   444 	LOG(Log::Printf(_L("CNif::PrimaryContextCreated [Nif=%S]"),&info.iName));
       
   445 	
       
   446 	iPrimary->SetContextStatus(aParams.iContextInfo.iStatus);
       
   447 
       
   448 	SetStatus(EReady);
       
   449 	IssueRequest();
       
   450 	return KErrNone;
       
   451 	}
       
   452 
       
   453 void CNif::SecondaryContextCreated(const TContextParameters& aParams)
       
   454 	{
       
   455 	if (iCurrentRequest)
       
   456 		{
       
   457 		SetStatus(EReady);
       
   458 		CPdpContext* context=NULL;
       
   459 		TRAPD(err, context = CPdpContext::NewL(*this, ESecondaryContext, aParams.iContextInfo.iContextId));
       
   460 		if (err == KErrNone)
       
   461 			{
       
   462 			//coverity[leave_without_push]
       
   463 			context->SetContextStatus(aParams.iContextInfo.iStatus);
       
   464 			AddContext(*context);
       
   465 			iCurrentRequest->Run(EPendingCreate, context, aParams);
       
   466 			return;	// Do not fall to context destruction.		
       
   467 			}
       
   468 		else
       
   469 			{
       
   470 			iCurrentRequest->CompleteAndDestruct(err, NULL);
       
   471 			// Fall to context destruction...
       
   472 			}
       
   473 		}
       
   474 	// Either there was no request to receive this, or running low on memory
       
   475 	LOG(Log::Printf(_L("CNif::SecondaryContextCreated -- but, GUGOS cannot use it, deleting context")));
       
   476 	TPckg<TContextParameters> options(aParams);
       
   477 	iNif.Control(KSOLInterface, KContextDelete, options);
       
   478 	}
       
   479 
       
   480 // Issue the creation of secondary PDP context
       
   481 TInt CNif::NewPdpContext()
       
   482 	{
       
   483 	LOG(Log::Printf(_L("\t\tCNif::NewPdpContext -- request creation of secondary context")));
       
   484 	TPckg<TContextParameters> opt(ContextParameters());
       
   485 	opt().iContextType = ESecondaryContext;
       
   486 	const TInt ret(iNif.Control(KSOLInterface, KContextCreate, opt));
       
   487 	return (ret == KErrNone) ? opt().iReasonCode : ret;
       
   488 	}
       
   489 
       
   490 
       
   491 // Turn off events
       
   492 TInt CNif::CloseInterface()
       
   493 	{
       
   494 	return SetEvents(EFalse);
       
   495 	}
       
   496 
       
   497 void CNif::AddRequest(CRequestBase& aRequest)
       
   498 	{
       
   499 	iPending.AddLast(aRequest);
       
   500 	++iPendingSequence;	// iPending Modified
       
   501 	LOG(Log::Printf(_L("\trequest %S[%u] -- Queued for activation on IAP=%u"), aRequest.iName, (TInt)&aRequest, iIapId));
       
   502 	IssueRequest();
       
   503 	}
       
   504 
       
   505 void CNif::CancelPendingRequest(CFlowData* aFlowData)
       
   506 	{
       
   507 	LOG(Log::Printf(_L("\tCancelPendingRequest for FLOW -- BEGIN")));
       
   508 	TUint32 mark;
       
   509 	do
       
   510 		{
       
   511 		mark = iPendingSequence;
       
   512 		TSglQueIter<CRequestBase> iter(iPending);
       
   513 		CRequestBase* request;
       
   514 		while (iPendingSequence == mark && (request = iter++) != NULL)
       
   515 			request->Cancel(aFlowData);
       
   516 		}
       
   517 	while (mark != iPendingSequence);
       
   518 	LOG(Log::Printf(_L("\tCancelPendingRequest FLOW -- END")));
       
   519 	}
       
   520 
       
   521 
       
   522 void CNif::CancelPendingRequest(CPdpContext* aContext)
       
   523 	{
       
   524 	LOG(Log::Printf(_L("\tCancelPendingRequest for PDP -- BEGIN")));
       
   525 
       
   526 	TUint32 mark;
       
   527 	do
       
   528 		{
       
   529 		mark = iPendingSequence;
       
   530 		TSglQueIter<CRequestBase> iter(iPending);
       
   531 		CRequestBase* request;
       
   532 		while (iPendingSequence == mark && (request = iter++) != NULL)
       
   533 			request->Cancel(aContext);
       
   534 		}
       
   535 	while (mark != iPendingSequence);
       
   536 
       
   537 	LOG(Log::Printf(_L("\tCancelPendingRequest for PDP -- END")));
       
   538 	}
       
   539 
       
   540 void CNif::IssueRequest()
       
   541 	{
       
   542 	// Request a callback with delay 0, calls RunPendingRequests as soon as possible.
       
   543 	iTimeout.Set(Module().TimeoutManager(), 0);
       
   544 	};
       
   545 
       
   546 void CNif::RunPendingRequests()
       
   547 	{
       
   548 	LOG(Log::Printf(_L("")));
       
   549 	if (Status() != EReady)
       
   550 		return;
       
   551 
       
   552 	while (!iPending.IsEmpty() && iCurrentRequest == NULL)
       
   553 		{
       
   554 		iCurrentRequest = iPending.First();
       
   555 		iCurrentRequest->Start();
       
   556 		}
       
   557 	}
       
   558 
       
   559 // Recompute evaluation precedences in use from the current state of PDP contexts.
       
   560 void CNif::RecomputeEvaluationPrecedences()
       
   561 	{
       
   562 	// This is called every time NIF returns the current set of filters.
       
   563 	//
       
   564 	// When new packet filters are added for the PDP Context, the
       
   565 	// precedence indexes must be selected for each of them and
       
   566 	// marked as used in the current table. Removal of filter must
       
   567 	// release the index, however at the time of TFT removal request,
       
   568 	// it is not yet known whether it will succeed.
       
   569 	//
       
   570 	// Eventually, NIF reports back what filters
       
   571 	// and indexes are actually used. Just recomputing the used
       
   572 	// status by scanning all (few) PDP Contexts and their current
       
   573 	// filters is the simplest solution to keep the information in
       
   574 	// in synch with NIF/network view of things.
       
   575 
       
   576 	Mem::FillZ(iEvaluationPrecedenceMap, sizeof(iEvaluationPrecedenceMap));
       
   577 	TContextIter iter(iContexts);
       
   578 	CPdpContext* context;
       
   579 	while ((context = iter++) != NULL)
       
   580 		{
       
   581 		for (TInt i = 0; i < context->iNumFilters; ++i)
       
   582 			{
       
   583 			const TInt p = context->iFilters[i].iEvaluationPrecedenceIndex;
       
   584 			if (p >= 0 && p < KMaxEvaluationPrecedences)
       
   585 				iEvaluationPrecedenceMap[p] = 1;
       
   586 			}
       
   587 		}
       
   588 	}
       
   589 
       
   590 // Evaluation precedence must be unique amongst all packet filters related to 
       
   591 // same APN. 
       
   592 TInt CNif::FindEvaluationPrecedence()
       
   593 	{
       
   594 	TUint i;
       
   595 	for (i=0; i < KMaxEvaluationPrecedences; i++)
       
   596 		{
       
   597 		if (iEvaluationPrecedenceMap[i] == 0)
       
   598 			{
       
   599 			iEvaluationPrecedenceMap[i] = 1;
       
   600 			return i;
       
   601 			}
       
   602 		}
       
   603 	return KErrNotFound;
       
   604 	}
       
   605 
       
   606 void CNif::CloseRequest(CRequestBase* aRequest)
       
   607 	{
       
   608 	LOG(Log::Printf(_L("\t\tCNif::CloseRequest")));
       
   609 	iPending.Remove(*aRequest);
       
   610 	++iPendingSequence;
       
   611 	// Note: If current request is already NULL, then this does not
       
   612 	// activate a new request from queue, even if there would be some.
       
   613 	// This is intentional -- see ~CNif() destructor!
       
   614 	if (iCurrentRequest != aRequest)
       
   615 		return;
       
   616 	iCurrentRequest = NULL;
       
   617 	IssueRequest();
       
   618 	}
       
   619 //
       
   620 CNifManager* CNifManager::NewL()
       
   621 	{
       
   622 	CNifManager* manager = new (ELeave) CNifManager();
       
   623 	CleanupStack::PushL(manager);
       
   624 	manager->ConstructL();
       
   625 	CleanupStack::Pop();
       
   626 	return manager;
       
   627 	}
       
   628 
       
   629 CNifManager::~CNifManager()
       
   630 	{
       
   631 	while (!iNifs.IsEmpty())
       
   632 		{
       
   633 		CNif* nif = iNifs.First();
       
   634 		iNifs.Remove(*nif);
       
   635 		delete nif;
       
   636 		}
       
   637 	iNifs.Reset();
       
   638 	}
       
   639 
       
   640 
       
   641 CNifManager::CNifManager()
       
   642 	{
       
   643 	iNifs.SetOffset(_FOFF(CNif, iNext));
       
   644 	}
       
   645 
       
   646 void CNifManager::ConstructL()
       
   647 	{
       
   648 	}
       
   649 
       
   650 CNif* CNifManager::CreateNifL(CNifIfBase& aInterface, CModuleGuqos& aModule)
       
   651 	{
       
   652 	CNif* nif = CNif::NewL(aInterface, aModule);
       
   653 	iNifs.AddLast(*nif);
       
   654 	nif->SetEvents(ETrue);
       
   655 	nif->SetDefaultQoS();
       
   656 	return nif;
       
   657 	}
       
   658 
       
   659 void CNifManager::DeleteNif(CNifIfBase* aInterface)
       
   660 	{
       
   661 	CNif* nif = FindInterface(aInterface);
       
   662 	if (nif)
       
   663 		DeleteNif(nif);
       
   664 	}
       
   665 
       
   666 void CNifManager::DeleteNif(CNif* aInterface)
       
   667 	{
       
   668 	iNifs.Remove(*aInterface);
       
   669 	delete aInterface;
       
   670 	}
       
   671 
       
   672 CNif* CNifManager::FindInterface(const CNifIfBase *aIface)
       
   673 	{
       
   674 	TNifIter iter(iNifs);
       
   675 	CNif* nif;
       
   676 	while ((nif = iter++) != NULL)
       
   677 		if (&nif->Interface() == aIface)
       
   678 			return nif;
       
   679 	return NULL;
       
   680 	}
       
   681 	
       
   682 CPdpContext* CNifManager::FindChannel(TInt aChannelId)
       
   683 	{
       
   684 	TNifIter iter(iNifs);
       
   685 	CNif* nif;
       
   686 	while ((nif = iter++) != NULL)
       
   687 		{
       
   688 		CPdpContext* context = nif->FindChannel(aChannelId);
       
   689 		if (context)
       
   690 			return context;
       
   691 		}
       
   692 	return NULL;
       
   693 	}
       
   694 
       
   695 
       
   696 // delete all pending requests related to this flow
       
   697 void CNifManager::CancelPendingRequests(CFlowData* aFlowData)
       
   698 	{
       
   699 	__ASSERT_ALWAYS(aFlowData!=NULL, User::Panic(_L("CNifManager::CancelPendingRequests"), 0));
       
   700 	TNifIter iter(iNifs);
       
   701 	CNif *nif;
       
   702 	while ((nif = iter++) != NULL)
       
   703 		nif->CancelPendingRequest(aFlowData);
       
   704 	}