24
|
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 binder manager
|
|
15 |
//
|
|
16 |
//
|
|
17 |
|
|
18 |
/**
|
|
19 |
@file
|
|
20 |
@internalComponent
|
|
21 |
*/
|
|
22 |
|
|
23 |
#include "bindman.h"
|
|
24 |
#include "spudnotify.h"
|
|
25 |
#include "mux.h"
|
|
26 |
#include <nifman.h>
|
|
27 |
|
|
28 |
/** Default name of lower NIF */
|
|
29 |
_LIT(KDefaultLowerNifName, "rawip");
|
|
30 |
|
|
31 |
#ifdef __FLOG_ACTIVE
|
|
32 |
#define BINDMAN_LOG(x) SpudMan()->x
|
|
33 |
#else
|
|
34 |
#define BINDMAN_LOG(x)
|
|
35 |
#endif
|
|
36 |
|
|
37 |
//*****************************************************************************
|
|
38 |
// CBindMan
|
|
39 |
//*****************************************************************************
|
|
40 |
|
|
41 |
/**
|
|
42 |
Constructs BindMan. Ownership of aMux and aProto is transferred to this object.
|
|
43 |
|
|
44 |
@param aSpudMan Reference to SpudMan object
|
|
45 |
@param aMux Pointer to SpudMux object (ownership is transferred)
|
|
46 |
@param aProto Pointer to SpudProtocol object (ownership is transferred)
|
|
47 |
*/
|
|
48 |
CBindMan::CBindMan(CSpudMan& aSpudMan, CSpudMux* aMux, CSpudProtocol* aProto)
|
|
49 |
: iSpudMan(aSpudMan), iMux(aMux), iDeleteMux(ETrue), iSpudProtocol(aProto)
|
|
50 |
{
|
|
51 |
ReadLowerNifName();
|
|
52 |
}
|
|
53 |
|
|
54 |
CBindMan::~CBindMan()
|
|
55 |
{
|
|
56 |
BINDMAN_LOG(__FLOG(_L("BindMan::~BindMan")));
|
|
57 |
|
|
58 |
#ifdef __FLOG_ACTIVE // Log for diagnostic purposes
|
|
59 |
TInt idx;
|
|
60 |
for(idx = 0; idx < iBinders.Count(); ++idx)
|
|
61 |
{
|
|
62 |
if(iBinders[idx] && iBinders[idx]->IsBound())
|
|
63 |
{
|
|
64 |
BINDMAN_LOG(__FLOG_1(_L("~BindMan: deleting bound lower NIF binding for context[%d]"), idx));
|
|
65 |
}
|
|
66 |
}
|
|
67 |
#endif
|
|
68 |
|
|
69 |
iBinders.DeleteAll();
|
|
70 |
delete iSpudProtocol;
|
|
71 |
if (iDeleteMux)
|
|
72 |
{
|
|
73 |
delete iMux;
|
|
74 |
}
|
|
75 |
}
|
|
76 |
|
|
77 |
/**
|
|
78 |
Reads the lower NIF name from CommDb.
|
|
79 |
|
|
80 |
@todo This function incorrectly returns the default value when IfParams is of the form:
|
|
81 |
"notlowernif=UNWANTED,lowernif=IGNORED".
|
|
82 |
This defect is also present in CPppLcp::InitL.
|
|
83 |
*/
|
|
84 |
void CBindMan::ReadLowerNifName(void)
|
|
85 |
{
|
|
86 |
TBuf<KCommsDbSvrMaxFieldLength> params;
|
|
87 |
_LIT(KInterfaceIdentifier,"lowernif=");
|
|
88 |
const TInt KLinkEqualsLength = 9; // length of "lowernif="
|
|
89 |
ASSERT(static_cast<const TDesC&>(KInterfaceIdentifier).Length() == KLinkEqualsLength);
|
|
90 |
|
|
91 |
// Read IfParams field
|
|
92 |
iSpudMan.Notify()->ReadDes(TPtrC(ISP_IF_PARAMS), params);
|
|
93 |
|
|
94 |
TInt paramStartMarker = params.Find(KInterfaceIdentifier);
|
|
95 |
|
|
96 |
if (paramStartMarker == KErrNotFound)
|
|
97 |
{
|
|
98 |
// "lowernif=" not found in the string - use default lower layer
|
|
99 |
iLowerNifName = KDefaultLowerNifName;
|
|
100 |
BINDMAN_LOG(__FLOG_1(_L("Lower NIF name not configured; defaulting to %S"), &iLowerNifName));
|
|
101 |
}
|
|
102 |
else
|
|
103 |
{
|
|
104 |
// "lowernif=<nifname>" found in the string - extract the lower layer Nif name
|
|
105 |
|
|
106 |
if (paramStartMarker > 0 && params[paramStartMarker-1] != ',')
|
|
107 |
{
|
|
108 |
// "xyzlowernif=<xxx>" found rather than "lowernif=<xxx>" - use default lower layer
|
|
109 |
iLowerNifName = KDefaultLowerNifName;
|
|
110 |
BINDMAN_LOG(__FLOG_1(_L("Lower NIF name not configured; defaulting to %S"), &iLowerNifName));
|
|
111 |
}
|
|
112 |
else
|
|
113 |
{
|
|
114 |
// String of the form "[...,]lowernif=<nifname>[,...]" found - extract the Nif name
|
|
115 |
TPtrC postfix(params.Mid(paramStartMarker + KLinkEqualsLength));
|
|
116 |
TInt comma = postfix.Locate(',');
|
|
117 |
if (comma != KErrNotFound)
|
|
118 |
{
|
|
119 |
postfix.Set(postfix.Ptr(), comma);
|
|
120 |
}
|
|
121 |
iLowerNifName = postfix;
|
|
122 |
}
|
|
123 |
}
|
|
124 |
}
|
|
125 |
|
|
126 |
/**
|
|
127 |
Informs CSpudProtocol of the CProtocolBase pointer from the L3 protocol.
|
|
128 |
*/
|
|
129 |
void CBindMan::SetProtocolBaseL(CProtocolBase* aProtocolBase) const
|
|
130 |
{
|
|
131 |
iSpudProtocol->SetProtocolBaseL(aProtocolBase);
|
|
132 |
}
|
|
133 |
|
|
134 |
/**
|
|
135 |
Returns the binder for the given context ID.
|
|
136 |
@param aContextId context ID
|
|
137 |
@return Pointer to binder object
|
|
138 |
@leave KErrBadHandle or KErrNotReady if context ID is invalid or not found
|
|
139 |
*/
|
|
140 |
CSpudBinderRef* CBindMan::GetRefL(TContextId aContextId) const
|
|
141 |
{
|
|
142 |
if (aContextId < 0 || aContextId >= iBinders.Count())
|
|
143 |
{
|
|
144 |
BINDMAN_LOG(__FLOG_1(_L("CBindMan::GetRefL invalid context ID %d"), aContextId));
|
|
145 |
User::Leave(KErrBadHandle);
|
|
146 |
}
|
|
147 |
CSpudBinderRef* ref = iBinders[aContextId];
|
|
148 |
if (ref == NULL)
|
|
149 |
{
|
|
150 |
// This situation can frequently occur when looping through all binders
|
|
151 |
User::Leave(KErrNotReady);
|
|
152 |
}
|
|
153 |
return ref;
|
|
154 |
}
|
|
155 |
|
|
156 |
/**
|
|
157 |
Returns the binder for any lower NIF that is available and bound.
|
|
158 |
@return Pointer to binder object
|
|
159 |
@leave KErrNotReady if no lower NIF is found
|
|
160 |
*/
|
|
161 |
CSpudBinderRef* CBindMan::GetAnyRefL() const
|
|
162 |
{
|
|
163 |
TInt index;
|
|
164 |
for (index=0; index < iBinders.Count(); ++index)
|
|
165 |
{
|
|
166 |
CSpudBinderRef* ref = iBinders[index];
|
|
167 |
if (ref && ref->IsBound() && ref->State() != ESpudWaitBinderDelete)
|
|
168 |
{
|
|
169 |
return ref;
|
|
170 |
}
|
|
171 |
}
|
|
172 |
BINDMAN_LOG(__FLOG_0(_L("CBindMan::GetAnyRefL Can't find any bound NIF")));
|
|
173 |
User::Leave(KErrNotReady);
|
|
174 |
return NULL; // never reached
|
|
175 |
}
|
|
176 |
|
|
177 |
/**
|
|
178 |
Returns the context ID the given lower NIF.
|
|
179 |
@param aNifBase pointer to lower NIF
|
|
180 |
@return context ID
|
|
181 |
@leave KErrNotReady if lower NIF is not found
|
|
182 |
*/
|
|
183 |
TContextId CBindMan::FindContextIdL(const CNifIfBase* aNifBase) const
|
|
184 |
{
|
|
185 |
TContextId index;
|
|
186 |
for (index=0; index < iBinders.Count(); ++index)
|
|
187 |
{
|
|
188 |
CSpudBinderRef* ref = iBinders[index];
|
|
189 |
if (ref && ref->MatchBase(aNifBase))
|
|
190 |
{
|
|
191 |
return index;
|
|
192 |
}
|
|
193 |
}
|
|
194 |
BINDMAN_LOG(__FLOG_1(_L("CBindMan::FindContextIdL Can't find aNifBase %x"), aNifBase));
|
|
195 |
User::Leave(KErrNotReady);
|
|
196 |
return KAllContexts; // never reached
|
|
197 |
}
|
|
198 |
|
|
199 |
/**
|
|
200 |
Returns the number of bound contexts.
|
|
201 |
@return Number of bound contexts
|
|
202 |
*/
|
|
203 |
TUint CBindMan::NumContexts() const
|
|
204 |
{
|
|
205 |
TInt index;
|
|
206 |
TUint count = 0;
|
|
207 |
for (index=0; index < iBinders.Count(); ++index)
|
|
208 |
{
|
|
209 |
CSpudBinderRef* ref = iBinders[index];
|
|
210 |
if (ref && ref->IsBound())
|
|
211 |
{
|
|
212 |
++count;
|
|
213 |
}
|
|
214 |
}
|
|
215 |
return count;
|
|
216 |
}
|
|
217 |
|
|
218 |
/**
|
|
219 |
Checks if this is is the last 'valid' context in SPUD, i.e. it is bound and not marked for deletion.
|
|
220 |
|
|
221 |
@param aContextID the ID of the context to check
|
|
222 |
@return ETrue if and only if aContextId (the subject bindre) is the only valid, bound, unmarked binder.
|
|
223 |
*/
|
|
224 |
TBool CBindMan::IsLastContext(TContextId aContextId)const
|
|
225 |
{
|
|
226 |
ASSERT(aContextId >= 0 && NumContexts() > 0); // we shouldn't be called unless we have at least 1 ctx
|
|
227 |
|
|
228 |
TUint numLiveBoundBinders(0);
|
|
229 |
TBool isTargetBinderFound(EFalse); // The binder for the subject context exists, is bound, and not marked for deletion.
|
|
230 |
|
|
231 |
TInt binderIdx;
|
|
232 |
for(binderIdx = 0; binderIdx < iBinders.Count(); ++binderIdx) // sift through all the binders
|
|
233 |
{
|
|
234 |
if(iBinders[binderIdx] && // binder exists
|
|
235 |
iBinders[binderIdx]->IsBound() && // is bound
|
|
236 |
ESpudWaitBinderDelete != iBinders[binderIdx]->State() // not marked for deletion
|
|
237 |
)
|
|
238 |
{
|
|
239 |
++numLiveBoundBinders;
|
|
240 |
|
|
241 |
if(binderIdx == aContextId)
|
|
242 |
{
|
|
243 |
isTargetBinderFound = ETrue;
|
|
244 |
}
|
|
245 |
}
|
|
246 |
}
|
|
247 |
ASSERT(isTargetBinderFound); // sanity check: we have a referene to the subject binder,
|
|
248 |
// and it is 'valid': bound and not marked for deletion.
|
|
249 |
|
|
250 |
if(0 == numLiveBoundBinders) // No valid bound binders remain.
|
|
251 |
{
|
|
252 |
ASSERT(EFalse); // spudman thinks it has valid binders, when there are none.
|
|
253 |
|
|
254 |
// In release builds, we can't say that there are more binders, because we have no
|
|
255 |
// references to them.
|
|
256 |
return ETrue; // EFalse implies that we have at least 1 binder
|
|
257 |
}
|
|
258 |
else if(1 == numLiveBoundBinders)
|
|
259 |
{
|
|
260 |
// In release builds: if live binder is not the subject context, we can't claim that the
|
|
261 |
// subject context is the last one, or SPUD may shutdown when it has a context.
|
|
262 |
return isTargetBinderFound; // Is there another valid binder beside the subject?
|
|
263 |
}
|
|
264 |
else // > 1
|
|
265 |
{
|
|
266 |
// Regardless of whether the subject context was found, we have more.
|
|
267 |
return EFalse;
|
|
268 |
}
|
|
269 |
}
|
|
270 |
|
|
271 |
/**
|
|
272 |
Creates and returns a pointer to a new binder object. Ownership remains with BindMan;
|
|
273 |
DeleteRef() must be called to delete the binder reference object.
|
|
274 |
|
|
275 |
@param aContextId Holds the new context ID on return
|
|
276 |
@return Pointer to binder object
|
|
277 |
@leave KErrNotSupported if we are out of PDP contexts, or KErrNoMemory if out of RAM
|
|
278 |
*/
|
|
279 |
CSpudBinderRef* CBindMan::GetNewRefForSecondaryL(TContextId& aContextId)
|
|
280 |
{
|
|
281 |
// Reusing the slot of the primary context is not allowed.
|
|
282 |
static const TContextId KFirst2ndaryCtxIdx(KPrimaryContextId + 1);
|
|
283 |
TContextId index;
|
|
284 |
for (index = KFirst2ndaryCtxIdx; index < iBinders.Count(); ++index)
|
|
285 |
{
|
|
286 |
CSpudBinderRef*& ref = iBinders[index];
|
|
287 |
if (ref == NULL)
|
|
288 |
{
|
|
289 |
// Create a binder in this new slot
|
|
290 |
aContextId = index;
|
|
291 |
// ref is a reference to a pointer that is owned by Bindman. It will be deleted in the
|
|
292 |
// destructor. There is no need for CleanupStack.
|
|
293 |
ref = new (ELeave) CSpudBinderRef(*iSpudMan.BindMan());
|
|
294 |
ref->ConstructL(iSpudMan.Notify(), aContextId);
|
|
295 |
return ref;
|
|
296 |
}
|
|
297 |
else if (!ref->IsBound())
|
|
298 |
{
|
|
299 |
// This binder was previously constructed but unbound
|
|
300 |
ASSERT(ref->Notify() == iSpudMan.Notify());
|
|
301 |
aContextId = index;
|
|
302 |
return ref;
|
|
303 |
}
|
|
304 |
}
|
|
305 |
BINDMAN_LOG(__FLOG_0(_L("CBindMan::GetNewRefForSecondaryL No room for new binder reference")));
|
|
306 |
User::Leave(KErrNotSupported);
|
|
307 |
return NULL; // never reached
|
|
308 |
}
|
|
309 |
|
|
310 |
|
|
311 |
|
|
312 |
/**
|
|
313 |
Creates and returns a pointer to the new binder for the Primary PDP context.
|
|
314 |
The primary is a special case, because it can be created only once, and it uses a special
|
|
315 |
ID = 0. If the primary fails then a secondary can be promoted to primary status
|
|
316 |
even in this case ID = 0 is not re-used because GetNewRefForSecondaryL prevents this.
|
|
317 |
This means that KPrimaryContextId is only significant once at startup time!
|
|
318 |
|
|
319 |
Ownership remains with BindMan;
|
|
320 |
DeleteRef() must be called to delete the binder reference object.
|
|
321 |
|
|
322 |
@return the pointer to the binder object for the primary pdp context.
|
|
323 |
@leave if the construction of the binder leaves.
|
|
324 |
*/
|
|
325 |
CSpudBinderRef* CBindMan::GetNewRefForPrimaryL()
|
|
326 |
{
|
|
327 |
CSpudBinderRef*& primRef = iBinders[KPrimaryContextId];
|
|
328 |
if(primRef) // We must not try to create the primary more than once.
|
|
329 |
{
|
|
330 |
ASSERT(EFalse);
|
|
331 |
User::Leave(KErrAlreadyExists); // Release builds
|
|
332 |
}
|
|
333 |
// primRef is a reference to a pointer that is owned by Bindman. It will be deleted in the
|
|
334 |
// destructor. There is no need for CleanupStack.
|
|
335 |
primRef = new (ELeave) CSpudBinderRef(*iSpudMan.BindMan());
|
|
336 |
primRef->ConstructL(iSpudMan.Notify(), KPrimaryContextId);
|
|
337 |
return primRef;
|
|
338 |
}
|
|
339 |
|
|
340 |
|
|
341 |
|
|
342 |
/**
|
|
343 |
Loads a new lower NIF and bind to the binder ref
|
|
344 |
|
|
345 |
@param aName Protocol name desired
|
|
346 |
@param aBinder the binder to bind the lower NIF into.
|
|
347 |
@see CNifAgentRef::ServiceStarted()
|
|
348 |
*/
|
|
349 |
void CBindMan::LoadNifL(const TDesC& aName, CSpudBinderRef& aBinder)
|
|
350 |
{
|
|
351 |
BINDMAN_LOG(__FLOG_2(_L("CBindMan::LoadNifL loading NIF %S for protocol %S"), &iLowerNifName, &aName));
|
|
352 |
|
|
353 |
CNifIfLink* lowerNif=static_cast<CNifIfLink*>(Nif::CreateInterfaceL(iLowerNifName, aBinder.Notify()));
|
|
354 |
|
|
355 |
// Increment reference count
|
|
356 |
lowerNif->Open();
|
|
357 |
|
|
358 |
CleanupClosePushL(*lowerNif);
|
|
359 |
// Create CNifIfBase and bind it
|
|
360 |
// Maybe binding should be left to CSpudBinderRef
|
|
361 |
CNifIfBase* nifBase = lowerNif->GetBinderL(aName);
|
|
362 |
CleanupStack::Pop();
|
|
363 |
|
|
364 |
// Increment reference count
|
|
365 |
nifBase->Open();
|
|
366 |
|
|
367 |
// Bind the lower NIF into the SPUD
|
|
368 |
aBinder.Bind(lowerNif, nifBase);
|
|
369 |
|
|
370 |
// Bind the lower NIF to SpudProtocol
|
|
371 |
nifBase->BindL(iSpudProtocol);
|
|
372 |
}
|
|
373 |
|
|
374 |
|
|
375 |
/** Deletes the dead (marked for deletion) references to lower NIF bindings..
|
|
376 |
|
|
377 |
@return the number of contexts remaining after the deletion
|
|
378 |
*/
|
|
379 |
TUint CBindMan::SweepBinders()
|
|
380 |
{
|
|
381 |
TUint liveContexts(0);
|
|
382 |
TInt binderIdx;
|
|
383 |
for(binderIdx = 0; binderIdx < iBinders.Count(); ++binderIdx) // Sift through all the binders
|
|
384 |
{
|
|
385 |
if(iBinders[binderIdx] && iBinders[binderIdx]->IsBound()) // Binder exists and is bound to a lower NIF
|
|
386 |
{
|
|
387 |
if(ESpudWaitBinderDelete == iBinders[binderIdx]->State()) //Must be deleted
|
|
388 |
{
|
|
389 |
BINDMAN_LOG(__FLOG_1(_L("CBindMan::SweepBinders: deleting binder for context[%d]"), binderIdx));
|
|
390 |
delete iBinders[binderIdx];
|
|
391 |
iBinders[binderIdx] = NULL;
|
|
392 |
}
|
|
393 |
else // Binder exists and is bound, but is not eligible for deletion.
|
|
394 |
{
|
|
395 |
BINDMAN_LOG(__FLOG_1(_L("CBindMan::SweepBinders: context[%d] is alive."), binderIdx));
|
|
396 |
++liveContexts;
|
|
397 |
}
|
|
398 |
}
|
|
399 |
// Binder is not bound. We don't care. It will be taken care of in the destructor.
|
|
400 |
}
|
|
401 |
return liveContexts;
|
|
402 |
}
|
|
403 |
|
|
404 |
//*****************************************************************************
|
|
405 |
// CSpudBinderRef
|
|
406 |
//*****************************************************************************
|
|
407 |
|
|
408 |
|
|
409 |
CSpudBinderRef::CSpudBinderRef(CBindMan& aBindMan)
|
|
410 |
:iBindMan(aBindMan)
|
|
411 |
{
|
|
412 |
}
|
|
413 |
|
|
414 |
CSpudBinderRef::~CSpudBinderRef()
|
|
415 |
{
|
|
416 |
if (IsBound())
|
|
417 |
{
|
|
418 |
// This call causes the NIF base to delete itself
|
|
419 |
iNifBase->Close();
|
|
420 |
|
|
421 |
// This call causes the NIF link to delete itself
|
|
422 |
iNifLink->Close();
|
|
423 |
}
|
|
424 |
|
|
425 |
delete iNotify;
|
|
426 |
}
|
|
427 |
|
|
428 |
/**
|
|
429 |
Creates a SpudNotify object.
|
|
430 |
@leave KErrNoMemory if out of RAM
|
|
431 |
*/
|
|
432 |
void CSpudBinderRef::ConstructL(MNifIfNotify* aNotify, TContextId aContextId)
|
|
433 |
{
|
|
434 |
iNotify = new (ELeave) CSpudNotify(iBindMan, aNotify, aContextId);
|
|
435 |
}
|