24
|
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 |
}
|