--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkcontrol/qosfwconfig/qos/src/modules.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,222 @@
+// Copyright (c) 2006-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:
+//
+
+#include "qos_prot.h"
+#include "policies.h"
+#include "modules.h"
+
+// CModuleData
+CModuleData* CModuleData::NewLC(const TDesC& aModuleName, TUint aProtocolId, TUint aTimeoutDelay, TDblQue<CModuleData>& aList)
+ {
+ LOG(Log::Printf(_L("NewL\tqos module[%S] prot=%u delay=%u"), &aModuleName, aProtocolId, aTimeoutDelay));
+
+ CModuleData* module = new (ELeave) CModuleData(aProtocolId, aTimeoutDelay);
+
+ LOG(module->iName = aModuleName.Left(module->iName.MaxLength() < aModuleName.Length() ? module->iName.MaxLength() : aModuleName.Length()));
+
+ aList.AddLast(*module);
+ // Although the "module" is already recorded into the aList, the address is
+ // still pushed into the cleanup stack. The destructor of the CModuleData
+ // always removes the object the list, and if any of the following initializations
+ // (including those in the caller of this method) fail, the half initialized
+ // object will get destroyed (and not left in the list!).
+ CleanupStack::PushL(module);
+ module->ConstructL(aModuleName);
+ return module;
+ }
+
+void CModuleData::ConstructL(const TDesC& aModuleName)
+ {
+ TCallBack callback(WatchDogCallBack, this);
+ iTimeout = CModuleTimeout::NewL(callback);
+
+ User::LeaveIfError(iLib.Load(aModuleName));
+ TProtocolNew entry = (TProtocolNew)iLib.Lookup(1);
+ if (!entry)
+ User::Leave(KErrNoMemory);
+
+ // Each module must be implemented as PRT module. One PRT
+ // can contain one module (= protocol).
+ // [Because the family and "protocol"
+ // are created and deleted as a pair here].
+ iFamily = (*entry)();
+ if (!iFamily)
+ User::Leave(KErrBadLibraryEntryPoint);
+ iFamily->Install();
+
+ iModule = (CModuleBase*)iFamily->NewProtocolL(KSockDatagram, iProtocolId);
+ if (!iModule)
+ User::LeaveIfError(KErrNotSupported);
+
+ // Get the module capabilities from the module
+ TInt flags=0;
+ TPckg<TInt> option(flags);
+ TInt ret = iModule->Configure(KSOLQoSModule, KSoCapabilities, option);
+ if (ret == KErrNone)
+ iFlags = flags;
+ }
+
+CModuleData::CModuleData(TUint aProtocolId, TUint aTimeoutDelay)
+ {
+ iTimeoutDelay = aTimeoutDelay;
+ iProtocolId = aProtocolId;
+ iModule = NULL;
+ iFamily = NULL;
+ iRefCount = 0;
+ iFlags = 0;
+ }
+
+CModuleData::~CModuleData()
+ {
+ LOG(Log::Printf(_L("~\tqos module[%S] destructor -- start"), &iName));
+ ASSERT(iRefCount == 0); // Reference count MUST BE ZERO at this point!
+ iLink.Deque(); // Remove from CModuleManager::iModuleList!
+ delete iTimeout; // ...cancels also the timer, if active.
+ delete iModule;
+ delete iFamily;
+ iLib.Close();
+ LOG(Log::Printf(_L("~\tqos module[%S] destructor -- end"), &iName));
+ }
+
+void CModuleData::Close()
+ {
+ ASSERT(iRefCount > 0);
+ if (--iRefCount <= 0)
+ {
+ LOG(Log::Printf(_L("\tqos module[%S] StartWatchdog"), &iName));
+ StartWatchDog();
+ }
+ }
+
+TInt CModuleData::WatchDogCallBack(TAny* aProvider)
+ {
+ CModuleData* module = (CModuleData*)aProvider;
+ LOG(Log::Printf(_L("<>\tqos module[%S] WatchDogCallback -- iRefCount=%d"), &module->iName, module->iRefCount));
+ if (module->iRefCount<=0)
+ {
+ // No references have appeared while waiting -- delete object
+ delete module;
+ }
+ return KErrNone;
+ }
+
+
+// CModuleManager
+CModuleManager* CModuleManager::NewL(CProtocolQoS& aProtocol)
+ {
+ return new (ELeave) CModuleManager(aProtocol);
+ }
+
+
+CModuleManager::CModuleManager(CProtocolQoS& aProtocol) : iProtocol(aProtocol)
+ {
+ LOG(Log::Printf(_L("new\tqos Module Manager[%u] size=%d"), (TInt)this, sizeof(CModuleManager)));
+ iModuleList.SetOffset(_FOFF(CModuleData, iLink));
+ }
+
+CModuleManager::~CModuleManager()
+ {
+ // UnloadAllModules();
+ while (!iModuleList.IsEmpty())
+ {
+ CModuleData* module = iModuleList.First();
+ delete module; // ~CModuleData() deques the object from the iModuleList
+ }
+ LOG(Log::Printf(_L("~\tqos Module Manager[%u] deleted"), (TInt)this));
+ }
+
+
+RModule* CModuleManager::LoadModuleL(CModuleSpec& aModuleSpec, CProtocolBase* aIpProtocol)
+ {
+ return LoadModuleL(aIpProtocol, aModuleSpec.FileName(), aModuleSpec.ProtocolId(), aModuleSpec.PolicyData());
+ }
+
+
+RModule* CModuleManager::LoadModuleL(CProtocolBase* aIpProtocol, const TDesC& aModuleName, TUint aProtocolId, CExtension* aData)
+ {
+ TInt pops = 0;
+ // ??? If a Lookup finds an existing object, does it matter if it was
+ // ??? created with different value for aData (CExtension *) ?
+ // ??? (Note: GUQOS currently ignores that parameter, and thus not a problem YET!)
+ CModuleData* info = Lookup(aProtocolId);
+ if (!info)
+ {
+ info = CModuleData::NewLC(aModuleName, aProtocolId, Protocol().ConfigOptions().iUnloadDelay, iModuleList);
+ ++pops;
+ info->iModule->BindToIP6L(aIpProtocol);
+ info->iModule->InitModuleL(Protocol(), aData);
+ }
+ RModule *module = new (ELeave) RModule(*info);
+ // Note: Having the "Pop" here solves the case where CModuleData contruction is complete, but
+ // the RModule allocation leaves. This prevents the case where the iModuleList contains object
+ // with iRefCount == 0, but no timer running => it would not get deleted until module manager dies or
+ // some reference is added and removed.
+ CleanupStack::Pop(pops);
+ return module;
+ }
+
+RModule* CModuleManager::OpenModuleL(TUint aProtocolId)
+ {
+ RModule* module=NULL;
+ CModuleData* moduleData = Lookup(aProtocolId);
+ if (moduleData)
+ module = new (ELeave) RModule(*moduleData);
+ return module;
+ }
+
+
+TBool CModuleManager::IsLoaded(TUint aProtocolId)
+ {
+ return (Lookup(aProtocolId) == NULL) ? EFalse : ETrue;
+ }
+
+void CModuleManager::Unbind(CProtocolBase* aProtocol, TInt aId)
+ {
+ TDblQueIter<CModuleData> iter(iModuleList);
+ CModuleData* module;
+ while ((module = iter++) != NULL)
+ module->iModule->Unbind(aProtocol, aId);
+ }
+
+
+CModuleData* CModuleManager::Lookup(TUint aProtocolId)
+ {
+ TDblQueIter<CModuleData> iter(iModuleList);
+ CModuleData* moduleData;
+
+ while ((moduleData = iter++) != NULL)
+ {
+ if (moduleData->iProtocolId == aProtocolId)
+ return moduleData;
+ }
+ return NULL;
+ }
+
+// RModule
+RModule::RModule(CModuleData& aModuleData) : iModuleData(aModuleData)
+ {
+ iModuleData.Open();
+ }
+
+RModule::RModule(const RModule& aModule) : iModuleData(aModule.iModuleData)
+ {
+ iModuleData.Open();
+ }
+
+RModule::~RModule()
+ {
+ iModuleData.Close();
+ }
+