telephonyprotocols/gprsumtsqosprt/src/tc.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyprotocols/gprsumtsqosprt/src/tc.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,187 @@
+// 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 <flow.h>
+
+#include "iface.h"
+#include "context.h"
+#include "async_request.h"
+#include "tc.h"
+#include "guqos_log.h"
+#include "guqos.h"
+
+#ifdef _LOG
+// Ugly use of function from another module (context.cpp), but this debugging only!
+extern void LogPacketFilter(const TPacketFilter& aFilter);
+#endif
+
+CFlowData* CFlowData::NewL(CFlowContext& aHandle, CNif& aNif, CFlowData *aNext)
+	{
+	CFlowData* flowData = new (ELeave) CFlowData(aHandle, aNif);
+	CleanupStack::PushL(flowData);
+	flowData->ConstructL();
+	CleanupStack::Pop();
+	flowData->iNext = aNext;
+	return flowData;
+	}
+
+CFlowData* CFlowData::Find(const CFlowContext* aHandle, CFlowData *aList)
+	{
+	while (aList)
+		{
+		if (&aList->iFlowContext == aHandle)
+			break;
+		aList = aList->iNext;
+		}
+	return aList;
+	}
+
+CFlowData* CFlowData::Remove(const CFlowContext* aHandle, CFlowData **aList)
+	{
+	CFlowData* p = NULL;
+	for ( ; (p = *aList) != NULL; aList = &p->iNext)
+		{
+		if (&p->iFlowContext == aHandle)
+			{
+			*aList = p->iNext;
+			break;
+			}
+		}
+	return p;
+	}
+
+void CFlowData::SetContext(CPdpContext *aContext)
+	/**
+	* Associate the flow with a new context (or none).
+	*
+	* Move the flow from one context to another. The
+	* internal CClose reuqest is not triggered. (It's
+	* only used in destructor).
+	*
+	* @param aContext The new context (or NULL)
+	*/
+	{
+	if (iContext == aContext)
+		{
+		// Already attache to this context (or NONE) -- nothing to do.
+		return;
+		}
+
+	if (iContext)
+		{
+		// Remove from previous context.
+		iLink.Deque();
+		iContext->FlowDetached();
+		}
+	iContext = aContext;
+	if (iContext)
+		{
+		// Add to new context.
+		iContext->Flows().AddLast(*this);
+		iContext->FlowAttached();
+		}
+	MEventInterface *notifier = Nif().Module().QoSEvent();
+	if (notifier)
+		{
+		// Determine the blocked or unblocked status for the flow
+		// and notify upwards accordingly...
+
+		// Throw away "const". The MEventInterface is misdeclared to
+		// use non-const reference parameter, when const reference
+		// would be the correct way...
+		if (iContext == NULL || iContext->IsFlowBlocked())
+			notifier->BlockFlow((CFlowContext &)iFlowContext);
+		else
+			notifier->UnBlockFlow((CFlowContext &)iFlowContext);
+		}
+	}
+
+
+CFlowData::CFlowData(CFlowContext& aHandle, CNif& aNif) : 
+	iNif(aNif), iFlowContext(aHandle)
+	{
+	
+	iContext = NULL;
+
+	// Initialize constant filter values from TPacketHead.
+	const TPacketHead& h = aHandle.iHead;
+	Mem::Copy(iPacketFilter.iSrcAddr, h.ip6.DstAddr().u.iAddr8, sizeof(iPacketFilter.iSrcAddr));
+	Mem::Fill(iPacketFilter.iSrcAddrSubnetMask, sizeof(iPacketFilter.iSrcAddrSubnetMask), 0xFF);
+	iPacketFilter.iProtocolNumberOrNextHeader = h.iProtocol;
+	iPacketFilter.iSrcPortMin = h.iDstPort;
+	iPacketFilter.iSrcPortMax = h.iDstPort;
+	iPacketFilter.iDestPortMin = h.iSrcPort;
+	iPacketFilter.iDestPortMax = h.iSrcPort;
+	iPacketFilter.iTOSorTrafficClass = 0;
+	LOG(Log::Printf(_L("new\tflow[%u] size=%d"), (TInt)this, sizeof(*this)));
+	LOG(LogPacketFilter(iPacketFilter));
+
+	// The filter is for the *INCOMING* traffic! Predicting the values
+	// of the following fields from the *OUTGOING* flow would be
+	// dubious!!
+
+	/* iPacketFilter.iIPSecSPI = ??? */
+	/* iPacketFilter.iTOSorTrafficClass = h.ip6.TrafficClass() ? */
+	/* iPacketFilter.iFlowLabel = h.ip6.FlowLabel() ? */
+	}
+
+CFlowData::~CFlowData()
+	{
+	if (iContext)
+		{
+		// The flow is still attached to a contex.
+		iLink.Deque();
+		iContext->FlowDetached();
+		}
+	LOG(Log::Printf(_L("~\tflow[%u]"), (TInt)this));
+	}
+
+void CFlowData::ConstructL()
+	{
+	}
+
+TInt CFlowData::Send(RMBufChain& aPacket, RMBufSendInfo& aInfo)
+	{
+	// Note: the fact that we are here, means that the CFlowContex in the aInfo
+	// is same as CFlowContext associated with CFlowData. ASSERT is only a
+	// remainder of this and never expect to fire.
+	ASSERT(aInfo.iFlow.FlowContext() == &iFlowContext);
+	if (iContext)
+		{
+		aInfo.iDstAddr.SetPort(iContext->ContextId());
+		// Note: this assumes that the Send below does to come back
+		// and delete structures from under us! If this becomes
+		// possible, then at least CFlowData and possibly CPdpContext
+		// need to be protected against destruction...
+		const TInt ret = aInfo.iFlow.FlowContext()->Send(aPacket);
+		if (ret <= 0)
+			{
+			// Packet accepted, but cannot send any more packets
+			// to this context, until it is unblocked.
+			LOG(Log::Printf(_L("Send\tflow[%u] returns %d, blocking PDP context id = %d"), (TInt)this, ret, iContext->ContextId()));
+			iContext->Block();
+			}
+		}
+	else
+		{
+		LOG(Log::Printf(_L("Send\tflow[%u] has no PDP context -- packet dropped"), (TInt)this));
+		aInfo.iFlow.Close();
+		aPacket.Free();
+		}
+	// Always eat the packet!
+	return 1;
+	}
+