diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/gprsumtsqosprt/src/tc.cpp --- /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 +#include + +#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; + } +