24
|
1 |
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
2 |
// All rights reserved.
|
|
3 |
// This component and the accompanying materials are made available
|
|
4 |
// under the terms of "Eclipse Public License v1.0"
|
|
5 |
// which accompanies this distribution, and is available
|
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
7 |
//
|
|
8 |
// Initial Contributors:
|
|
9 |
// Nokia Corporation - initial contribution.
|
|
10 |
//
|
|
11 |
// Contributors:
|
|
12 |
//
|
|
13 |
// Description:
|
|
14 |
//
|
|
15 |
|
|
16 |
#include <es_ini.h>
|
|
17 |
#include <flow.h>
|
|
18 |
|
|
19 |
#include "iface.h"
|
|
20 |
#include "context.h"
|
|
21 |
#include "async_request.h"
|
|
22 |
#include "tc.h"
|
|
23 |
#include "guqos_log.h"
|
|
24 |
#include "guqos.h"
|
|
25 |
|
|
26 |
#ifdef _LOG
|
|
27 |
// Ugly use of function from another module (context.cpp), but this debugging only!
|
|
28 |
extern void LogPacketFilter(const TPacketFilter& aFilter);
|
|
29 |
#endif
|
|
30 |
|
|
31 |
CFlowData* CFlowData::NewL(CFlowContext& aHandle, CNif& aNif, CFlowData *aNext)
|
|
32 |
{
|
|
33 |
CFlowData* flowData = new (ELeave) CFlowData(aHandle, aNif);
|
|
34 |
CleanupStack::PushL(flowData);
|
|
35 |
flowData->ConstructL();
|
|
36 |
CleanupStack::Pop();
|
|
37 |
flowData->iNext = aNext;
|
|
38 |
return flowData;
|
|
39 |
}
|
|
40 |
|
|
41 |
CFlowData* CFlowData::Find(const CFlowContext* aHandle, CFlowData *aList)
|
|
42 |
{
|
|
43 |
while (aList)
|
|
44 |
{
|
|
45 |
if (&aList->iFlowContext == aHandle)
|
|
46 |
break;
|
|
47 |
aList = aList->iNext;
|
|
48 |
}
|
|
49 |
return aList;
|
|
50 |
}
|
|
51 |
|
|
52 |
CFlowData* CFlowData::Remove(const CFlowContext* aHandle, CFlowData **aList)
|
|
53 |
{
|
|
54 |
CFlowData* p = NULL;
|
|
55 |
for ( ; (p = *aList) != NULL; aList = &p->iNext)
|
|
56 |
{
|
|
57 |
if (&p->iFlowContext == aHandle)
|
|
58 |
{
|
|
59 |
*aList = p->iNext;
|
|
60 |
break;
|
|
61 |
}
|
|
62 |
}
|
|
63 |
return p;
|
|
64 |
}
|
|
65 |
|
|
66 |
void CFlowData::SetContext(CPdpContext *aContext)
|
|
67 |
/**
|
|
68 |
* Associate the flow with a new context (or none).
|
|
69 |
*
|
|
70 |
* Move the flow from one context to another. The
|
|
71 |
* internal CClose reuqest is not triggered. (It's
|
|
72 |
* only used in destructor).
|
|
73 |
*
|
|
74 |
* @param aContext The new context (or NULL)
|
|
75 |
*/
|
|
76 |
{
|
|
77 |
if (iContext == aContext)
|
|
78 |
{
|
|
79 |
// Already attache to this context (or NONE) -- nothing to do.
|
|
80 |
return;
|
|
81 |
}
|
|
82 |
|
|
83 |
if (iContext)
|
|
84 |
{
|
|
85 |
// Remove from previous context.
|
|
86 |
iLink.Deque();
|
|
87 |
iContext->FlowDetached();
|
|
88 |
}
|
|
89 |
iContext = aContext;
|
|
90 |
if (iContext)
|
|
91 |
{
|
|
92 |
// Add to new context.
|
|
93 |
iContext->Flows().AddLast(*this);
|
|
94 |
iContext->FlowAttached();
|
|
95 |
}
|
|
96 |
MEventInterface *notifier = Nif().Module().QoSEvent();
|
|
97 |
if (notifier)
|
|
98 |
{
|
|
99 |
// Determine the blocked or unblocked status for the flow
|
|
100 |
// and notify upwards accordingly...
|
|
101 |
|
|
102 |
// Throw away "const". The MEventInterface is misdeclared to
|
|
103 |
// use non-const reference parameter, when const reference
|
|
104 |
// would be the correct way...
|
|
105 |
if (iContext == NULL || iContext->IsFlowBlocked())
|
|
106 |
notifier->BlockFlow((CFlowContext &)iFlowContext);
|
|
107 |
else
|
|
108 |
notifier->UnBlockFlow((CFlowContext &)iFlowContext);
|
|
109 |
}
|
|
110 |
}
|
|
111 |
|
|
112 |
|
|
113 |
CFlowData::CFlowData(CFlowContext& aHandle, CNif& aNif) :
|
|
114 |
iNif(aNif), iFlowContext(aHandle)
|
|
115 |
{
|
|
116 |
|
|
117 |
iContext = NULL;
|
|
118 |
|
|
119 |
// Initialize constant filter values from TPacketHead.
|
|
120 |
const TPacketHead& h = aHandle.iHead;
|
|
121 |
Mem::Copy(iPacketFilter.iSrcAddr, h.ip6.DstAddr().u.iAddr8, sizeof(iPacketFilter.iSrcAddr));
|
|
122 |
Mem::Fill(iPacketFilter.iSrcAddrSubnetMask, sizeof(iPacketFilter.iSrcAddrSubnetMask), 0xFF);
|
|
123 |
iPacketFilter.iProtocolNumberOrNextHeader = h.iProtocol;
|
|
124 |
iPacketFilter.iSrcPortMin = h.iDstPort;
|
|
125 |
iPacketFilter.iSrcPortMax = h.iDstPort;
|
|
126 |
iPacketFilter.iDestPortMin = h.iSrcPort;
|
|
127 |
iPacketFilter.iDestPortMax = h.iSrcPort;
|
|
128 |
iPacketFilter.iTOSorTrafficClass = 0;
|
|
129 |
LOG(Log::Printf(_L("new\tflow[%u] size=%d"), (TInt)this, sizeof(*this)));
|
|
130 |
LOG(LogPacketFilter(iPacketFilter));
|
|
131 |
|
|
132 |
// The filter is for the *INCOMING* traffic! Predicting the values
|
|
133 |
// of the following fields from the *OUTGOING* flow would be
|
|
134 |
// dubious!!
|
|
135 |
|
|
136 |
/* iPacketFilter.iIPSecSPI = ??? */
|
|
137 |
/* iPacketFilter.iTOSorTrafficClass = h.ip6.TrafficClass() ? */
|
|
138 |
/* iPacketFilter.iFlowLabel = h.ip6.FlowLabel() ? */
|
|
139 |
}
|
|
140 |
|
|
141 |
CFlowData::~CFlowData()
|
|
142 |
{
|
|
143 |
if (iContext)
|
|
144 |
{
|
|
145 |
// The flow is still attached to a contex.
|
|
146 |
iLink.Deque();
|
|
147 |
iContext->FlowDetached();
|
|
148 |
}
|
|
149 |
LOG(Log::Printf(_L("~\tflow[%u]"), (TInt)this));
|
|
150 |
}
|
|
151 |
|
|
152 |
void CFlowData::ConstructL()
|
|
153 |
{
|
|
154 |
}
|
|
155 |
|
|
156 |
TInt CFlowData::Send(RMBufChain& aPacket, RMBufSendInfo& aInfo)
|
|
157 |
{
|
|
158 |
// Note: the fact that we are here, means that the CFlowContex in the aInfo
|
|
159 |
// is same as CFlowContext associated with CFlowData. ASSERT is only a
|
|
160 |
// remainder of this and never expect to fire.
|
|
161 |
ASSERT(aInfo.iFlow.FlowContext() == &iFlowContext);
|
|
162 |
if (iContext)
|
|
163 |
{
|
|
164 |
aInfo.iDstAddr.SetPort(iContext->ContextId());
|
|
165 |
// Note: this assumes that the Send below does to come back
|
|
166 |
// and delete structures from under us! If this becomes
|
|
167 |
// possible, then at least CFlowData and possibly CPdpContext
|
|
168 |
// need to be protected against destruction...
|
|
169 |
const TInt ret = aInfo.iFlow.FlowContext()->Send(aPacket);
|
|
170 |
if (ret <= 0)
|
|
171 |
{
|
|
172 |
// Packet accepted, but cannot send any more packets
|
|
173 |
// to this context, until it is unblocked.
|
|
174 |
LOG(Log::Printf(_L("Send\tflow[%u] returns %d, blocking PDP context id = %d"), (TInt)this, ret, iContext->ContextId()));
|
|
175 |
iContext->Block();
|
|
176 |
}
|
|
177 |
}
|
|
178 |
else
|
|
179 |
{
|
|
180 |
LOG(Log::Printf(_L("Send\tflow[%u] has no PDP context -- packet dropped"), (TInt)this));
|
|
181 |
aInfo.iFlow.Close();
|
|
182 |
aPacket.Free();
|
|
183 |
}
|
|
184 |
// Always eat the packet!
|
|
185 |
return 1;
|
|
186 |
}
|
|
187 |
|