--- /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;
+ }
+