telephonyprotocols/gprsumtsqosprt/src/guqos.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/telephonyprotocols/gprsumtsqosprt/src/guqos.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/telephonyprotocols/gprsumtsqosprt/src/guqos.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,529 +1,529 @@
-// Copyright (c) 2007-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 <es_ini.h>
-#include <timeout.h>
-#include <es_prot_internal.h>
-
-#include "guqos.h"
-#include "iface.h"
-#include "tc.h"
-#include "guqos_ini.h"
-#include "context.h"
-#include "async_request.h"
-#include "guqos_log.h"
-
-CModuleGuqos* CModuleGuqos::NewL()
-	{
-	CModuleGuqos* module = new (ELeave) CModuleGuqos();
-	CleanupStack::PushL(module);
-	module->ConstructL();
-	CleanupStack::Pop();
-	return module;
-	}
-
-CModuleGuqos::CModuleGuqos()
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("**** CREATING MODULE GUQOS (size=%u) ****"), sizeof(*this)));
-	iFlowCount = 0;
-	}
-
-void CModuleGuqos::ConstructL()
-	{
-	iIfManager = CNifManager::NewL();
-	iTimeoutManager = TimeoutFactory::NewL(100);	// Time Unit is [1/100 seconds]
-	ReadConfigOptions();
-	}
-
-void CModuleGuqos::ReadConfigOptions()
-	{
-	CESockIniData* config = NULL;
-	TRAP_IGNORE(config = CESockIniData::NewL(GUQOS_INI_DATA));
-	TInt value;
-	if (config == NULL || !config->FindVar(GUQOS_INI_VARIABLES, GUQOS_INI_TIMEOUT, value))
-		value = KPdpContextDeleteTimeout;
-	delete config;
-	iOptions.iTimeout = (value + 9999) / 10000;
-	LOG(Log::Printf(_L("%S = %d [microseconds] converted to %d [1/100 seconds]"), &GUQOS_INI_TIMEOUT, value, iOptions.iTimeout));
-	}
-
-CModuleGuqos::~CModuleGuqos()
-	{
-	LOG(Log::Printf(_L("~\tGUGOS DESTRUCTOR")));
-	ASSERT(iFlowCount == 0);
-	delete iIfManager;
-	delete iTimeoutManager;
-	}
-
-void CModuleGuqos::InterfaceAttached(const TDesC& /*aName*/, CNifIfBase* aIf)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::InterfaceAttached -- start CNifIfBase[%u]"), (TInt)aIf));
-	if (!aIf)
-		return;		// Nothing to attach! (someone is making invalid calls!).
-
-	if (!iIfManager->FindInterface(aIf))
-		{
-		TRAPD(err, iIfManager->CreateNifL(*aIf, *this));
-		if (err != KErrNone)
-			{
-			LOG(Log::Printf(_L("\tError creating Nif [error code = %d]"), err));				
-			}
-		}
-	LOG(Log::Printf(_L("Guqos::InterfaceAttached -- end")));
-	}
-
-void CModuleGuqos::InterfaceDetached(const TDesC& /*aName*/, CNifIfBase* aIf)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::InterfaceDetached -- start")));
-	iIfManager->DeleteNif(aIf);
-	LOG(Log::Printf(_L("Guqos::InterfaceDetached -- end")));
-	}
-
-// references to protocol must be removed, i.e. drop all packets because they contain CFlowContext references
-void CModuleGuqos::Unbind(CProtocolBase* /*aProtocol*/, TUint /*aId = 0*/)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::Unbind -- Nothing to do")));
-	// NOTHING TO īDO FOR NOW
-	// CFlowData may include CFlowContext reference, but those
-	// are never dereferenced, unless the context is otherwise
-	// known to be valid (e.g. in OpenL or is referenced from
-	// RMBufSendInfo. Otherwise the reference is used only as
-	// opaque identifier.
-	}
-
-void CModuleGuqos::InitModuleL(MEventInterface& aEventInterface, CExtension* /*aData*/)
-	{
-	iNotify = &aEventInterface;
-	}
-
-void CModuleGuqos::OpenL(CFlowContext& aFlow, CNifIfBase* aIf)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::OpenL -- start")));
-    CNif* nif = iIfManager->FindInterface(aIf);
-    if (!nif)
-        {
-        User::Leave(KErrNotFound);
-        }
-    CFlowData *flowdata = FindFlow(&aFlow);
-    if (flowdata)
-        {
-        User::Leave(KErrAlreadyExists);
-        }
-
-	// Add new CFlowData to iList (will be the first element in the list)
-	iList = CFlowData::NewL(aFlow, *nif, iList);
-	iFlowCount++;
-      aFlow.iIgnoreFlowControl = ETrue;
-	iList->SetContext(nif->DefaultPdpContext());
-	//aFlow.SetStatus(EFlow_READY);
-    LOG(Log::Printf(_L("Guqos::OpenL -- end")));
-	}
-
-void CModuleGuqos::Close(CFlowContext& aFlow)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::Close -- start")));
-	CFlowData* flowdata = CFlowData::Remove(&aFlow, &iList);
-	if (flowdata)
-		{
-		CPdpContext* context = flowdata->PdpContext();
-		if (context && !context->IsPrimary())
-			{
-			// Schedule a detached CClose request for updating
-			// the TFT filters on secondary context. (Either
-			// the context is flow specific or leave has not
-			// been issued).
-			CClose* request = CClose::New(*context);
-			if (request)
-				{
-				context->Nif().AddRequest(*request);
-				}
-			else
-				{
-				// Note: If the CClose cannot be allocated due to
-				// memory problem, the TFT will remain in effect,
-				// it will automaticly correct itself when there
-				// is another Leave or Close, that can be executed.
-				LOG(Log::Printf(_L("\tCannot schedule TFT filter removal due to out of memory")));
-				}
-			}
-		iFlowCount--;
-		iIfManager->CancelPendingRequests(flowdata);
-		delete flowdata;
-		}
-	LOG(Log::Printf(_L("Guqos::Close -- end")));
-	}
-
-void CModuleGuqos::Release(CFlowContext& aFlow)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::Release -- start")));
-	CFlowData* flowdata = FindFlow(&aFlow);
-	if (!flowdata)
-		return;
-	// Abort any pending actions on the flow
-	iIfManager->CancelPendingRequests(flowdata);
-
-	CPdpContext* context = flowdata->PdpContext();
-	CPdpContext* default_context = flowdata->Nif().DefaultPdpContext();
-	if (context && context != default_context)
-		{
-		// Flow was attached to some other context, shedule some
-		// cleanup for that context.
-		CClose* request = CClose::New(*context);
-		if (request)
-			{
-			context->Nif().AddRequest(*request);
-			}
-		}
-	// Note: this detaches the flow from the old context,
-	// and may trigger destruction of the "context". Do not
-	// reference "context" after this! (the sheduled
-	// request is also cancelled implicitly in such case).
-	flowdata->SetContext(default_context);
-	// Flow will be in blocked state, if default_context does not exist.
-	}
-
-void CModuleGuqos::OpenChannel(TInt aChannelId, const TQoSParameters& aParams, CExtensionPolicy& aPolicy, MQoSNegotiateEvent& aNotify, CFlowContext& aFlow)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::OpenChannel -- start id=%d"), aChannelId));
-	TInt ret = KErrNone; 
-
-	for (;;) /* FOR EXISTS ONLY FOR BREAK EXITS */
-		{
-		if (aChannelId <= 0)
-			{
-			// Channel ID must be > 0
-			ret = KErrArgument;
-			break;
-			}
-		CFlowData *flowdata = FindFlow(&aFlow);
-		if (flowdata == NULL)
-			{
-			ret = KErrNotFound;
-			break;
-			}
-
-		if (IfManager()->FindChannel(aChannelId))
-			{
-			// Note: This could be due to FindChannel finding a channel
-			// which has the delayed destruction and QoS framework is
-			// for some reason reusing the channel id for new channel
-			// (not possible currently, because QoS does not reuse
-			// channel ids).
-			ret = KErrAlreadyExists;
-			break;		
-			}
-
-		// Instead of creating totally new secondary context, there
-		// could be a check for expiring, but not yet deleted contexts,
-		// and reuse one of them for this channel -- that action
-		// would require a different request class, not COpenChannel,
-		// which would renegotiate the channel and recompute it's
-		// filters.
-		// coverity[alloc_fn] coverity[assign] coverity [memory_leak]  	
-		COpenChannel* open_request = COpenChannel::New(aChannelId, *flowdata, &aNotify);
-		if (open_request == NULL)
-			{
-			ret = KErrNoMemory;
-			break;
-			}
-		open_request->SetParameters(aParams, aPolicy);
-		open_request->SetParametersFlowExtn(aPolicy);
-		flowdata->Nif().AddRequest(*open_request);
-		/* TERMINATE FOR LOOP -- OpenChannel success -- request completes asyncronously */
-		LOG(Log::Printf(_L("Guqos::OpenChannel -- end")));
-		return;
-		}
-
-	aNotify.RequestComplete(ret, &aParams);
-	LOG(Log::Printf(_L("Guqos::OpenChannel -- end err=%d"), ret));
-	}
-
-void CModuleGuqos::CloseChannel(TInt aChannelId)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::CloseChannel -- start id=%d"), aChannelId));
-	if (aChannelId <= 0)
-		return;
-	CPdpContext* context = IfManager()->FindChannel(aChannelId);
-	if (!context)
-		return;
-	if (context->IsPrimary())
-		{
-		// This is a secondary context turned into a default context. The use
-		// context as a channel is terminated, but it must continue to live as
-		// a default context. Thus, only remove the channel association from
-		// the context.
-		LOG(Log::Printf(_L("\tTurning secondary context into default only")));
-		context->SetChannelId(0);
-		}
-	else
-		{
-		//?? Need to use CDeleteRequest request to serialize NIF control!!!
-		//?? What happens if this is called in the middle of some request processing?
-		context->Delete();		// Notify NIF, destroy context on NIF.
-		context->Nif().DeletePdpContext(context);
-		}
-	LOG(Log::Printf(_L("Guqos::CloseChannel -- end")));
-	}
-
-void CModuleGuqos::NegotiateChannel(TInt aChannelId, const TQoSParameters& aParams, CExtensionPolicy& aPolicy, MQoSNegotiateEvent& aNotify)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::NegotiateChannel -- start id=%d"), aChannelId));
-	TInt ret = KErrNone;
-
-	if (aChannelId <= 0)
-		{
-		ret = KErrArgument;
-		}
-	else
-		{
-		CPdpContext* context = IfManager()->FindChannel(aChannelId); 
-		if (context == NULL)
-			{
-			ret = KErrNotFound;
-			}
-		else
-			{
-			CNegotiateChannel* request = CNegotiateChannel::New(context, &aNotify);
-			if (request)
-				{
-				//coverity[leave_without_push]
-				request->SetParameters(aParams, aPolicy);
-				//coverity[leave_without_push]
-				request->SetParametersFlowExtn(aPolicy);
-				context->Nif().AddRequest(*request);
-				}
-			else
-				ret = KErrNoMemory;
-			}
-		}
-
-	if (ret != KErrNone)
-		aNotify.RequestComplete(ret, &aParams);
-	LOG(Log::Printf(_L("Guqos::NegotiateChannel -- end res=%d"), ret));
-	}
-
-void CModuleGuqos::Join(TInt aChannelId, CFlowContext& aFlow, MQoSNegotiateEvent& aNotify)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::JoinChannel -- start id=%d"), aChannelId));
-	TInt ret = KErrNone;
-	CPdpContext* channel = IfManager()->FindChannel(aChannelId);
-	CFlowData *flowdata = FindFlow(&aFlow);
-	if (!channel || !flowdata)
-		ret = KErrNotFound;
-	else
-		{
-		CJoinRequest* join_request = CJoinRequest::New(channel, flowdata, &aNotify);
-		if (join_request)
-			channel->Nif().AddRequest(*join_request);
-		else
-			ret = KErrNoMemory;
-		}
-
-	if (ret != KErrNone)
-		aNotify.RequestComplete(ret, NULL);
-	LOG(Log::Printf(_L("Guqos::JoinChannel -- end err=%d"), ret));
-	}
-
-void CModuleGuqos::Leave(TInt aChannelId, CFlowContext& aFlow, MQoSNegotiateEvent& aNotify)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::LeaveChannel -- start id=%d"), aChannelId));
-	TInt ret = KErrNone;
-	CPdpContext* channel = IfManager()->FindChannel(aChannelId);
-	CFlowData *flowdata = FindFlow(&aFlow);
-	if (!channel || !flowdata)
-		ret = KErrNotFound;
-
-	if (ret == KErrNone)
-		{
-		CLeaveRequest* leave_request = CLeaveRequest::New(channel, flowdata, &aNotify);
-		if (leave_request)
-			channel->Nif().AddRequest(*leave_request);
-		else
-			ret = KErrNoMemory;
-		}
-
-	if (ret != KErrNone)
-		aNotify.RequestComplete(ret, NULL);
-	LOG(Log::Printf(_L("Guqos::LeaveChannel -- end ret=%d"), ret));
-	}
-
-void CModuleGuqos::Negotiate(CFlowContext &aFlow, const TQoSParameters& aParams, MQoSNegotiateEvent& aNotify)
-	{
-	LOG(Log::Printf(_L("")));
-	LOG(Log::Printf(_L("Guqos::Negotiate -- start")));
-	TInt ret = KErrNone;
-
-	for (;;) /* FOR EXISTS ONLY FOR BREAK EXITS */
-		{
-		CFlowData* flowdata = FindFlow(&aFlow);
-		if (!flowdata)
-			{
-			ret = KErrNotFound;
-			break;
-			}
-		//?? This needs rework and specification of how things should work!
-		//?? But, for now the assumption is that the Negotiate() is not used in the
-		//?? current framework.
-		
-		// The Negotiate operation does not have the extension policies as parameter,
-		// like OpenChannel or NegotiateChannel has. The code below attempts to fix
-		// this by searching the matching policy. However, only first found is used
-		// (in order Override, Application, Default). This gets murky, if more than
-		// one match would exist -- should extensions be merged in such case?
-		CExtensionPolicy *policy = NULL;
-		if ((policy = (CExtensionPolicy*)iNotify->Lookup(aFlow, EPfqosExtensionPolicy, EPfqosOverridePriority)) == NULL &&
-			(policy = (CExtensionPolicy*)iNotify->Lookup(aFlow, EPfqosExtensionPolicy, EPfqosApplicationPriority)) == NULL &&
-			(policy = (CExtensionPolicy*)iNotify->Lookup(aFlow, EPfqosExtensionPolicy, EPfqosDefaultPriority)) == NULL)
-			{
-			ret = KErrNotFound;
-			break;
-			}
-
-		// Instead of creating totally new context, one could search for
-		// expiring contexts, and reuse one of them for this flow. Could
-		// also prefer a context that has been used for this same flow
-		// previously -- less negotiating, as the filter might already be
-		// correct.
-		COpenChannel* negotiate_request = COpenChannel::New(0, *flowdata, &aNotify);
-		if (negotiate_request == NULL)
-			{
-			ret = KErrNoMemory;
-			break;
-			}
-		//coverity[leave_without_push]
-		negotiate_request->SetParameters(aParams, *policy);
-		//coverity[leave_without_push]
-		negotiate_request->SetParametersFlowExtn(*policy);
-		flowdata->Nif().AddRequest(*negotiate_request);
-		LOG(Log::Printf(_L("Guqos::Negotiate -- end OK")));
-		return;
-		}
-
-	aNotify.RequestComplete(ret, &aParams);
-	LOG(Log::Printf(_L("Guqos::Negotiate -- end ret=%d"), ret));
-	}
-
-TInt CModuleGuqos::Configure(TUint aLevel,TUint aName, TDes8& aOption, TAny* /*aSource*/)
-	{
-	LOG(Log::Printf(_L("guqos::Configure")));
-	if (aLevel == KSOLQoSModule)
-		{
-		switch (aName)
-			{
-		case KSoCapabilities:
-			if (aOption.Length() >= (TInt)sizeof(TInt))
-				{
-				//lint -e{826} complains, pointer conversion is ok
-				TInt& opt = *(TInt*)aOption.Ptr();
-				opt = KModuleCapabilites;
-				return KErrNone;
-				}
-			return KErrArgument;
-		default:
-			break;
-			}
-		}
-	return KErrNotSupported;
-	}
-
-
-TInt CModuleGuqos::Send(RMBufChain& aPacket, CProtocolBase* /*aSourceProtocol*/)
-	{
-	for (;;)	/* FOREVER, ONLY FOR BREAK EXITS */
-		{
-		RMBufSendInfo* const info = RMBufSendPacket::PeekInfoInChain(aPacket);
-		if (!info)
-			{
-			// Malformed packet, cannot do anything with it
-			LOG(Log::Printf(_L("Guqos::Send -- packet has no info block!")));	
-			break;
-			}
-		CFlowContext* const context = info->iFlow.FlowContext();
-		if (!context)
-			{
-			// Malformed packet, cannot do anything with it
-			LOG(Log::Printf(_L("Guqos::Send -- packet has no flow context!")));
-			break;
-			}
-
-		CFlowData* flowdata = FindFlow(context);
-		if (!flowdata)
-			{
-			// Flow is not registered with GUQOS and this Send should
-			// not have happened.
-			info->iFlow.Close();
-			LOG(Log::Printf(_L("Guqos::Send -- flow is not open in GUQOS!")));
-			break;
-			}
-		return flowdata->Send(aPacket, *info);
-		}
-	aPacket.Free();
-	return 1;
-	}
-
-void CModuleGuqos::Identify(TServerProtocolDesc* aProtocolDesc) const
-	{
-	Identify(*aProtocolDesc);
-	}
-
-void CModuleGuqos::Identify(TServerProtocolDesc& aDesc)
-	{
-	_LIT(Kguqos, "quqos");
-
-	aDesc.iName=Kguqos;
-	aDesc.iAddrFamily=KAfInet;
-	aDesc.iSockType=KSockDatagram;
-	aDesc.iProtocol=KModuleGUQoS;
-	aDesc.iVersion=TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
-	aDesc.iByteOrder=EBigEndian;
-	aDesc.iServiceInfo=0;
-	aDesc.iNamingServices=0;
-	aDesc.iSecurity=KSocketNoSecurity;
-	aDesc.iMessageSize=0xffff;
-	aDesc.iServiceTypeInfo=EPreferMBufChains | ENeedMBufs;
-	aDesc.iNumSockets=KUnlimitedSockets;
-	}
-
-
-
-CFlowData* CModuleGuqos::FindFlow(const CFlowContext* aFlow)
-	{
-	return CFlowData::Find(aFlow, iList);
-	}
-
-// Default parameters are fetched from the QoS policy db.
-TInt CModuleGuqos::GetDefaultParameters(TQoSRequested& aParameters, TUint32 aIapId)
-	{
-	TInetAddr addr;
-	addr.SetAddress(KInet6AddrNone);
-	TUidType uid(TUid::Uid(0), TUid::Uid(0), TUid::Uid(0));
-	CExtensionPolicy* sel = (CExtensionPolicy*)iNotify->Lookup(addr, addr, 0, 0, 0, EPfqosExtensionPolicy, uid, aIapId, 0);
-	if (!sel)
-		return KErrNotFound;
-	aParameters.ParsePolicyData(sel);
-	return KErrNone;
-	}
+// Copyright (c) 2007-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 <es_ini.h>
+#include <timeout.h>
+#include <es_prot_internal.h>
+
+#include "guqos.h"
+#include "iface.h"
+#include "tc.h"
+#include "guqos_ini.h"
+#include "context.h"
+#include "async_request.h"
+#include "guqos_log.h"
+
+CModuleGuqos* CModuleGuqos::NewL()
+	{
+	CModuleGuqos* module = new (ELeave) CModuleGuqos();
+	CleanupStack::PushL(module);
+	module->ConstructL();
+	CleanupStack::Pop();
+	return module;
+	}
+
+CModuleGuqos::CModuleGuqos()
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("**** CREATING MODULE GUQOS (size=%u) ****"), sizeof(*this)));
+	iFlowCount = 0;
+	}
+
+void CModuleGuqos::ConstructL()
+	{
+	iIfManager = CNifManager::NewL();
+	iTimeoutManager = TimeoutFactory::NewL(100);	// Time Unit is [1/100 seconds]
+	ReadConfigOptions();
+	}
+
+void CModuleGuqos::ReadConfigOptions()
+	{
+	CESockIniData* config = NULL;
+	TRAP_IGNORE(config = CESockIniData::NewL(GUQOS_INI_DATA));
+	TInt value;
+	if (config == NULL || !config->FindVar(GUQOS_INI_VARIABLES, GUQOS_INI_TIMEOUT, value))
+		value = KPdpContextDeleteTimeout;
+	delete config;
+	iOptions.iTimeout = (value + 9999) / 10000;
+	LOG(Log::Printf(_L("%S = %d [microseconds] converted to %d [1/100 seconds]"), &GUQOS_INI_TIMEOUT, value, iOptions.iTimeout));
+	}
+
+CModuleGuqos::~CModuleGuqos()
+	{
+	LOG(Log::Printf(_L("~\tGUGOS DESTRUCTOR")));
+	ASSERT(iFlowCount == 0);
+	delete iIfManager;
+	delete iTimeoutManager;
+	}
+
+void CModuleGuqos::InterfaceAttached(const TDesC& /*aName*/, CNifIfBase* aIf)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::InterfaceAttached -- start CNifIfBase[%u]"), (TInt)aIf));
+	if (!aIf)
+		return;		// Nothing to attach! (someone is making invalid calls!).
+
+	if (!iIfManager->FindInterface(aIf))
+		{
+		TRAPD(err, iIfManager->CreateNifL(*aIf, *this));
+		if (err != KErrNone)
+			{
+			LOG(Log::Printf(_L("\tError creating Nif [error code = %d]"), err));				
+			}
+		}
+	LOG(Log::Printf(_L("Guqos::InterfaceAttached -- end")));
+	}
+
+void CModuleGuqos::InterfaceDetached(const TDesC& /*aName*/, CNifIfBase* aIf)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::InterfaceDetached -- start")));
+	iIfManager->DeleteNif(aIf);
+	LOG(Log::Printf(_L("Guqos::InterfaceDetached -- end")));
+	}
+
+// references to protocol must be removed, i.e. drop all packets because they contain CFlowContext references
+void CModuleGuqos::Unbind(CProtocolBase* /*aProtocol*/, TUint /*aId = 0*/)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::Unbind -- Nothing to do")));
+	// NOTHING TO īDO FOR NOW
+	// CFlowData may include CFlowContext reference, but those
+	// are never dereferenced, unless the context is otherwise
+	// known to be valid (e.g. in OpenL or is referenced from
+	// RMBufSendInfo. Otherwise the reference is used only as
+	// opaque identifier.
+	}
+
+void CModuleGuqos::InitModuleL(MEventInterface& aEventInterface, CExtension* /*aData*/)
+	{
+	iNotify = &aEventInterface;
+	}
+
+void CModuleGuqos::OpenL(CFlowContext& aFlow, CNifIfBase* aIf)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::OpenL -- start")));
+    CNif* nif = iIfManager->FindInterface(aIf);
+    if (!nif)
+        {
+        User::Leave(KErrNotFound);
+        }
+    CFlowData *flowdata = FindFlow(&aFlow);
+    if (flowdata)
+        {
+        User::Leave(KErrAlreadyExists);
+        }
+
+	// Add new CFlowData to iList (will be the first element in the list)
+	iList = CFlowData::NewL(aFlow, *nif, iList);
+	iFlowCount++;
+      aFlow.iIgnoreFlowControl = ETrue;
+	iList->SetContext(nif->DefaultPdpContext());
+	//aFlow.SetStatus(EFlow_READY);
+    LOG(Log::Printf(_L("Guqos::OpenL -- end")));
+	}
+
+void CModuleGuqos::Close(CFlowContext& aFlow)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::Close -- start")));
+	CFlowData* flowdata = CFlowData::Remove(&aFlow, &iList);
+	if (flowdata)
+		{
+		CPdpContext* context = flowdata->PdpContext();
+		if (context && !context->IsPrimary())
+			{
+			// Schedule a detached CClose request for updating
+			// the TFT filters on secondary context. (Either
+			// the context is flow specific or leave has not
+			// been issued).
+			CClose* request = CClose::New(*context);
+			if (request)
+				{
+				context->Nif().AddRequest(*request);
+				}
+			else
+				{
+				// Note: If the CClose cannot be allocated due to
+				// memory problem, the TFT will remain in effect,
+				// it will automaticly correct itself when there
+				// is another Leave or Close, that can be executed.
+				LOG(Log::Printf(_L("\tCannot schedule TFT filter removal due to out of memory")));
+				}
+			}
+		iFlowCount--;
+		iIfManager->CancelPendingRequests(flowdata);
+		delete flowdata;
+		}
+	LOG(Log::Printf(_L("Guqos::Close -- end")));
+	}
+
+void CModuleGuqos::Release(CFlowContext& aFlow)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::Release -- start")));
+	CFlowData* flowdata = FindFlow(&aFlow);
+	if (!flowdata)
+		return;
+	// Abort any pending actions on the flow
+	iIfManager->CancelPendingRequests(flowdata);
+
+	CPdpContext* context = flowdata->PdpContext();
+	CPdpContext* default_context = flowdata->Nif().DefaultPdpContext();
+	if (context && context != default_context)
+		{
+		// Flow was attached to some other context, shedule some
+		// cleanup for that context.
+		CClose* request = CClose::New(*context);
+		if (request)
+			{
+			context->Nif().AddRequest(*request);
+			}
+		}
+	// Note: this detaches the flow from the old context,
+	// and may trigger destruction of the "context". Do not
+	// reference "context" after this! (the sheduled
+	// request is also cancelled implicitly in such case).
+	flowdata->SetContext(default_context);
+	// Flow will be in blocked state, if default_context does not exist.
+	}
+
+void CModuleGuqos::OpenChannel(TInt aChannelId, const TQoSParameters& aParams, CExtensionPolicy& aPolicy, MQoSNegotiateEvent& aNotify, CFlowContext& aFlow)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::OpenChannel -- start id=%d"), aChannelId));
+	TInt ret = KErrNone; 
+
+	for (;;) /* FOR EXISTS ONLY FOR BREAK EXITS */
+		{
+		if (aChannelId <= 0)
+			{
+			// Channel ID must be > 0
+			ret = KErrArgument;
+			break;
+			}
+		CFlowData *flowdata = FindFlow(&aFlow);
+		if (flowdata == NULL)
+			{
+			ret = KErrNotFound;
+			break;
+			}
+
+		if (IfManager()->FindChannel(aChannelId))
+			{
+			// Note: This could be due to FindChannel finding a channel
+			// which has the delayed destruction and QoS framework is
+			// for some reason reusing the channel id for new channel
+			// (not possible currently, because QoS does not reuse
+			// channel ids).
+			ret = KErrAlreadyExists;
+			break;		
+			}
+
+		// Instead of creating totally new secondary context, there
+		// could be a check for expiring, but not yet deleted contexts,
+		// and reuse one of them for this channel -- that action
+		// would require a different request class, not COpenChannel,
+		// which would renegotiate the channel and recompute it's
+		// filters.
+		// coverity[alloc_fn] coverity[assign] coverity [memory_leak]  	
+		COpenChannel* open_request = COpenChannel::New(aChannelId, *flowdata, &aNotify);
+		if (open_request == NULL)
+			{
+			ret = KErrNoMemory;
+			break;
+			}
+		open_request->SetParameters(aParams, aPolicy);
+		open_request->SetParametersFlowExtn(aPolicy);
+		flowdata->Nif().AddRequest(*open_request);
+		/* TERMINATE FOR LOOP -- OpenChannel success -- request completes asyncronously */
+		LOG(Log::Printf(_L("Guqos::OpenChannel -- end")));
+		return;
+		}
+
+	aNotify.RequestComplete(ret, &aParams);
+	LOG(Log::Printf(_L("Guqos::OpenChannel -- end err=%d"), ret));
+	}
+
+void CModuleGuqos::CloseChannel(TInt aChannelId)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::CloseChannel -- start id=%d"), aChannelId));
+	if (aChannelId <= 0)
+		return;
+	CPdpContext* context = IfManager()->FindChannel(aChannelId);
+	if (!context)
+		return;
+	if (context->IsPrimary())
+		{
+		// This is a secondary context turned into a default context. The use
+		// context as a channel is terminated, but it must continue to live as
+		// a default context. Thus, only remove the channel association from
+		// the context.
+		LOG(Log::Printf(_L("\tTurning secondary context into default only")));
+		context->SetChannelId(0);
+		}
+	else
+		{
+		//?? Need to use CDeleteRequest request to serialize NIF control!!!
+		//?? What happens if this is called in the middle of some request processing?
+		context->Delete();		// Notify NIF, destroy context on NIF.
+		context->Nif().DeletePdpContext(context);
+		}
+	LOG(Log::Printf(_L("Guqos::CloseChannel -- end")));
+	}
+
+void CModuleGuqos::NegotiateChannel(TInt aChannelId, const TQoSParameters& aParams, CExtensionPolicy& aPolicy, MQoSNegotiateEvent& aNotify)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::NegotiateChannel -- start id=%d"), aChannelId));
+	TInt ret = KErrNone;
+
+	if (aChannelId <= 0)
+		{
+		ret = KErrArgument;
+		}
+	else
+		{
+		CPdpContext* context = IfManager()->FindChannel(aChannelId); 
+		if (context == NULL)
+			{
+			ret = KErrNotFound;
+			}
+		else
+			{
+			CNegotiateChannel* request = CNegotiateChannel::New(context, &aNotify);
+			if (request)
+				{
+				//coverity[leave_without_push]
+				request->SetParameters(aParams, aPolicy);
+				//coverity[leave_without_push]
+				request->SetParametersFlowExtn(aPolicy);
+				context->Nif().AddRequest(*request);
+				}
+			else
+				ret = KErrNoMemory;
+			}
+		}
+
+	if (ret != KErrNone)
+		aNotify.RequestComplete(ret, &aParams);
+	LOG(Log::Printf(_L("Guqos::NegotiateChannel -- end res=%d"), ret));
+	}
+
+void CModuleGuqos::Join(TInt aChannelId, CFlowContext& aFlow, MQoSNegotiateEvent& aNotify)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::JoinChannel -- start id=%d"), aChannelId));
+	TInt ret = KErrNone;
+	CPdpContext* channel = IfManager()->FindChannel(aChannelId);
+	CFlowData *flowdata = FindFlow(&aFlow);
+	if (!channel || !flowdata)
+		ret = KErrNotFound;
+	else
+		{
+		CJoinRequest* join_request = CJoinRequest::New(channel, flowdata, &aNotify);
+		if (join_request)
+			channel->Nif().AddRequest(*join_request);
+		else
+			ret = KErrNoMemory;
+		}
+
+	if (ret != KErrNone)
+		aNotify.RequestComplete(ret, NULL);
+	LOG(Log::Printf(_L("Guqos::JoinChannel -- end err=%d"), ret));
+	}
+
+void CModuleGuqos::Leave(TInt aChannelId, CFlowContext& aFlow, MQoSNegotiateEvent& aNotify)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::LeaveChannel -- start id=%d"), aChannelId));
+	TInt ret = KErrNone;
+	CPdpContext* channel = IfManager()->FindChannel(aChannelId);
+	CFlowData *flowdata = FindFlow(&aFlow);
+	if (!channel || !flowdata)
+		ret = KErrNotFound;
+
+	if (ret == KErrNone)
+		{
+		CLeaveRequest* leave_request = CLeaveRequest::New(channel, flowdata, &aNotify);
+		if (leave_request)
+			channel->Nif().AddRequest(*leave_request);
+		else
+			ret = KErrNoMemory;
+		}
+
+	if (ret != KErrNone)
+		aNotify.RequestComplete(ret, NULL);
+	LOG(Log::Printf(_L("Guqos::LeaveChannel -- end ret=%d"), ret));
+	}
+
+void CModuleGuqos::Negotiate(CFlowContext &aFlow, const TQoSParameters& aParams, MQoSNegotiateEvent& aNotify)
+	{
+	LOG(Log::Printf(_L("")));
+	LOG(Log::Printf(_L("Guqos::Negotiate -- start")));
+	TInt ret = KErrNone;
+
+	for (;;) /* FOR EXISTS ONLY FOR BREAK EXITS */
+		{
+		CFlowData* flowdata = FindFlow(&aFlow);
+		if (!flowdata)
+			{
+			ret = KErrNotFound;
+			break;
+			}
+		//?? This needs rework and specification of how things should work!
+		//?? But, for now the assumption is that the Negotiate() is not used in the
+		//?? current framework.
+		
+		// The Negotiate operation does not have the extension policies as parameter,
+		// like OpenChannel or NegotiateChannel has. The code below attempts to fix
+		// this by searching the matching policy. However, only first found is used
+		// (in order Override, Application, Default). This gets murky, if more than
+		// one match would exist -- should extensions be merged in such case?
+		CExtensionPolicy *policy = NULL;
+		if ((policy = (CExtensionPolicy*)iNotify->Lookup(aFlow, EPfqosExtensionPolicy, EPfqosOverridePriority)) == NULL &&
+			(policy = (CExtensionPolicy*)iNotify->Lookup(aFlow, EPfqosExtensionPolicy, EPfqosApplicationPriority)) == NULL &&
+			(policy = (CExtensionPolicy*)iNotify->Lookup(aFlow, EPfqosExtensionPolicy, EPfqosDefaultPriority)) == NULL)
+			{
+			ret = KErrNotFound;
+			break;
+			}
+
+		// Instead of creating totally new context, one could search for
+		// expiring contexts, and reuse one of them for this flow. Could
+		// also prefer a context that has been used for this same flow
+		// previously -- less negotiating, as the filter might already be
+		// correct.
+		COpenChannel* negotiate_request = COpenChannel::New(0, *flowdata, &aNotify);
+		if (negotiate_request == NULL)
+			{
+			ret = KErrNoMemory;
+			break;
+			}
+		//coverity[leave_without_push]
+		negotiate_request->SetParameters(aParams, *policy);
+		//coverity[leave_without_push]
+		negotiate_request->SetParametersFlowExtn(*policy);
+		flowdata->Nif().AddRequest(*negotiate_request);
+		LOG(Log::Printf(_L("Guqos::Negotiate -- end OK")));
+		return;
+		}
+
+	aNotify.RequestComplete(ret, &aParams);
+	LOG(Log::Printf(_L("Guqos::Negotiate -- end ret=%d"), ret));
+	}
+
+TInt CModuleGuqos::Configure(TUint aLevel,TUint aName, TDes8& aOption, TAny* /*aSource*/)
+	{
+	LOG(Log::Printf(_L("guqos::Configure")));
+	if (aLevel == KSOLQoSModule)
+		{
+		switch (aName)
+			{
+		case KSoCapabilities:
+			if (aOption.Length() >= (TInt)sizeof(TInt))
+				{
+				//lint -e{826} complains, pointer conversion is ok
+				TInt& opt = *(TInt*)aOption.Ptr();
+				opt = KModuleCapabilites;
+				return KErrNone;
+				}
+			return KErrArgument;
+		default:
+			break;
+			}
+		}
+	return KErrNotSupported;
+	}
+
+
+TInt CModuleGuqos::Send(RMBufChain& aPacket, CProtocolBase* /*aSourceProtocol*/)
+	{
+	for (;;)	/* FOREVER, ONLY FOR BREAK EXITS */
+		{
+		RMBufSendInfo* const info = RMBufSendPacket::PeekInfoInChain(aPacket);
+		if (!info)
+			{
+			// Malformed packet, cannot do anything with it
+			LOG(Log::Printf(_L("Guqos::Send -- packet has no info block!")));	
+			break;
+			}
+		CFlowContext* const context = info->iFlow.FlowContext();
+		if (!context)
+			{
+			// Malformed packet, cannot do anything with it
+			LOG(Log::Printf(_L("Guqos::Send -- packet has no flow context!")));
+			break;
+			}
+
+		CFlowData* flowdata = FindFlow(context);
+		if (!flowdata)
+			{
+			// Flow is not registered with GUQOS and this Send should
+			// not have happened.
+			info->iFlow.Close();
+			LOG(Log::Printf(_L("Guqos::Send -- flow is not open in GUQOS!")));
+			break;
+			}
+		return flowdata->Send(aPacket, *info);
+		}
+	aPacket.Free();
+	return 1;
+	}
+
+void CModuleGuqos::Identify(TServerProtocolDesc* aProtocolDesc) const
+	{
+	Identify(*aProtocolDesc);
+	}
+
+void CModuleGuqos::Identify(TServerProtocolDesc& aDesc)
+	{
+	_LIT(Kguqos, "quqos");
+
+	aDesc.iName=Kguqos;
+	aDesc.iAddrFamily=KAfInet;
+	aDesc.iSockType=KSockDatagram;
+	aDesc.iProtocol=KModuleGUQoS;
+	aDesc.iVersion=TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
+	aDesc.iByteOrder=EBigEndian;
+	aDesc.iServiceInfo=0;
+	aDesc.iNamingServices=0;
+	aDesc.iSecurity=KSocketNoSecurity;
+	aDesc.iMessageSize=0xffff;
+	aDesc.iServiceTypeInfo=EPreferMBufChains | ENeedMBufs;
+	aDesc.iNumSockets=KUnlimitedSockets;
+	}
+
+
+
+CFlowData* CModuleGuqos::FindFlow(const CFlowContext* aFlow)
+	{
+	return CFlowData::Find(aFlow, iList);
+	}
+
+// Default parameters are fetched from the QoS policy db.
+TInt CModuleGuqos::GetDefaultParameters(TQoSRequested& aParameters, TUint32 aIapId)
+	{
+	TInetAddr addr;
+	addr.SetAddress(KInet6AddrNone);
+	TUidType uid(TUid::Uid(0), TUid::Uid(0), TUid::Uid(0));
+	CExtensionPolicy* sel = (CExtensionPolicy*)iNotify->Lookup(addr, addr, 0, 0, 0, EPfqosExtensionPolicy, uid, aIapId, 0);
+	if (!sel)
+		return KErrNotFound;
+	aParameters.ParsePolicyData(sel);
+	return KErrNone;
+	}