// 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);#endifCFlowData* 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; }