diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/bindman.cpp --- a/telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/bindman.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyprotocols/secondarypdpcontextumtsdriver/spudman/src/bindman.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,435 +1,435 @@ -// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). -// All rights reserved. -// This component and the accompanying materials are made available -// under the terms of "Eclipse Public License v1.0" -// which accompanies this distribution, and is available -// at the URL "http://www.eclipse.org/legal/epl-v10.html". -// -// Initial Contributors: -// Nokia Corporation - initial contribution. -// -// Contributors: -// -// Description: -// SPUD binder manager -// -// - -/** - @file - @internalComponent -*/ - -#include "bindman.h" -#include "spudnotify.h" -#include "mux.h" -#include - -/** Default name of lower NIF */ -_LIT(KDefaultLowerNifName, "rawip"); - -#ifdef __FLOG_ACTIVE -#define BINDMAN_LOG(x) SpudMan()->x -#else -#define BINDMAN_LOG(x) -#endif - -//***************************************************************************** -// CBindMan -//***************************************************************************** - -/** -Constructs BindMan. Ownership of aMux and aProto is transferred to this object. - -@param aSpudMan Reference to SpudMan object -@param aMux Pointer to SpudMux object (ownership is transferred) -@param aProto Pointer to SpudProtocol object (ownership is transferred) -*/ -CBindMan::CBindMan(CSpudMan& aSpudMan, CSpudMux* aMux, CSpudProtocol* aProto) - : iSpudMan(aSpudMan), iMux(aMux), iDeleteMux(ETrue), iSpudProtocol(aProto) - { - ReadLowerNifName(); - } - -CBindMan::~CBindMan() - { - BINDMAN_LOG(__FLOG(_L("BindMan::~BindMan"))); - - #ifdef __FLOG_ACTIVE // Log for diagnostic purposes - TInt idx; - for(idx = 0; idx < iBinders.Count(); ++idx) - { - if(iBinders[idx] && iBinders[idx]->IsBound()) - { - BINDMAN_LOG(__FLOG_1(_L("~BindMan: deleting bound lower NIF binding for context[%d]"), idx)); - } - } - #endif - - iBinders.DeleteAll(); - delete iSpudProtocol; - if (iDeleteMux) - { - delete iMux; - } - } - -/** -Reads the lower NIF name from CommDb. - -@todo This function incorrectly returns the default value when IfParams is of the form: - "notlowernif=UNWANTED,lowernif=IGNORED". - This defect is also present in CPppLcp::InitL. -*/ -void CBindMan::ReadLowerNifName(void) - { - TBuf params; - _LIT(KInterfaceIdentifier,"lowernif="); - const TInt KLinkEqualsLength = 9; // length of "lowernif=" - ASSERT(static_cast(KInterfaceIdentifier).Length() == KLinkEqualsLength); - - // Read IfParams field - iSpudMan.Notify()->ReadDes(TPtrC(ISP_IF_PARAMS), params); - - TInt paramStartMarker = params.Find(KInterfaceIdentifier); - - if (paramStartMarker == KErrNotFound) - { - // "lowernif=" not found in the string - use default lower layer - iLowerNifName = KDefaultLowerNifName; - BINDMAN_LOG(__FLOG_1(_L("Lower NIF name not configured; defaulting to %S"), &iLowerNifName)); - } - else - { - // "lowernif=" found in the string - extract the lower layer Nif name - - if (paramStartMarker > 0 && params[paramStartMarker-1] != ',') - { - // "xyzlowernif=" found rather than "lowernif=" - use default lower layer - iLowerNifName = KDefaultLowerNifName; - BINDMAN_LOG(__FLOG_1(_L("Lower NIF name not configured; defaulting to %S"), &iLowerNifName)); - } - else - { - // String of the form "[...,]lowernif=[,...]" found - extract the Nif name - TPtrC postfix(params.Mid(paramStartMarker + KLinkEqualsLength)); - TInt comma = postfix.Locate(','); - if (comma != KErrNotFound) - { - postfix.Set(postfix.Ptr(), comma); - } - iLowerNifName = postfix; - } - } - } - -/** -Informs CSpudProtocol of the CProtocolBase pointer from the L3 protocol. -*/ -void CBindMan::SetProtocolBaseL(CProtocolBase* aProtocolBase) const - { - iSpudProtocol->SetProtocolBaseL(aProtocolBase); - } - -/** -Returns the binder for the given context ID. -@param aContextId context ID -@return Pointer to binder object -@leave KErrBadHandle or KErrNotReady if context ID is invalid or not found -*/ -CSpudBinderRef* CBindMan::GetRefL(TContextId aContextId) const - { - if (aContextId < 0 || aContextId >= iBinders.Count()) - { - BINDMAN_LOG(__FLOG_1(_L("CBindMan::GetRefL invalid context ID %d"), aContextId)); - User::Leave(KErrBadHandle); - } - CSpudBinderRef* ref = iBinders[aContextId]; - if (ref == NULL) - { - // This situation can frequently occur when looping through all binders - User::Leave(KErrNotReady); - } - return ref; - } - -/** -Returns the binder for any lower NIF that is available and bound. -@return Pointer to binder object -@leave KErrNotReady if no lower NIF is found -*/ -CSpudBinderRef* CBindMan::GetAnyRefL() const - { - TInt index; - for (index=0; index < iBinders.Count(); ++index) - { - CSpudBinderRef* ref = iBinders[index]; - if (ref && ref->IsBound() && ref->State() != ESpudWaitBinderDelete) - { - return ref; - } - } - BINDMAN_LOG(__FLOG_0(_L("CBindMan::GetAnyRefL Can't find any bound NIF"))); - User::Leave(KErrNotReady); - return NULL; // never reached - } - -/** -Returns the context ID the given lower NIF. -@param aNifBase pointer to lower NIF -@return context ID -@leave KErrNotReady if lower NIF is not found -*/ -TContextId CBindMan::FindContextIdL(const CNifIfBase* aNifBase) const - { - TContextId index; - for (index=0; index < iBinders.Count(); ++index) - { - CSpudBinderRef* ref = iBinders[index]; - if (ref && ref->MatchBase(aNifBase)) - { - return index; - } - } - BINDMAN_LOG(__FLOG_1(_L("CBindMan::FindContextIdL Can't find aNifBase %x"), aNifBase)); - User::Leave(KErrNotReady); - return KAllContexts; // never reached - } - -/** -Returns the number of bound contexts. -@return Number of bound contexts -*/ -TUint CBindMan::NumContexts() const - { - TInt index; - TUint count = 0; - for (index=0; index < iBinders.Count(); ++index) - { - CSpudBinderRef* ref = iBinders[index]; - if (ref && ref->IsBound()) - { - ++count; - } - } - return count; - } - -/** -Checks if this is is the last 'valid' context in SPUD, i.e. it is bound and not marked for deletion. - -@param aContextID the ID of the context to check -@return ETrue if and only if aContextId (the subject bindre) is the only valid, bound, unmarked binder. -*/ -TBool CBindMan::IsLastContext(TContextId aContextId)const - { - ASSERT(aContextId >= 0 && NumContexts() > 0); // we shouldn't be called unless we have at least 1 ctx - - TUint numLiveBoundBinders(0); - TBool isTargetBinderFound(EFalse); // The binder for the subject context exists, is bound, and not marked for deletion. - - TInt binderIdx; - for(binderIdx = 0; binderIdx < iBinders.Count(); ++binderIdx) // sift through all the binders - { - if(iBinders[binderIdx] && // binder exists - iBinders[binderIdx]->IsBound() && // is bound - ESpudWaitBinderDelete != iBinders[binderIdx]->State() // not marked for deletion - ) - { - ++numLiveBoundBinders; - - if(binderIdx == aContextId) - { - isTargetBinderFound = ETrue; - } - } - } - ASSERT(isTargetBinderFound); // sanity check: we have a referene to the subject binder, - // and it is 'valid': bound and not marked for deletion. - - if(0 == numLiveBoundBinders) // No valid bound binders remain. - { - ASSERT(EFalse); // spudman thinks it has valid binders, when there are none. - - // In release builds, we can't say that there are more binders, because we have no - // references to them. - return ETrue; // EFalse implies that we have at least 1 binder - } - else if(1 == numLiveBoundBinders) - { - // In release builds: if live binder is not the subject context, we can't claim that the - // subject context is the last one, or SPUD may shutdown when it has a context. - return isTargetBinderFound; // Is there another valid binder beside the subject? - } - else // > 1 - { - // Regardless of whether the subject context was found, we have more. - return EFalse; - } - } - -/** -Creates and returns a pointer to a new binder object. Ownership remains with BindMan; -DeleteRef() must be called to delete the binder reference object. - -@param aContextId Holds the new context ID on return -@return Pointer to binder object -@leave KErrNotSupported if we are out of PDP contexts, or KErrNoMemory if out of RAM -*/ -CSpudBinderRef* CBindMan::GetNewRefForSecondaryL(TContextId& aContextId) - { - // Reusing the slot of the primary context is not allowed. - static const TContextId KFirst2ndaryCtxIdx(KPrimaryContextId + 1); - TContextId index; - for (index = KFirst2ndaryCtxIdx; index < iBinders.Count(); ++index) - { - CSpudBinderRef*& ref = iBinders[index]; - if (ref == NULL) - { - // Create a binder in this new slot - aContextId = index; - // ref is a reference to a pointer that is owned by Bindman. It will be deleted in the - // destructor. There is no need for CleanupStack. - ref = new (ELeave) CSpudBinderRef(*iSpudMan.BindMan()); - ref->ConstructL(iSpudMan.Notify(), aContextId); - return ref; - } - else if (!ref->IsBound()) - { - // This binder was previously constructed but unbound - ASSERT(ref->Notify() == iSpudMan.Notify()); - aContextId = index; - return ref; - } - } - BINDMAN_LOG(__FLOG_0(_L("CBindMan::GetNewRefForSecondaryL No room for new binder reference"))); - User::Leave(KErrNotSupported); - return NULL; // never reached - } - - - -/** -Creates and returns a pointer to the new binder for the Primary PDP context. -The primary is a special case, because it can be created only once, and it uses a special -ID = 0. If the primary fails then a secondary can be promoted to primary status -even in this case ID = 0 is not re-used because GetNewRefForSecondaryL prevents this. -This means that KPrimaryContextId is only significant once at startup time! - -Ownership remains with BindMan; -DeleteRef() must be called to delete the binder reference object. - -@return the pointer to the binder object for the primary pdp context. -@leave if the construction of the binder leaves. -*/ -CSpudBinderRef* CBindMan::GetNewRefForPrimaryL() - { - CSpudBinderRef*& primRef = iBinders[KPrimaryContextId]; - if(primRef) // We must not try to create the primary more than once. - { - ASSERT(EFalse); - User::Leave(KErrAlreadyExists); // Release builds - } - // primRef is a reference to a pointer that is owned by Bindman. It will be deleted in the - // destructor. There is no need for CleanupStack. - primRef = new (ELeave) CSpudBinderRef(*iSpudMan.BindMan()); - primRef->ConstructL(iSpudMan.Notify(), KPrimaryContextId); - return primRef; - } - - - -/** -Loads a new lower NIF and bind to the binder ref - -@param aName Protocol name desired -@param aBinder the binder to bind the lower NIF into. -@see CNifAgentRef::ServiceStarted() -*/ -void CBindMan::LoadNifL(const TDesC& aName, CSpudBinderRef& aBinder) - { - BINDMAN_LOG(__FLOG_2(_L("CBindMan::LoadNifL loading NIF %S for protocol %S"), &iLowerNifName, &aName)); - - CNifIfLink* lowerNif=static_cast(Nif::CreateInterfaceL(iLowerNifName, aBinder.Notify())); - - // Increment reference count - lowerNif->Open(); - - CleanupClosePushL(*lowerNif); - // Create CNifIfBase and bind it - // Maybe binding should be left to CSpudBinderRef - CNifIfBase* nifBase = lowerNif->GetBinderL(aName); - CleanupStack::Pop(); - - // Increment reference count - nifBase->Open(); - - // Bind the lower NIF into the SPUD - aBinder.Bind(lowerNif, nifBase); - - // Bind the lower NIF to SpudProtocol - nifBase->BindL(iSpudProtocol); - } - - -/** Deletes the dead (marked for deletion) references to lower NIF bindings.. - -@return the number of contexts remaining after the deletion -*/ -TUint CBindMan::SweepBinders() - { - TUint liveContexts(0); - TInt binderIdx; - for(binderIdx = 0; binderIdx < iBinders.Count(); ++binderIdx) // Sift through all the binders - { - if(iBinders[binderIdx] && iBinders[binderIdx]->IsBound()) // Binder exists and is bound to a lower NIF - { - if(ESpudWaitBinderDelete == iBinders[binderIdx]->State()) //Must be deleted - { - BINDMAN_LOG(__FLOG_1(_L("CBindMan::SweepBinders: deleting binder for context[%d]"), binderIdx)); - delete iBinders[binderIdx]; - iBinders[binderIdx] = NULL; - } - else // Binder exists and is bound, but is not eligible for deletion. - { - BINDMAN_LOG(__FLOG_1(_L("CBindMan::SweepBinders: context[%d] is alive."), binderIdx)); - ++liveContexts; - } - } - // Binder is not bound. We don't care. It will be taken care of in the destructor. - } - return liveContexts; - } - -//***************************************************************************** -// CSpudBinderRef -//***************************************************************************** - - -CSpudBinderRef::CSpudBinderRef(CBindMan& aBindMan) - :iBindMan(aBindMan) - { - } - -CSpudBinderRef::~CSpudBinderRef() - { - if (IsBound()) - { - // This call causes the NIF base to delete itself - iNifBase->Close(); - - // This call causes the NIF link to delete itself - iNifLink->Close(); - } - - delete iNotify; - } - -/** -Creates a SpudNotify object. -@leave KErrNoMemory if out of RAM -*/ -void CSpudBinderRef::ConstructL(MNifIfNotify* aNotify, TContextId aContextId) - { - iNotify = new (ELeave) CSpudNotify(iBindMan, aNotify, aContextId); - } +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// SPUD binder manager +// +// + +/** + @file + @internalComponent +*/ + +#include "bindman.h" +#include "spudnotify.h" +#include "mux.h" +#include + +/** Default name of lower NIF */ +_LIT(KDefaultLowerNifName, "rawip"); + +#ifdef __FLOG_ACTIVE +#define BINDMAN_LOG(x) SpudMan()->x +#else +#define BINDMAN_LOG(x) +#endif + +//***************************************************************************** +// CBindMan +//***************************************************************************** + +/** +Constructs BindMan. Ownership of aMux and aProto is transferred to this object. + +@param aSpudMan Reference to SpudMan object +@param aMux Pointer to SpudMux object (ownership is transferred) +@param aProto Pointer to SpudProtocol object (ownership is transferred) +*/ +CBindMan::CBindMan(CSpudMan& aSpudMan, CSpudMux* aMux, CSpudProtocol* aProto) + : iSpudMan(aSpudMan), iMux(aMux), iDeleteMux(ETrue), iSpudProtocol(aProto) + { + ReadLowerNifName(); + } + +CBindMan::~CBindMan() + { + BINDMAN_LOG(__FLOG(_L("BindMan::~BindMan"))); + + #ifdef __FLOG_ACTIVE // Log for diagnostic purposes + TInt idx; + for(idx = 0; idx < iBinders.Count(); ++idx) + { + if(iBinders[idx] && iBinders[idx]->IsBound()) + { + BINDMAN_LOG(__FLOG_1(_L("~BindMan: deleting bound lower NIF binding for context[%d]"), idx)); + } + } + #endif + + iBinders.DeleteAll(); + delete iSpudProtocol; + if (iDeleteMux) + { + delete iMux; + } + } + +/** +Reads the lower NIF name from CommDb. + +@todo This function incorrectly returns the default value when IfParams is of the form: + "notlowernif=UNWANTED,lowernif=IGNORED". + This defect is also present in CPppLcp::InitL. +*/ +void CBindMan::ReadLowerNifName(void) + { + TBuf params; + _LIT(KInterfaceIdentifier,"lowernif="); + const TInt KLinkEqualsLength = 9; // length of "lowernif=" + ASSERT(static_cast(KInterfaceIdentifier).Length() == KLinkEqualsLength); + + // Read IfParams field + iSpudMan.Notify()->ReadDes(TPtrC(ISP_IF_PARAMS), params); + + TInt paramStartMarker = params.Find(KInterfaceIdentifier); + + if (paramStartMarker == KErrNotFound) + { + // "lowernif=" not found in the string - use default lower layer + iLowerNifName = KDefaultLowerNifName; + BINDMAN_LOG(__FLOG_1(_L("Lower NIF name not configured; defaulting to %S"), &iLowerNifName)); + } + else + { + // "lowernif=" found in the string - extract the lower layer Nif name + + if (paramStartMarker > 0 && params[paramStartMarker-1] != ',') + { + // "xyzlowernif=" found rather than "lowernif=" - use default lower layer + iLowerNifName = KDefaultLowerNifName; + BINDMAN_LOG(__FLOG_1(_L("Lower NIF name not configured; defaulting to %S"), &iLowerNifName)); + } + else + { + // String of the form "[...,]lowernif=[,...]" found - extract the Nif name + TPtrC postfix(params.Mid(paramStartMarker + KLinkEqualsLength)); + TInt comma = postfix.Locate(','); + if (comma != KErrNotFound) + { + postfix.Set(postfix.Ptr(), comma); + } + iLowerNifName = postfix; + } + } + } + +/** +Informs CSpudProtocol of the CProtocolBase pointer from the L3 protocol. +*/ +void CBindMan::SetProtocolBaseL(CProtocolBase* aProtocolBase) const + { + iSpudProtocol->SetProtocolBaseL(aProtocolBase); + } + +/** +Returns the binder for the given context ID. +@param aContextId context ID +@return Pointer to binder object +@leave KErrBadHandle or KErrNotReady if context ID is invalid or not found +*/ +CSpudBinderRef* CBindMan::GetRefL(TContextId aContextId) const + { + if (aContextId < 0 || aContextId >= iBinders.Count()) + { + BINDMAN_LOG(__FLOG_1(_L("CBindMan::GetRefL invalid context ID %d"), aContextId)); + User::Leave(KErrBadHandle); + } + CSpudBinderRef* ref = iBinders[aContextId]; + if (ref == NULL) + { + // This situation can frequently occur when looping through all binders + User::Leave(KErrNotReady); + } + return ref; + } + +/** +Returns the binder for any lower NIF that is available and bound. +@return Pointer to binder object +@leave KErrNotReady if no lower NIF is found +*/ +CSpudBinderRef* CBindMan::GetAnyRefL() const + { + TInt index; + for (index=0; index < iBinders.Count(); ++index) + { + CSpudBinderRef* ref = iBinders[index]; + if (ref && ref->IsBound() && ref->State() != ESpudWaitBinderDelete) + { + return ref; + } + } + BINDMAN_LOG(__FLOG_0(_L("CBindMan::GetAnyRefL Can't find any bound NIF"))); + User::Leave(KErrNotReady); + return NULL; // never reached + } + +/** +Returns the context ID the given lower NIF. +@param aNifBase pointer to lower NIF +@return context ID +@leave KErrNotReady if lower NIF is not found +*/ +TContextId CBindMan::FindContextIdL(const CNifIfBase* aNifBase) const + { + TContextId index; + for (index=0; index < iBinders.Count(); ++index) + { + CSpudBinderRef* ref = iBinders[index]; + if (ref && ref->MatchBase(aNifBase)) + { + return index; + } + } + BINDMAN_LOG(__FLOG_1(_L("CBindMan::FindContextIdL Can't find aNifBase %x"), aNifBase)); + User::Leave(KErrNotReady); + return KAllContexts; // never reached + } + +/** +Returns the number of bound contexts. +@return Number of bound contexts +*/ +TUint CBindMan::NumContexts() const + { + TInt index; + TUint count = 0; + for (index=0; index < iBinders.Count(); ++index) + { + CSpudBinderRef* ref = iBinders[index]; + if (ref && ref->IsBound()) + { + ++count; + } + } + return count; + } + +/** +Checks if this is is the last 'valid' context in SPUD, i.e. it is bound and not marked for deletion. + +@param aContextID the ID of the context to check +@return ETrue if and only if aContextId (the subject bindre) is the only valid, bound, unmarked binder. +*/ +TBool CBindMan::IsLastContext(TContextId aContextId)const + { + ASSERT(aContextId >= 0 && NumContexts() > 0); // we shouldn't be called unless we have at least 1 ctx + + TUint numLiveBoundBinders(0); + TBool isTargetBinderFound(EFalse); // The binder for the subject context exists, is bound, and not marked for deletion. + + TInt binderIdx; + for(binderIdx = 0; binderIdx < iBinders.Count(); ++binderIdx) // sift through all the binders + { + if(iBinders[binderIdx] && // binder exists + iBinders[binderIdx]->IsBound() && // is bound + ESpudWaitBinderDelete != iBinders[binderIdx]->State() // not marked for deletion + ) + { + ++numLiveBoundBinders; + + if(binderIdx == aContextId) + { + isTargetBinderFound = ETrue; + } + } + } + ASSERT(isTargetBinderFound); // sanity check: we have a referene to the subject binder, + // and it is 'valid': bound and not marked for deletion. + + if(0 == numLiveBoundBinders) // No valid bound binders remain. + { + ASSERT(EFalse); // spudman thinks it has valid binders, when there are none. + + // In release builds, we can't say that there are more binders, because we have no + // references to them. + return ETrue; // EFalse implies that we have at least 1 binder + } + else if(1 == numLiveBoundBinders) + { + // In release builds: if live binder is not the subject context, we can't claim that the + // subject context is the last one, or SPUD may shutdown when it has a context. + return isTargetBinderFound; // Is there another valid binder beside the subject? + } + else // > 1 + { + // Regardless of whether the subject context was found, we have more. + return EFalse; + } + } + +/** +Creates and returns a pointer to a new binder object. Ownership remains with BindMan; +DeleteRef() must be called to delete the binder reference object. + +@param aContextId Holds the new context ID on return +@return Pointer to binder object +@leave KErrNotSupported if we are out of PDP contexts, or KErrNoMemory if out of RAM +*/ +CSpudBinderRef* CBindMan::GetNewRefForSecondaryL(TContextId& aContextId) + { + // Reusing the slot of the primary context is not allowed. + static const TContextId KFirst2ndaryCtxIdx(KPrimaryContextId + 1); + TContextId index; + for (index = KFirst2ndaryCtxIdx; index < iBinders.Count(); ++index) + { + CSpudBinderRef*& ref = iBinders[index]; + if (ref == NULL) + { + // Create a binder in this new slot + aContextId = index; + // ref is a reference to a pointer that is owned by Bindman. It will be deleted in the + // destructor. There is no need for CleanupStack. + ref = new (ELeave) CSpudBinderRef(*iSpudMan.BindMan()); + ref->ConstructL(iSpudMan.Notify(), aContextId); + return ref; + } + else if (!ref->IsBound()) + { + // This binder was previously constructed but unbound + ASSERT(ref->Notify() == iSpudMan.Notify()); + aContextId = index; + return ref; + } + } + BINDMAN_LOG(__FLOG_0(_L("CBindMan::GetNewRefForSecondaryL No room for new binder reference"))); + User::Leave(KErrNotSupported); + return NULL; // never reached + } + + + +/** +Creates and returns a pointer to the new binder for the Primary PDP context. +The primary is a special case, because it can be created only once, and it uses a special +ID = 0. If the primary fails then a secondary can be promoted to primary status +even in this case ID = 0 is not re-used because GetNewRefForSecondaryL prevents this. +This means that KPrimaryContextId is only significant once at startup time! + +Ownership remains with BindMan; +DeleteRef() must be called to delete the binder reference object. + +@return the pointer to the binder object for the primary pdp context. +@leave if the construction of the binder leaves. +*/ +CSpudBinderRef* CBindMan::GetNewRefForPrimaryL() + { + CSpudBinderRef*& primRef = iBinders[KPrimaryContextId]; + if(primRef) // We must not try to create the primary more than once. + { + ASSERT(EFalse); + User::Leave(KErrAlreadyExists); // Release builds + } + // primRef is a reference to a pointer that is owned by Bindman. It will be deleted in the + // destructor. There is no need for CleanupStack. + primRef = new (ELeave) CSpudBinderRef(*iSpudMan.BindMan()); + primRef->ConstructL(iSpudMan.Notify(), KPrimaryContextId); + return primRef; + } + + + +/** +Loads a new lower NIF and bind to the binder ref + +@param aName Protocol name desired +@param aBinder the binder to bind the lower NIF into. +@see CNifAgentRef::ServiceStarted() +*/ +void CBindMan::LoadNifL(const TDesC& aName, CSpudBinderRef& aBinder) + { + BINDMAN_LOG(__FLOG_2(_L("CBindMan::LoadNifL loading NIF %S for protocol %S"), &iLowerNifName, &aName)); + + CNifIfLink* lowerNif=static_cast(Nif::CreateInterfaceL(iLowerNifName, aBinder.Notify())); + + // Increment reference count + lowerNif->Open(); + + CleanupClosePushL(*lowerNif); + // Create CNifIfBase and bind it + // Maybe binding should be left to CSpudBinderRef + CNifIfBase* nifBase = lowerNif->GetBinderL(aName); + CleanupStack::Pop(); + + // Increment reference count + nifBase->Open(); + + // Bind the lower NIF into the SPUD + aBinder.Bind(lowerNif, nifBase); + + // Bind the lower NIF to SpudProtocol + nifBase->BindL(iSpudProtocol); + } + + +/** Deletes the dead (marked for deletion) references to lower NIF bindings.. + +@return the number of contexts remaining after the deletion +*/ +TUint CBindMan::SweepBinders() + { + TUint liveContexts(0); + TInt binderIdx; + for(binderIdx = 0; binderIdx < iBinders.Count(); ++binderIdx) // Sift through all the binders + { + if(iBinders[binderIdx] && iBinders[binderIdx]->IsBound()) // Binder exists and is bound to a lower NIF + { + if(ESpudWaitBinderDelete == iBinders[binderIdx]->State()) //Must be deleted + { + BINDMAN_LOG(__FLOG_1(_L("CBindMan::SweepBinders: deleting binder for context[%d]"), binderIdx)); + delete iBinders[binderIdx]; + iBinders[binderIdx] = NULL; + } + else // Binder exists and is bound, but is not eligible for deletion. + { + BINDMAN_LOG(__FLOG_1(_L("CBindMan::SweepBinders: context[%d] is alive."), binderIdx)); + ++liveContexts; + } + } + // Binder is not bound. We don't care. It will be taken care of in the destructor. + } + return liveContexts; + } + +//***************************************************************************** +// CSpudBinderRef +//***************************************************************************** + + +CSpudBinderRef::CSpudBinderRef(CBindMan& aBindMan) + :iBindMan(aBindMan) + { + } + +CSpudBinderRef::~CSpudBinderRef() + { + if (IsBound()) + { + // This call causes the NIF base to delete itself + iNifBase->Close(); + + // This call causes the NIF link to delete itself + iNifLink->Close(); + } + + delete iNotify; + } + +/** +Creates a SpudNotify object. +@leave KErrNoMemory if out of RAM +*/ +void CSpudBinderRef::ConstructL(MNifIfNotify* aNotify, TContextId aContextId) + { + iNotify = new (ELeave) CSpudNotify(iBindMan, aNotify, aContextId); + }