|
1 // Copyright (c) 2006-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 // in_net.cpp - network layer protocol |
|
15 // |
|
16 |
|
17 #include "in6_if.h" |
|
18 #include "inet.h" |
|
19 #include "in_net.h" |
|
20 #include "tcpip_ini.h" |
|
21 #include "inet6log.h" |
|
22 |
|
23 void CProtocolInet6Network::StartL() |
|
24 { |
|
25 CProtocolInet6Base::StartL(); |
|
26 // |
|
27 // Get the default value for the provider receive queue limiter |
|
28 // (use the protocol name as section name) |
|
29 TServerProtocolDesc info; |
|
30 Identify(&info); |
|
31 TInt value; |
|
32 if (iNetwork->Interfacer()->FindVar(info.iName, TCPIP_INI_RECV_BUF, value)) |
|
33 iQueueLimit = value; |
|
34 else |
|
35 iQueueLimit = KNetDefaultRecvBuf; |
|
36 } |
|
37 |
|
38 |
|
39 CProtocolInet6Network::~CProtocolInet6Network() |
|
40 { |
|
41 } |
|
42 |
|
43 // |
|
44 // CProtocolInet6Network::Deliver |
|
45 // ****************************** |
|
46 // Generate a copy of the packet to every bound provider |
|
47 // |
|
48 void CProtocolInet6Network::Deliver(/*const*/ RMBufPacketBase &aPacket) |
|
49 // .. cannot use "const", because CopyInfoL is not const! -- msa */ |
|
50 { |
|
51 CProviderInet6Network* provider; |
|
52 TInet6SAPIter iter(this); |
|
53 |
|
54 const RMBufPktInfo *const info = aPacket.Info(); |
|
55 while (provider = (CProviderInet6Network *)iter++, provider != NULL) |
|
56 { |
|
57 if (provider->IsReceiving(*info)) |
|
58 { |
|
59 RMBufRecvPacket copy; |
|
60 TRAPD(err, aPacket.CopyL(copy);aPacket.CopyInfoL(copy)); |
|
61 if (err == KErrNone) |
|
62 { |
|
63 copy.Pack(); |
|
64 provider->Process(copy); |
|
65 } |
|
66 else |
|
67 copy.Free(); |
|
68 } |
|
69 } |
|
70 } |
|
71 |
|
72 // |
|
73 // Shared provider methods (defaults) |
|
74 // |
|
75 CProviderInet6Network::~CProviderInet6Network() |
|
76 { |
|
77 iProtocol->UnbindProvider(this); |
|
78 iRecvQ.Free(); |
|
79 } |
|
80 |
|
81 |
|
82 void CProviderInet6Network::InitL() |
|
83 { |
|
84 // |
|
85 // Set initial value for the iQueueLimit |
|
86 // |
|
87 iQueueLimit = ((CProtocolInet6Network*)iProtocol)->QueueLimit(); |
|
88 CProviderInet6Base::InitL(); |
|
89 iProtocol->UnbindProvider(this); |
|
90 iProtocol->BindProvider(this); |
|
91 } |
|
92 |
|
93 TInt CProviderInet6Network::SetLocalName(TSockAddr &aAddr) |
|
94 { |
|
95 iProtocol->UnbindProvider(this); |
|
96 // Note: a non-zero port in aAddr is significant! |
|
97 iFlow.SetLocalAddr(aAddr); |
|
98 iProtocol->BindProvider(this); |
|
99 return 0; |
|
100 } |
|
101 |
|
102 void CProviderInet6Network::AutoBind() |
|
103 { |
|
104 // TInetAddr() is assumed to be KAFUnspec & port=0 |
|
105 iFlow.SetLocalAddr(TInetAddr()); |
|
106 } |
|
107 |
|
108 |
|
109 void CProviderInet6Network::Shutdown(TCloseType aOption) |
|
110 { |
|
111 |
|
112 switch(aOption) |
|
113 { |
|
114 case EStopInput: |
|
115 iInputStopped = 1; |
|
116 iProtocol->UnbindProvider(this); // We don't need any incoming data |
|
117 iRecvQ.Free(); |
|
118 iSocket->Error(KErrNone,MSocketNotify::EErrorClose); // Complete KErrNone |
|
119 // Nif::SetSocketState(ENifSocketConnected, this); // Reset CSocket state to ESStateConnected |
|
120 break; |
|
121 |
|
122 case EStopOutput: |
|
123 iSocket->Error(KErrNone,MSocketNotify::EErrorClose); // Complete KErrNone |
|
124 // Nif::SetSocketState(ENifSocketConnected, this); // Reset CSocket state to ESStateConnected |
|
125 break; |
|
126 |
|
127 default: |
|
128 iProtocol->UnbindProvider(this); |
|
129 if (aOption!=EImmediate) |
|
130 iSocket->CanClose(); |
|
131 } |
|
132 } |
|
133 |
|
134 // |
|
135 // CProviderInet6Network::Process() |
|
136 // ******************************** |
|
137 // Process incoming data from the protocol object. |
|
138 // |
|
139 void CProviderInet6Network::Process(RMBufChain& aPacket, CProtocolBase * /*aSourceProtocol*/) |
|
140 { |
|
141 // iInputStopped is set at ShutDown() and no packets should be coming |
|
142 // from the protocol after that. However, without knowing the exact |
|
143 // details of the process model/threads, it could be possible that |
|
144 // a Process() call has been initiated by the protocol and interrupted |
|
145 // before the shutdown, thus there may be a need for this iInputStopped |
|
146 // flag, although I would prefer to do without... NEED TO VERIFY IF |
|
147 // iInputStopped is really needed!!! -- msa |
|
148 // |
|
149 if(!(iInputStopped || |
|
150 (iErrorMask & (MSocketNotify::EErrorFatal|MSocketNotify::EErrorConnect|MSocketNotify::EErrorRecv)))) |
|
151 { |
|
152 iQueueLimit -= RMBufPacketBase::PeekInfoInChain(aPacket)->iLength; |
|
153 iRecvQ.Append(aPacket); |
|
154 LOG(Log::Printf(_L("\t%S SAP[%u] Packet Queued, calling NewData(1), limit=%d"), &ProtocolName(), (TInt)this, iQueueLimit)); |
|
155 iSocket->NewData(1); |
|
156 } |
|
157 else |
|
158 { |
|
159 LOG(Log::Printf(_L("\t%S SAP[%u] Packet Dropped"), &ProtocolName(), (TInt)this)); |
|
160 aPacket.Free(); |
|
161 } |
|
162 } |
|
163 |
|
164 // CProviderInet6Network::IsReceiving |
|
165 // ********************************** |
|
166 // |
|
167 TBool CProviderInet6Network::IsReceiving(const RMBufPktInfo &aInfo) |
|
168 { |
|
169 if (!HasNetworkServices() && (aInfo.iFlags & KIpLoopbackPacket) == 0) |
|
170 return FALSE; // No network services and packet is external. |
|
171 const TInt port = iFlow.FlowContext()->LocalPort(); |
|
172 |
|
173 if (iQueueLimit < 0) |
|
174 { |
|
175 // Receive Queue limit is full, cannot receive this packet |
|
176 |
|
177 LOG(Log::Printf(_L("\t%S SAP[%u] Not receiving packets, limit=%d"), &ProtocolName(), (TInt)this, iQueueLimit)); |
|
178 iPacketsDropped++; |
|
179 return FALSE; |
|
180 } |
|
181 return port == 0 || port == aInfo.iProtocol; |
|
182 } |
|
183 |
|
184 |
|
185 // CProviderInet6Network::GetData |
|
186 // ****************************** |
|
187 |
|
188 TInt CProviderInet6Network::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* aAddr) |
|
189 { |
|
190 RMBufRecvPacket packet; |
|
191 const RMBufRecvInfo *info; |
|
192 if (!iRecvQ.Remove(packet)) |
|
193 { |
|
194 LOG(Log::Printf(_L("GetData\t%S SAP[%u] No Data Available (0)"), &ProtocolName(), (TInt)this)); |
|
195 return 0; // No Data Available |
|
196 } |
|
197 |
|
198 info = packet.Unpack(); |
|
199 |
|
200 if (aAddr != NULL) |
|
201 *aAddr = info->iSrcAddr; |
|
202 |
|
203 #ifdef _LOG |
|
204 TBuf<70> tmp(_L("NULL")); |
|
205 if (aAddr) |
|
206 TInetAddr::Cast(*aAddr).OutputWithScope(tmp); |
|
207 #endif |
|
208 const TInt offset = ((aOptions & KIpHeaderIncluded) != 0 || iRawMode) ? 0 : info->iOffset; |
|
209 |
|
210 if (aOptions & KSockReadPeek) |
|
211 { |
|
212 // |
|
213 // Oops, peek needs to keep the original packet intact in the queue |
|
214 // |
|
215 TInt len = info->iLength - offset; |
|
216 if (len > (TInt)aLength) |
|
217 len = aLength; |
|
218 TInt err = packet.Copy(aData, offset, len); |
|
219 packet.Pack(); |
|
220 iRecvQ.Prepend(packet); |
|
221 LOG(Log::Printf(_L("GetData\t%S SAP[%u] Peek len=%d err=%d from=%S, calling NewData(1)"), &ProtocolName(), (TInt)this, len, err, &tmp)); |
|
222 iSocket->NewData(1); |
|
223 // Any failure to create the RMBufChain is signalled as KErrNoMBufs! |
|
224 return err != KErrNone ? KErrNoMBufs : len; |
|
225 } |
|
226 iQueueLimit += info->iLength; // Allow more packets in.. |
|
227 packet.TrimStart(offset); |
|
228 aData.Assign(packet); |
|
229 if ((TUint)info->iLength > aLength) |
|
230 aData.TrimEnd(aLength); |
|
231 packet.Free(); // (Releases info block) |
|
232 LOG(Log::Printf(_L("GetData\t%S SAP[%u] length=%d from=%S"), &ProtocolName(), (TInt)this, aLength, &tmp)); |
|
233 return aLength; |
|
234 } |
|
235 |
|
236 void CProviderInet6Network::GetData(TDes8 &aDesc, TUint aOptions, TSockAddr *anAddr) |
|
237 { |
|
238 RMBufRecvPacket packet; |
|
239 const RMBufRecvInfo *info; |
|
240 if (!iRecvQ.Remove(packet)) |
|
241 Panic(EInet6Panic_NoData); |
|
242 |
|
243 info = packet.Unpack(); |
|
244 |
|
245 const TInt offset = ((aOptions & KIpHeaderIncluded) != 0 || iRawMode) ? 0 : info->iOffset; |
|
246 packet.CopyOut(aDesc, offset); |
|
247 |
|
248 if (anAddr!=NULL) |
|
249 *anAddr = info->iSrcAddr; |
|
250 |
|
251 #ifdef _LOG |
|
252 TBuf<70> tmp(_L("NULL")); |
|
253 if (anAddr) |
|
254 TInetAddr::Cast(*anAddr).OutputWithScope(tmp); |
|
255 #endif |
|
256 |
|
257 if (aOptions & KSockReadPeek) |
|
258 { |
|
259 packet.Pack(); |
|
260 iRecvQ.Prepend(packet); |
|
261 LOG(Log::Printf(_L("GetData\t%S SAP[%u] peek aDesc = %d from %S, calling NewData(1)"), &ProtocolName(), (TInt)this, aDesc.Length(), &tmp)); |
|
262 iSocket->NewData(1); |
|
263 } |
|
264 else |
|
265 { |
|
266 iQueueLimit += info->iLength; // Allow more packets in.. |
|
267 packet.Free(); |
|
268 LOG(Log::Printf(_L("GetData\t%S SAP[%u] aDesc = %d from=%S"), &ProtocolName(), (TInt)this, aDesc.Length(), &tmp)); |
|
269 } |
|
270 } |