|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Receiver for UDP data |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <es_sock.h> |
|
20 #include "receiver.h" |
|
21 #include "ikemsgheader.h" |
|
22 #include "ikev2const.h" |
|
23 #include "ikesocketdefs.h" |
|
24 #include "ikedebug.h" |
|
25 #include "ikesocketassert.h" |
|
26 |
|
27 using namespace IkeSocket; |
|
28 |
|
29 const TInt KMaxIkePacketSize( 65536 ); // Maximum size for UDP packet |
|
30 |
|
31 // ======== MEMBER FUNCTIONS ======== |
|
32 |
|
33 // --------------------------------------------------------------------------- |
|
34 // Two-phased constructor. |
|
35 // --------------------------------------------------------------------------- |
|
36 // |
|
37 CReceiver* CReceiver::NewL( RSocket& aSocket, |
|
38 MReceiverCallback& aCallback, |
|
39 MIkeDebug& aDebug ) |
|
40 { |
|
41 CReceiver* self = new (ELeave) CReceiver( aSocket, |
|
42 aCallback, |
|
43 aDebug ); |
|
44 CleanupStack::PushL(self); |
|
45 self->ConstructL(); |
|
46 CleanupStack::Pop(self); |
|
47 return self; |
|
48 } |
|
49 |
|
50 // --------------------------------------------------------------------------- |
|
51 // Destructor. |
|
52 // --------------------------------------------------------------------------- |
|
53 // |
|
54 CReceiver::~CReceiver() |
|
55 { |
|
56 DEBUG_LOG( _L("CReceiver::~CReceiver") ); |
|
57 Cancel(); |
|
58 delete iMsg; |
|
59 } |
|
60 |
|
61 // --------------------------------------------------------------------------- |
|
62 // Constructor. |
|
63 // --------------------------------------------------------------------------- |
|
64 // |
|
65 CReceiver::CReceiver( RSocket& aSocket, |
|
66 MReceiverCallback& aCallback, |
|
67 MIkeDebug& aDebug ) |
|
68 : CActive( EPriorityStandard ), |
|
69 iState( EIdle ), |
|
70 iMsgPtr( 0, 0, 0 ), |
|
71 iSocket( aSocket ), |
|
72 iCallback( aCallback ), |
|
73 iDebug( aDebug ) |
|
74 { |
|
75 CActiveScheduler::Add( this ); // Added to the Active Scheduler |
|
76 } |
|
77 |
|
78 // --------------------------------------------------------------------------- |
|
79 // Second phase construction. |
|
80 // --------------------------------------------------------------------------- |
|
81 // |
|
82 void CReceiver::ConstructL() |
|
83 { |
|
84 DEBUG_LOG( _L("CReceiver::ConstructL") ); |
|
85 } |
|
86 |
|
87 // --------------------------------------------------------------------------- |
|
88 // Sets IKE major version. |
|
89 // --------------------------------------------------------------------------- |
|
90 // |
|
91 void CReceiver::SetIkeMajorVersion( const TIkeMajorVersion aIkeMajorVersion ) |
|
92 { |
|
93 IKESOCKET_ASSERT( aIkeMajorVersion == EIkeMajorV1 || |
|
94 aIkeMajorVersion == EIkeMajorV2 ); |
|
95 |
|
96 iIkeMajorVersion = aIkeMajorVersion; |
|
97 } |
|
98 |
|
99 // --------------------------------------------------------------------------- |
|
100 // Starts receive. |
|
101 // --------------------------------------------------------------------------- |
|
102 // |
|
103 void CReceiver::Receive() |
|
104 { |
|
105 IKESOCKET_ASSERT( iIkeMajorVersion == EIkeMajorV1 || |
|
106 iIkeMajorVersion == EIkeMajorV2 ); |
|
107 |
|
108 if ( iState == EIdle ) |
|
109 { |
|
110 WaitDataAvailable(); |
|
111 } |
|
112 } |
|
113 |
|
114 // --------------------------------------------------------------------------- |
|
115 // Cancels receive. |
|
116 // --------------------------------------------------------------------------- |
|
117 // |
|
118 void CReceiver::CancelReceive() |
|
119 { |
|
120 Cancel(); |
|
121 |
|
122 delete iMsg; |
|
123 iMsg = NULL; |
|
124 iMsgPtr.Set( 0, 0, 0 ); |
|
125 |
|
126 iState = EIdle; |
|
127 } |
|
128 |
|
129 // --------------------------------------------------------------------------- |
|
130 // Waits for data to become available for reading. |
|
131 // --------------------------------------------------------------------------- |
|
132 // |
|
133 void CReceiver::WaitDataAvailable() |
|
134 { |
|
135 IKESOCKET_ASSERT( iState == EIdle ); |
|
136 IKESOCKET_ASSERT( !IsActive() ); |
|
137 |
|
138 iState = EWaitingData; |
|
139 delete iMsg; |
|
140 iMsg = NULL; |
|
141 |
|
142 iFlags() = KSockSelectRead | KSockSelectExcept; |
|
143 |
|
144 iSocket.Ioctl( KIOctlSelect, |
|
145 iStatus, |
|
146 &iFlags, |
|
147 KSOLSocket ); |
|
148 SetActive(); |
|
149 } |
|
150 |
|
151 // --------------------------------------------------------------------------- |
|
152 // Receives data from socket. |
|
153 // --------------------------------------------------------------------------- |
|
154 // |
|
155 void CReceiver::ReceiveDataL() |
|
156 { |
|
157 IKESOCKET_ASSERT( !IsActive() ); |
|
158 |
|
159 iState = EReceiving; |
|
160 |
|
161 TInt bytesPending( 0 ); |
|
162 TInt err = iSocket.GetOpt( KSOReadBytesPending, |
|
163 KSOLSocket, |
|
164 bytesPending ); |
|
165 |
|
166 User::LeaveIfError( err ); |
|
167 |
|
168 if ( bytesPending > KMaxIkePacketSize ) |
|
169 { |
|
170 // KMaxIkePacketSize (65536) is max message size supported. |
|
171 bytesPending = KMaxIkePacketSize; |
|
172 } |
|
173 |
|
174 iMsg = HBufC8::NewL( bytesPending ); |
|
175 iMsgPtr.Set( iMsg->Des() ); |
|
176 |
|
177 iSocket.RecvFrom( iMsgPtr, |
|
178 iSrcAddr, |
|
179 0, |
|
180 iStatus ); |
|
181 SetActive(); |
|
182 } |
|
183 |
|
184 // --------------------------------------------------------------------------- |
|
185 // Handles receive of data. |
|
186 // --------------------------------------------------------------------------- |
|
187 // |
|
188 void CReceiver::HandleDataReceivedL() |
|
189 { |
|
190 #ifdef _DEBUG |
|
191 TBuf<100> txt_addr; |
|
192 iSrcAddr.Output( txt_addr ); |
|
193 TUint32 port = iSrcAddr.Port(); |
|
194 DEBUG_LOG3( _L("CReceiver::HandleDataReceivedL, local port=%d, src address:port=%S:%d"), |
|
195 iSocket.LocalPort(), &txt_addr, port ); |
|
196 #endif |
|
197 |
|
198 TInt msgLength = iMsgPtr.Length(); |
|
199 if ( msgLength <= TInt(ISAKMP_HDR_SIZE) ) |
|
200 { |
|
201 // Message size smaller than header size. |
|
202 User::Leave( KErrArgument ); |
|
203 } |
|
204 |
|
205 // Check if <non-ESP marker> is in the beginning of IKE message. |
|
206 // <non-ESP marker> is related to the NAT traversal and it should |
|
207 // exist only if IKE messages received through port 4500. |
|
208 // However, we accept <non-ESP marker> also in IKE message |
|
209 // received through normal IKE port (500). |
|
210 const ThdrISAKMP* ikeHdr = ThdrISAKMP::Ptr( iMsgPtr ); |
|
211 TUint32 octets = BigEndian::Get32( (TUint8*)(ikeHdr) ); |
|
212 TBool nonEspMarker = ( octets == NON_ESP_MARKER ); |
|
213 if ( nonEspMarker ) |
|
214 { |
|
215 ikeHdr = ikeHdr->GotoOffset( NON_ESP_MARKER_SIZE ); |
|
216 msgLength -= NON_ESP_MARKER_SIZE; |
|
217 if ( msgLength <= TInt(ISAKMP_HDR_SIZE) ) |
|
218 { |
|
219 // Message size smaller than header size. |
|
220 User::Leave( KErrArgument ); |
|
221 } |
|
222 } |
|
223 |
|
224 // Because the received data can be any UDP data transmitted to |
|
225 // IKE port(s), some checks are done before packet is processed. Length |
|
226 // value read from header must be greater than ISAKMP_HDR_SIZE. |
|
227 TInt ikeMsgLength = ikeHdr->GetLength(); |
|
228 if ( ikeMsgLength <= TInt(ISAKMP_HDR_SIZE) ) |
|
229 { |
|
230 User::Leave( KErrArgument ); |
|
231 } |
|
232 |
|
233 // IKE major version in packet MUST be as client expects (1 or 2). |
|
234 TUint8 majorVersion = ikeHdr->GetMajorVersion(); |
|
235 if ( majorVersion != iIkeMajorVersion ) |
|
236 { |
|
237 User::Leave( KErrArgument ); |
|
238 } |
|
239 |
|
240 NotifyDataReceived(); |
|
241 } |
|
242 |
|
243 // --------------------------------------------------------------------------- |
|
244 // Handles error in receiving. |
|
245 // --------------------------------------------------------------------------- |
|
246 // |
|
247 void CReceiver::HandleError( const TInt aStatus ) |
|
248 { |
|
249 DEBUG_LOG1( _L("CReceiver::HandleError, aStatus=%d"), aStatus ); |
|
250 |
|
251 delete iMsg; |
|
252 iMsg = NULL; |
|
253 iMsgPtr.Set( 0, 0, 0 ); |
|
254 iState = EIdle; |
|
255 |
|
256 if ( aStatus == KErrDied || |
|
257 aStatus == KErrServerTerminated || |
|
258 aStatus == KErrNoMemory ) |
|
259 { |
|
260 // Fatal error. Notify client. |
|
261 iCallback.ReceiveError( aStatus ); |
|
262 } |
|
263 else |
|
264 { |
|
265 // Error is not fatal. Restart receiving |
|
266 Receive(); |
|
267 } |
|
268 } |
|
269 |
|
270 // --------------------------------------------------------------------------- |
|
271 // Notifies client that data has been received. |
|
272 // --------------------------------------------------------------------------- |
|
273 // |
|
274 void CReceiver::NotifyDataReceived() |
|
275 { |
|
276 TInetAddr srcAddr = iSrcAddr; |
|
277 TInt localPort = iSocket.LocalPort(); |
|
278 HBufC8* msg = iMsg; |
|
279 |
|
280 iMsg = NULL; |
|
281 iMsgPtr.Set( 0, 0, 0 ); |
|
282 iState = EIdle; |
|
283 |
|
284 // Continue receiving. |
|
285 Receive(); |
|
286 |
|
287 iCallback.DataReceived( msg, // Ownership transferred |
|
288 srcAddr, |
|
289 localPort ); |
|
290 } |
|
291 |
|
292 // --------------------------------------------------------------------------- |
|
293 // From CActive |
|
294 // Handles a leave occurring in RunL(). |
|
295 // --------------------------------------------------------------------------- |
|
296 // |
|
297 TInt CReceiver::RunError( TInt aError ) |
|
298 { |
|
299 HandleError( aError ); |
|
300 return KErrNone; |
|
301 } |
|
302 |
|
303 // --------------------------------------------------------------------------- |
|
304 // From CActive |
|
305 // Handles request completion event about available data or received data. |
|
306 // --------------------------------------------------------------------------- |
|
307 // |
|
308 void CReceiver::RunL() |
|
309 { |
|
310 IKESOCKET_ASSERT( iState == EWaitingData || |
|
311 iState == EReceiving ); |
|
312 DEBUG_LOG2( _L("CReceiver::RunL, iState=%d, iStatus=%d"), |
|
313 iState, iStatus.Int() ); |
|
314 |
|
315 if ( iStatus.Int() ) |
|
316 { |
|
317 HandleError( iStatus.Int() ); |
|
318 return; |
|
319 } |
|
320 |
|
321 switch ( iState ) |
|
322 { |
|
323 case EWaitingData: |
|
324 { |
|
325 ReceiveDataL(); |
|
326 break; |
|
327 } |
|
328 case EReceiving: |
|
329 { |
|
330 HandleDataReceivedL(); |
|
331 break; |
|
332 } |
|
333 default: |
|
334 break; |
|
335 } |
|
336 } |
|
337 |
|
338 // --------------------------------------------------------------------------- |
|
339 // From CActive |
|
340 // Implements cancellation of an active request. |
|
341 // --------------------------------------------------------------------------- |
|
342 // |
|
343 void CReceiver::DoCancel() |
|
344 { |
|
345 IKESOCKET_ASSERT( iState == EWaitingData || |
|
346 iState == EReceiving ); |
|
347 DEBUG_LOG1( _L("CReceiver::DoCancel, iState=%d"), |
|
348 iState ); |
|
349 |
|
350 switch ( iState ) |
|
351 { |
|
352 case EWaitingData: |
|
353 { |
|
354 iSocket.CancelIoctl(); |
|
355 break; |
|
356 } |
|
357 case EReceiving: |
|
358 { |
|
359 iSocket.CancelRecv(); |
|
360 break; |
|
361 } |
|
362 default: |
|
363 break; |
|
364 } |
|
365 } |