|
1 /* |
|
2 * Copyright (c) 2006-2007 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 #include "natfwunsaflog.h" |
|
22 #include "cnatfwunsafudpsender.h" |
|
23 #include "natfwunsafbindingrequest.h" |
|
24 #include "natfwunsaferrorcodeattribute.h" |
|
25 #include "natfwunsafunknownattributesattribute.h" |
|
26 #include "natfwunsafmessageintegrityattribute.h" |
|
27 #include "stunassert.h" |
|
28 #include "stunutils.h" |
|
29 #include "mstuntransactionobserver.h" |
|
30 #include "cstuntransaction.h" |
|
31 #include "ttransactioncleanup.h" |
|
32 #include "stunturnclientlogs.h" |
|
33 #include "tstuncallbackinfo.h" |
|
34 |
|
35 // ======== MEMBER FUNCTIONS ======== |
|
36 |
|
37 const TInt KInitCompareValue = 1; |
|
38 |
|
39 // Divide factor from uSecs to mSecs |
|
40 const TInt KDivideFactor = 1000; |
|
41 |
|
42 const TInt KWaitingTime = 1600; // rfc3489bis-06#section-7.1 |
|
43 |
|
44 const TInt KMaxTCPWaitingTime = 7900; // rfc3489bis-06#section-7.1 |
|
45 |
|
46 // --------------------------------------------------------------------------- |
|
47 // CSTUNTransaction::NewL |
|
48 // --------------------------------------------------------------------------- |
|
49 // |
|
50 CSTUNTransaction* CSTUNTransaction::NewL( CNATFWUNSAFMessage& aRequest, |
|
51 const TInetAddr& aAddress, |
|
52 const TDesC8& aSharedSecret, |
|
53 RSocket& aSocket, |
|
54 CDeltaTimer& aTimer, |
|
55 TInt aRetransmitInterval, |
|
56 MSTUNTransactionObserver& aObserver, |
|
57 const TDesC8& aProtocol, |
|
58 TTransportProtocol aTransportProtocol ) |
|
59 { |
|
60 __ASSERT_ALWAYS( !aAddress.IsUnspecified(), User::Leave( KErrArgument ) ); |
|
61 |
|
62 CSTUNTransaction* self = |
|
63 new ( ELeave ) CSTUNTransaction( aRequest, |
|
64 aAddress, |
|
65 aSharedSecret, |
|
66 aTimer, |
|
67 aRetransmitInterval, |
|
68 aObserver, |
|
69 aTransportProtocol ); |
|
70 CleanupStack::PushL( self ); |
|
71 self->ConstructL( aSocket, aProtocol ); |
|
72 CleanupStack::Pop( self ); |
|
73 return self; |
|
74 } |
|
75 |
|
76 // --------------------------------------------------------------------------- |
|
77 // CSTUNTransaction::NewL - overloaded |
|
78 // --------------------------------------------------------------------------- |
|
79 // |
|
80 CSTUNTransaction* CSTUNTransaction::NewL( CNATFWUNSAFMessage& aRequest, |
|
81 const TInetAddr& aAddress, |
|
82 const TDesC8& aSharedSecret, |
|
83 TUint aStreamId, |
|
84 TUint aConnectionId, |
|
85 CDeltaTimer& aTimer, |
|
86 TInt aRetransmitInterval, |
|
87 MSTUNTransactionObserver& aObserver, |
|
88 const TDesC8& aProtocol, |
|
89 MNcmConnectionMultiplexer& aMux, |
|
90 TTransportProtocol aTransportProtocol, |
|
91 TBool aUseFingerprint, |
|
92 const TInetAddr& aDestAddr ) |
|
93 { |
|
94 __ASSERT_ALWAYS( !aAddress.IsUnspecified(), User::Leave( KErrArgument ) ); |
|
95 |
|
96 CSTUNTransaction* self = |
|
97 new ( ELeave ) CSTUNTransaction( aRequest, |
|
98 aAddress, |
|
99 aSharedSecret, |
|
100 aStreamId, |
|
101 aConnectionId, |
|
102 aTimer, |
|
103 aRetransmitInterval, |
|
104 aObserver, |
|
105 aDestAddr, |
|
106 aTransportProtocol, |
|
107 aUseFingerprint ); |
|
108 CleanupStack::PushL( self ); |
|
109 self->ConstructL( aProtocol, aMux ); |
|
110 CleanupStack::Pop( self ); |
|
111 return self; |
|
112 } |
|
113 |
|
114 // --------------------------------------------------------------------------- |
|
115 // CSTUNTransaction::CSTUNTransaction |
|
116 // --------------------------------------------------------------------------- |
|
117 // |
|
118 CSTUNTransaction::CSTUNTransaction( CNATFWUNSAFMessage& aRequest, |
|
119 const TInetAddr& aAddress, |
|
120 const TDesC8& aSharedSecret, |
|
121 CDeltaTimer& aTimer, |
|
122 TInt aRetransmitInterval, |
|
123 MSTUNTransactionObserver& aObserver, |
|
124 TTransportProtocol aTransportProtocol ) : |
|
125 CSTUNTimerUser( aTimer ), |
|
126 iObserver( aObserver ), |
|
127 iRequest( aRequest ), |
|
128 iAddress( aAddress ), |
|
129 iSharedSecret( aSharedSecret ), |
|
130 iInitialRetransmitInterval( aRetransmitInterval ), |
|
131 iRetransmit( ETrue ), |
|
132 iTransportProtocol( aTransportProtocol ), |
|
133 iRetransmitCompareValue( KInitCompareValue ) |
|
134 { |
|
135 } |
|
136 |
|
137 // --------------------------------------------------------------------------- |
|
138 // CSTUNTransaction::CSTUNTransaction - overloaded |
|
139 // --------------------------------------------------------------------------- |
|
140 // |
|
141 CSTUNTransaction::CSTUNTransaction( CNATFWUNSAFMessage& aRequest, |
|
142 const TInetAddr& aAddress, |
|
143 const TDesC8& aSharedSecret, |
|
144 TUint aStreamId, |
|
145 TUint aConnectionId, |
|
146 CDeltaTimer& aTimer, |
|
147 TInt aRetransmitInterval, |
|
148 MSTUNTransactionObserver& aObserver, |
|
149 const TInetAddr& aDestAddr, |
|
150 TTransportProtocol aTransportProtocol, |
|
151 TBool aUseFingerprint ) : |
|
152 CSTUNTimerUser( aTimer ), |
|
153 iObserver( aObserver ), |
|
154 iRequest( aRequest ), |
|
155 iAddress( aAddress ), |
|
156 iSharedSecret( aSharedSecret ), |
|
157 iInitialRetransmitInterval( aRetransmitInterval ), |
|
158 iRetransmit( ETrue ), |
|
159 iStreamId( aStreamId ), |
|
160 iSubstreamId( aConnectionId ), |
|
161 iDestAddr( aDestAddr ), |
|
162 iTransportProtocol( aTransportProtocol ), |
|
163 iRetransmitCompareValue( KInitCompareValue ), |
|
164 iUseFingerprint( aUseFingerprint ) |
|
165 { |
|
166 } |
|
167 |
|
168 // --------------------------------------------------------------------------- |
|
169 // CSTUNTransaction::CSTUNTransaction |
|
170 // Dummy implementation. Default constructor is declared private and not used. |
|
171 // --------------------------------------------------------------------------- |
|
172 // |
|
173 CSTUNTransaction::CSTUNTransaction() : |
|
174 CSTUNTimerUser( *( CDeltaTimer* )0x1 ), |
|
175 iObserver( *( MSTUNTransactionObserver* )0x1 ), |
|
176 iRequest( *( CNATFWUNSAFMessage* )0x1 ), |
|
177 iAddress( *( TInetAddr* )0x1 ), |
|
178 iSharedSecret( KNullDesC8 ) |
|
179 { |
|
180 } |
|
181 |
|
182 // --------------------------------------------------------------------------- |
|
183 // CSTUNTransaction::CSTUNTransaction |
|
184 // Dummy implementation, as copy constructor is declared private and not used. |
|
185 // --------------------------------------------------------------------------- |
|
186 // |
|
187 CSTUNTransaction::CSTUNTransaction( const CSTUNTransaction& aTransaction ) : |
|
188 CSTUNTimerUser( *( CDeltaTimer* )0x1 ), |
|
189 iObserver( aTransaction.iObserver ), |
|
190 iRequest( aTransaction.iRequest ), |
|
191 iAddress( aTransaction.iAddress ), |
|
192 iSharedSecret( aTransaction.iSharedSecret ) |
|
193 { |
|
194 } |
|
195 |
|
196 // --------------------------------------------------------------------------- |
|
197 // CSTUNTransaction::ConstructL |
|
198 // --------------------------------------------------------------------------- |
|
199 // |
|
200 void CSTUNTransaction::ConstructL( RSocket& aSocket, const TDesC8& aProtocol ) |
|
201 { |
|
202 __STUNTURNCLIENT( "CSTUNTransaction::ConstructL with sender" ) |
|
203 CheckProtocolL( aProtocol ); |
|
204 iSender = CNATFWUNSAFUdpSender::NewL( aSocket, *this ); |
|
205 SendRequestL(); |
|
206 } |
|
207 |
|
208 // --------------------------------------------------------------------------- |
|
209 // CSTUNTransaction::ConstructL |
|
210 // --------------------------------------------------------------------------- |
|
211 // |
|
212 void CSTUNTransaction::ConstructL( const TDesC8& aProtocol, |
|
213 MNcmConnectionMultiplexer& aMux ) |
|
214 { |
|
215 __STUNTURNCLIENT( "CSTUNTransaction::ConstructL with mediaconsender" ) |
|
216 CheckProtocolL( aProtocol ); |
|
217 iMediaConSender = CNATFWUNSAFMediaConnSender::NewL( aMux ); |
|
218 SendRequestL(); |
|
219 } |
|
220 |
|
221 // --------------------------------------------------------------------------- |
|
222 // CSTUNTransaction::~CSTUNTransaction |
|
223 // --------------------------------------------------------------------------- |
|
224 // |
|
225 CSTUNTransaction::~CSTUNTransaction() |
|
226 { |
|
227 __STUNTURNCLIENT( "CSTUNTransaction::~CSTUNTransaction IN" ) |
|
228 |
|
229 if ( iMediaConSender ) |
|
230 { |
|
231 iMediaConSender->Cancel( iStreamId, iSubstreamId, this ); |
|
232 } |
|
233 |
|
234 delete iMediaConSender; |
|
235 delete iSender; |
|
236 delete iUnknownAttr; |
|
237 delete iProtocol; |
|
238 |
|
239 __STUNTURNCLIENT( "CSTUNTransaction::~CSTUNTransaction OUT" ) |
|
240 } |
|
241 |
|
242 // --------------------------------------------------------------------------- |
|
243 // CSTUNTransaction::NATFWUNSAFUdpMessageSentL |
|
244 // --------------------------------------------------------------------------- |
|
245 // |
|
246 void CSTUNTransaction::UNSAFUdpMessageSentL() |
|
247 { |
|
248 __STUNTURNCLIENT( "CSTUNTransaction::UNSAFUdpMessageSentL" ) |
|
249 __TEST_INVARIANT; |
|
250 |
|
251 if ( !iTerminated ) |
|
252 { |
|
253 ++iSendCount; |
|
254 |
|
255 if ( iRetransmit ) |
|
256 { |
|
257 if ( ETcpProtocol == iTransportProtocol ) |
|
258 { |
|
259 StartTimer( KMaxTCPWaitingTime ); |
|
260 } |
|
261 else |
|
262 { |
|
263 iSendTime.HomeTime(); |
|
264 StartTimer( RetransmitInterval() ); |
|
265 } |
|
266 } |
|
267 } |
|
268 |
|
269 __TEST_INVARIANT; |
|
270 } |
|
271 |
|
272 // --------------------------------------------------------------------------- |
|
273 // CSTUNTransaction::NATFWUNSAFUdpMessageFailure |
|
274 // --------------------------------------------------------------------------- |
|
275 // |
|
276 void CSTUNTransaction::UNSAFUdpMessageFailure( TInt aError ) |
|
277 { |
|
278 __STUNTURNCLIENT_INT1( "\ |
|
279 CSTUNTransaction::UNSAFUdpMessageFailure, error=", aError ) |
|
280 __TEST_INVARIANT; |
|
281 __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument ); |
|
282 |
|
283 if ( !iTerminated ) |
|
284 { |
|
285 Terminate( aError ); |
|
286 } |
|
287 } |
|
288 |
|
289 // --------------------------------------------------------------------------- |
|
290 // CSTUNTransaction::MessageSent |
|
291 // --------------------------------------------------------------------------- |
|
292 // |
|
293 void CSTUNTransaction::MessageSent() |
|
294 { |
|
295 iRequestPending = EFalse; |
|
296 |
|
297 TRAP_IGNORE( UNSAFUdpMessageSentL() ); |
|
298 } |
|
299 |
|
300 // --------------------------------------------------------------------------- |
|
301 // CSTUNTransaction::MessageSentFailure |
|
302 // --------------------------------------------------------------------------- |
|
303 // |
|
304 void CSTUNTransaction::MessageSentFailure( TInt aError ) |
|
305 { |
|
306 __STUNTURNCLIENT_INT1( "\ |
|
307 CSTUNTransaction::MessageSentFailure, error=", aError ) |
|
308 iRequestPending = EFalse; |
|
309 UNSAFUdpMessageFailure( aError ); |
|
310 } |
|
311 |
|
312 // ----------------------------------------------------------------------------- |
|
313 // CSTUNTransaction::SendRequestL |
|
314 // ----------------------------------------------------------------------------- |
|
315 // |
|
316 void CSTUNTransaction::SendRequestL() |
|
317 { |
|
318 __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL" ) |
|
319 if ( iMediaConSender ) |
|
320 { |
|
321 __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL with mediaconsender" ) |
|
322 if ( iDestAddr.IsUnspecified() ) |
|
323 { |
|
324 iMediaConSender->SendL( iStreamId, |
|
325 iSubstreamId, iRequest, iSharedSecret, this, iUseFingerprint ); |
|
326 iRequestPending = ETrue; |
|
327 } |
|
328 else |
|
329 { |
|
330 iMediaConSender->SendL( iStreamId, |
|
331 iSubstreamId, iRequest, iSharedSecret, |
|
332 iDestAddr, this, iUseFingerprint ); |
|
333 |
|
334 iRequestPending = ETrue; |
|
335 } |
|
336 } |
|
337 else if ( iSender ) |
|
338 { |
|
339 __STUNTURNCLIENT( "CSTUNTransaction::SendRequestL with original sender" ) |
|
340 iSender->SendL( iAddress, iRequest, iSharedSecret ); |
|
341 } |
|
342 else |
|
343 { |
|
344 User::Leave( KErrNotReady ); |
|
345 } |
|
346 } |
|
347 |
|
348 // ----------------------------------------------------------------------------- |
|
349 // CSTUNTransaction::RetransmitRequestL |
|
350 // ----------------------------------------------------------------------------- |
|
351 // |
|
352 void CSTUNTransaction::RetransmitRequestL() |
|
353 { |
|
354 __STUNTURNCLIENT_INT1( "\ |
|
355 CSTUNTransaction::RetransmitRequestL, sendcount= ",iSendCount ) |
|
356 if ( iSendCount < KMaxRequestSentCount ) |
|
357 { |
|
358 if ( !iDisableSending ) |
|
359 { |
|
360 SendRequestL(); |
|
361 } |
|
362 else |
|
363 { |
|
364 iSendTime.HomeTime(); |
|
365 StartTimer( RetransmitInterval() ); |
|
366 } |
|
367 } |
|
368 else |
|
369 { |
|
370 Terminate( KErrTimedOut ); |
|
371 } |
|
372 } |
|
373 |
|
374 // --------------------------------------------------------------------------- |
|
375 // CSTUNTransaction::ReceiveL |
|
376 // Also an ignored response stops retransmission. |
|
377 // --------------------------------------------------------------------------- |
|
378 // |
|
379 void CSTUNTransaction::ReceiveL( CNATFWUNSAFMessage& aResponse, |
|
380 const TDesC8& aByteStream ) |
|
381 { |
|
382 __TEST_INVARIANT; |
|
383 __STUN_ASSERT_L( |
|
384 aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse || |
|
385 aResponse.Type() == CNATFWUNSAFMessage::EBindingErrorResponse || |
|
386 aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse || |
|
387 aResponse.Type() == CNATFWUNSAFMessage::EAllocateErrorResponse || |
|
388 aResponse.Type() == CNATFWUNSAFMessage::EConnectResponse || |
|
389 aResponse.Type() == CNATFWUNSAFMessage::EConnectErrorResponse || |
|
390 aResponse.Type() == |
|
391 CNATFWUNSAFMessage::ESetActiveDestinationResponse || |
|
392 aResponse.Type() == |
|
393 CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse, |
|
394 KErrArgument ); |
|
395 |
|
396 if ( !iTerminated ) |
|
397 { |
|
398 iRetransmit = EFalse; |
|
399 StopTimer(); |
|
400 |
|
401 if ( ShouldIgnoreResponse( aResponse ) ) |
|
402 { |
|
403 StartTimer( ComputeWaitDuration() ); |
|
404 } |
|
405 else |
|
406 { |
|
407 if ( EUdpProtocol == iTransportProtocol ) |
|
408 { |
|
409 MeasureNewRTTSample(); |
|
410 } |
|
411 |
|
412 TTransactionCleanup taCleanup( *this ); |
|
413 CleanupStack::PushL( taCleanup.CleanupItem() ); |
|
414 |
|
415 TInt status = ProcessResponseL( aResponse, aByteStream ); |
|
416 |
|
417 CleanupStack::Pop(); //cleanupItem |
|
418 Terminate( status ); |
|
419 } |
|
420 } |
|
421 } |
|
422 |
|
423 // ----------------------------------------------------------------------------- |
|
424 // CSTUNTransaction::ShouldIgnoreResponse |
|
425 // 1xx-3xx response stops retransmissions, but doesn't terminate transaction. |
|
426 // ----------------------------------------------------------------------------- |
|
427 // |
|
428 TBool |
|
429 CSTUNTransaction::ShouldIgnoreResponse( const CNATFWUNSAFMessage& aResponse ) const |
|
430 { |
|
431 __TEST_INVARIANT; |
|
432 |
|
433 TInt responseCode = GetResponseCode( aResponse ); |
|
434 return !aResponse.Validate() || |
|
435 aResponse.HasUnknownMandatoryAttributes() || |
|
436 ( responseCode >= E1XX && responseCode < E4XX ); |
|
437 } |
|
438 |
|
439 // ----------------------------------------------------------------------------- |
|
440 // CSTUNTransaction::ProcessResponseL |
|
441 // ----------------------------------------------------------------------------- |
|
442 // |
|
443 TInt CSTUNTransaction::ProcessResponseL( CNATFWUNSAFMessage& aResponse, |
|
444 const TDesC8& aByteStream ) |
|
445 { |
|
446 __STUNTURNCLIENT( "CSTUNTransaction::ProcessResponseL" ) |
|
447 __TEST_INVARIANT; |
|
448 |
|
449 TInt status = KErrNone; |
|
450 |
|
451 // binding response ( stun functionality ) |
|
452 if ( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse ) |
|
453 { |
|
454 status = CheckIntegrityL( aResponse, aByteStream ); |
|
455 if ( KErrNone == status ) |
|
456 { |
|
457 STUNUtils::GetMappedAddress( aResponse, iMappedAddress ); |
|
458 STUNUtils::GetXorMappedAddressL( aResponse, iXorMappedAddress ); |
|
459 } |
|
460 } |
|
461 |
|
462 // allocate response ( stun relay functionality ) |
|
463 else if ( aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse ) |
|
464 { |
|
465 status = CheckIntegrityL( aResponse, aByteStream ); |
|
466 if ( KErrNone == status ) |
|
467 { |
|
468 // get server relay address |
|
469 STUNUtils::GetRelayAddressL( aResponse, iRelayAddress ); |
|
470 // get server reflexive address |
|
471 STUNUtils::GetXorMappedAddressL( aResponse, iXorMappedAddress ); |
|
472 } |
|
473 } |
|
474 |
|
475 // Connect Response ( stun relay TCP functionality ) |
|
476 else if ( aResponse.Type() == |
|
477 CNATFWUNSAFMessage::EConnectResponse ) |
|
478 { |
|
479 status = CheckIntegrityL( aResponse, aByteStream ); |
|
480 } |
|
481 |
|
482 // Active Destination Response ( stun relay functionality ) |
|
483 else if ( aResponse.Type() == |
|
484 CNATFWUNSAFMessage::ESetActiveDestinationResponse ) |
|
485 { |
|
486 __STUNTURNCLIENT( "do msg integrity check for active destination response" ) |
|
487 status = CheckIntegrityL( aResponse, aByteStream ); |
|
488 if ( KErrNone != status ) |
|
489 { |
|
490 __STUNTURNCLIENT_INT1( "msg integrity check for active\ |
|
491 destination response FAILED - BUT IGNORE IT - SERVER MISBEHAVIOR DETECTED", status ) |
|
492 status = KErrNone; |
|
493 } |
|
494 |
|
495 if ( KErrNone == status ) |
|
496 { |
|
497 // notify stun relay implementation |
|
498 STUNUtils::GetTimerValueL( aResponse, iTimerValue ); |
|
499 } |
|
500 } |
|
501 |
|
502 else |
|
503 { |
|
504 status = GetResponseCode( aResponse ); |
|
505 if ( E4XX > status ) |
|
506 { |
|
507 //Invalid Binding Error Response received |
|
508 status = KErrCorrupt; |
|
509 } |
|
510 if ( status == E420UnknownAttributes ) |
|
511 { |
|
512 __STUN_ASSERT_L( !iUnknownAttr, KErrAlreadyExists ); |
|
513 iUnknownAttr = static_cast<CNATFWUNSAFUnknownAttributesAttribute*>( |
|
514 aResponse.Attribute( |
|
515 CNATFWUNSAFAttribute::EUnknownAttributes ) ); |
|
516 aResponse.DetachAttribute( iUnknownAttr ); |
|
517 } |
|
518 } |
|
519 |
|
520 __TEST_INVARIANT; |
|
521 __STUNTURNCLIENT_INT1( "CSTUNTransaction::ProcessResponseL end, errorcode/status:", status ) |
|
522 return status; |
|
523 } |
|
524 |
|
525 // ----------------------------------------------------------------------------- |
|
526 // CSTUNTransaction::CheckIntegrityL |
|
527 // MESSAGE-INTEGRITY is in the encoded message, not in iRequest. If iRequest has |
|
528 // a USERNAME, then also a MESSAGE-INTEGRITY was sent in the Binding Request. |
|
529 // ----------------------------------------------------------------------------- |
|
530 // |
|
531 TInt CSTUNTransaction::CheckIntegrityL( const CNATFWUNSAFMessage& aResponse, |
|
532 const TDesC8& aByteStream ) |
|
533 { |
|
534 __TEST_INVARIANT; |
|
535 __STUN_ASSERT_L( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse || |
|
536 aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse || |
|
537 aResponse.Type() == CNATFWUNSAFMessage::EConnectResponse || |
|
538 aResponse.Type() == |
|
539 CNATFWUNSAFMessage::ESetActiveDestinationResponse, |
|
540 KErrArgument ); |
|
541 |
|
542 if ( !iRequest.Attribute( CNATFWUNSAFAttribute::EUsername ) ) |
|
543 { |
|
544 return KErrNone; |
|
545 } |
|
546 |
|
547 if ( aResponse.HasAttribute( CNATFWUNSAFAttribute::EMessageIntegrity ) ) |
|
548 { |
|
549 if ( static_cast<CNATFWUNSAFMessageIntegrityAttribute*>( |
|
550 aResponse.Attribute( CNATFWUNSAFAttribute::EMessageIntegrity ) )-> |
|
551 CheckMessageIntegrityL( aByteStream, iSharedSecret ) ) |
|
552 { |
|
553 return KErrNone; |
|
554 } |
|
555 |
|
556 //If XOR-ONLY was already sent, maybe server doesn't support it. |
|
557 if ( CheckForNatOverwriteL( aResponse ) && |
|
558 !iRequest.Attribute( CNATFWUNSAFAttribute::EXorOnly ) ) |
|
559 { |
|
560 return ERetryAfterAddingXorOnly; |
|
561 } |
|
562 } |
|
563 |
|
564 return KErrCorrupt; |
|
565 } |
|
566 |
|
567 // ----------------------------------------------------------------------------- |
|
568 // CSTUNTransaction::CheckForNatOverwriteL |
|
569 // Be compatible with old STUN servers that don't understand XOR-MAPPED-ADDRESS |
|
570 // or XOR-ONLY. Don't treat XOR-MAPPED-ADDRESS as mandatory in Binding Response. |
|
571 // ----------------------------------------------------------------------------- |
|
572 // |
|
573 TBool CSTUNTransaction::CheckForNatOverwriteL( const CNATFWUNSAFMessage& aResponse ) |
|
574 { |
|
575 __TEST_INVARIANT; |
|
576 __STUN_ASSERT_L( aResponse.Type() == CNATFWUNSAFMessage::EBindingResponse || |
|
577 aResponse.Type() == CNATFWUNSAFMessage::EAllocateResponse, |
|
578 KErrArgument ); |
|
579 TInetAddr mappedAddr; |
|
580 TInetAddr xorMappedAddr; |
|
581 return STUNUtils::GetMappedAddress( aResponse, mappedAddr ) && |
|
582 STUNUtils::GetXorMappedAddressL( aResponse, xorMappedAddr ) && |
|
583 !mappedAddr.CmpAddr( xorMappedAddr ); |
|
584 } |
|
585 |
|
586 // ----------------------------------------------------------------------------- |
|
587 // CSTUNTransaction::GetResponseCode |
|
588 // ----------------------------------------------------------------------------- |
|
589 // |
|
590 TInt CSTUNTransaction:: |
|
591 GetResponseCode( const CNATFWUNSAFMessage& aResponse ) const |
|
592 { |
|
593 __TEST_INVARIANT; |
|
594 if ( aResponse.Type() == CNATFWUNSAFMessage::EBindingErrorResponse || |
|
595 aResponse.Type() == CNATFWUNSAFMessage::EAllocateErrorResponse || |
|
596 aResponse.Type() == CNATFWUNSAFMessage::EConnectErrorResponse || |
|
597 aResponse.Type() == |
|
598 CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse ) |
|
599 { |
|
600 CNATFWUNSAFErrorCodeAttribute* errorCode = |
|
601 static_cast<CNATFWUNSAFErrorCodeAttribute*> |
|
602 ( aResponse.Attribute( CNATFWUNSAFAttribute::EErrorCode ) ); |
|
603 |
|
604 if ( errorCode ) |
|
605 { |
|
606 return errorCode->ResponseCode(); |
|
607 } |
|
608 } |
|
609 return KErrNotFound; |
|
610 } |
|
611 |
|
612 // --------------------------------------------------------------------------- |
|
613 // CSTUNTransaction::Terminate |
|
614 // Don't use invariant at the end of Terminate nor elsewhere after calling it, |
|
615 // as binding deletes this transaction. |
|
616 // If PublicAddressObtainedL leaves, call TransactionError. |
|
617 // --------------------------------------------------------------------------- |
|
618 // |
|
619 void CSTUNTransaction::Terminate( TInt aError ) |
|
620 { |
|
621 __STUNTURNCLIENT_INT1( "CSTUNTransaction::Terminate, error = ", aError ) |
|
622 __TEST_INVARIANT; |
|
623 |
|
624 //Terminate only once |
|
625 __STUN_ASSERT_RETURN( !iTerminated, KErrDied ); |
|
626 NATFWUNSAF_INTLOG( "STUNTransaction terminated, reason:", aError ) |
|
627 |
|
628 iTerminated = ETrue; |
|
629 |
|
630 if ( aError == KErrNone ) |
|
631 { |
|
632 TInetAddr publicAddr = iXorMappedAddress; |
|
633 if ( publicAddr.IsUnspecified() ) |
|
634 { |
|
635 publicAddr = iMappedAddress; |
|
636 } |
|
637 |
|
638 if ( publicAddr.IsUnspecified() ) |
|
639 { |
|
640 if ( CNATFWUNSAFMessage::ESetActiveDestinationRequest == |
|
641 iRequest.Type() ) |
|
642 { |
|
643 TRAP( aError, iObserver.TransactionEventOccurredL( |
|
644 TSTUNCallbackInfo::EEventActiveDestinationSet ) ); |
|
645 if ( aError ) |
|
646 { |
|
647 __STUNTURNCLIENT_INT1( |
|
648 "TransactionEventOccurredL leaves, reason:", aError ) |
|
649 } |
|
650 } |
|
651 else if ( CNATFWUNSAFMessage::EConnectRequest == iRequest.Type() ) |
|
652 { |
|
653 TRAP( aError, iObserver.TransactionEventOccurredL( |
|
654 TSTUNCallbackInfo::EEventTCPConnectOk ) ); |
|
655 if ( aError ) |
|
656 { |
|
657 __STUNTURNCLIENT_INT1( |
|
658 "TransactionEventOccurredL leaves, reason:", aError ) |
|
659 } |
|
660 } |
|
661 else |
|
662 { |
|
663 // Server sent invalid Binding Response |
|
664 aError = KErrCorrupt; |
|
665 } |
|
666 } |
|
667 else |
|
668 { |
|
669 if ( !StunRelayUsed() || iRelayAddress.IsUnspecified() ) |
|
670 { |
|
671 __STUNTURNCLIENT( "\ |
|
672 CSTUNTransaction::Terminate StunRelay NOT Used." ) |
|
673 TRAP( aError, iObserver.PublicAddressObtainedL( publicAddr ) ); |
|
674 } |
|
675 else |
|
676 { |
|
677 __STUNTURNCLIENT( "\ |
|
678 CSTUNTransaction::Terminate StunRelay Used." ) |
|
679 TRAP( aError, iObserver.PublicAddressObtainedL( |
|
680 publicAddr, iRelayAddress ) ); |
|
681 } |
|
682 } |
|
683 } |
|
684 |
|
685 if ( aError ) |
|
686 { |
|
687 CNATFWUNSAFUnknownAttributesAttribute* unknownAttr = iUnknownAttr; |
|
688 iUnknownAttr = NULL; |
|
689 iObserver.TransactionError( aError, unknownAttr ); |
|
690 } |
|
691 } |
|
692 |
|
693 // ----------------------------------------------------------------------------- |
|
694 // CSTUNTransaction::RetransmitInterval |
|
695 // ----------------------------------------------------------------------------- |
|
696 // |
|
697 TInt CSTUNTransaction::RetransmitInterval() |
|
698 { |
|
699 __STUNTURNCLIENT( "CSTUNTransaction::RetransmitInterval" ) |
|
700 __TEST_INVARIANT; |
|
701 |
|
702 if ( 0 == iRetransmitInterval ) |
|
703 { |
|
704 iRetransmitInterval = iInitialRetransmitInterval; |
|
705 } |
|
706 else if ( KMaxRequestSentCount == iSendCount ) |
|
707 { |
|
708 iRetransmitInterval = KWaitingTime; |
|
709 } |
|
710 else |
|
711 { |
|
712 iRetransmitInterval = iRetransmitInterval << 1; |
|
713 } |
|
714 |
|
715 __TEST_INVARIANT; |
|
716 return iRetransmitInterval; |
|
717 } |
|
718 |
|
719 // ----------------------------------------------------------------------------- |
|
720 // CSTUNTransaction::ComputeWaitDuration |
|
721 // ----------------------------------------------------------------------------- |
|
722 // |
|
723 TInt CSTUNTransaction::ComputeWaitDuration() |
|
724 { |
|
725 __STUNTURNCLIENT( "CSTUNTransaction::ComputeWaitDuration" ) |
|
726 __TEST_INVARIANT; |
|
727 |
|
728 TInt duration( 0 ); |
|
729 for ( TInt i = iSendCount; i < KMaxRequestSentCount; ++i ) |
|
730 { |
|
731 duration += RetransmitInterval(); |
|
732 } |
|
733 |
|
734 __TEST_INVARIANT; |
|
735 return duration; |
|
736 } |
|
737 |
|
738 // ----------------------------------------------------------------------------- |
|
739 // CSTUNTransaction::TimerExpiredL |
|
740 // ----------------------------------------------------------------------------- |
|
741 // |
|
742 void CSTUNTransaction::TimerExpiredL() |
|
743 { |
|
744 __STUNTURNCLIENT( "CSTUNTransaction::TimerExpiredL" ) |
|
745 __TEST_INVARIANT; |
|
746 |
|
747 if ( iRetransmit && EUdpProtocol == iTransportProtocol ) |
|
748 { |
|
749 RetransmitRequestL(); |
|
750 } |
|
751 else |
|
752 { |
|
753 Terminate( KErrTimedOut ); |
|
754 } |
|
755 } |
|
756 |
|
757 // ----------------------------------------------------------------------------- |
|
758 // CSTUNTransaction::LeaveFromTimerExpired |
|
759 // ----------------------------------------------------------------------------- |
|
760 // |
|
761 void CSTUNTransaction::LeaveFromTimerExpired( TInt aError ) |
|
762 { |
|
763 __STUNTURNCLIENT_INT1( "\ |
|
764 CSTUNTransaction::LeaveFromTimerExpired, error = ", aError ) |
|
765 __TEST_INVARIANT; |
|
766 __STUN_ASSERT_RETURN( aError != KErrNone, KErrArgument ); |
|
767 |
|
768 Terminate( aError ); |
|
769 } |
|
770 |
|
771 // ----------------------------------------------------------------------------- |
|
772 // CSTUNTransaction::TimerValue |
|
773 // ----------------------------------------------------------------------------- |
|
774 // |
|
775 const TUint32& CSTUNTransaction::TimerValue() const |
|
776 { |
|
777 return iTimerValue; |
|
778 } |
|
779 |
|
780 // ----------------------------------------------------------------------------- |
|
781 // CSTUNTransaction::CancelRetransmission |
|
782 // ----------------------------------------------------------------------------- |
|
783 // |
|
784 void CSTUNTransaction::CancelRetransmission() |
|
785 { |
|
786 iDisableSending = ETrue; |
|
787 } |
|
788 |
|
789 // ----------------------------------------------------------------------------- |
|
790 // CSTUNTransaction::CheckProtocolL |
|
791 // ----------------------------------------------------------------------------- |
|
792 // |
|
793 void CSTUNTransaction::CheckProtocolL( const TDesC8& aProtocol ) |
|
794 { |
|
795 __STUNTURNCLIENT( "CSTUNTransaction::CheckProtocolL" ) |
|
796 delete iProtocol; |
|
797 iProtocol = NULL; |
|
798 |
|
799 if ( aProtocol.Compare( KStun ) ) |
|
800 { |
|
801 iProtocol = aProtocol.AllocL(); |
|
802 } |
|
803 else if ( aProtocol.Compare( KStunRelay ) ) |
|
804 { |
|
805 iProtocol = aProtocol.AllocL(); |
|
806 } |
|
807 else |
|
808 { |
|
809 User::Leave( KErrArgument ); |
|
810 } |
|
811 } |
|
812 |
|
813 // ----------------------------------------------------------------------------- |
|
814 // CSTUNTransaction::StunRelayUsed |
|
815 // ----------------------------------------------------------------------------- |
|
816 // |
|
817 TBool CSTUNTransaction::StunRelayUsed() |
|
818 { |
|
819 __STUNTURNCLIENT( "CSTUNTransaction::StunRelayUsed()" ) |
|
820 return !iProtocol->Compare( KStunRelay ); |
|
821 } |
|
822 |
|
823 // ----------------------------------------------------------------------------- |
|
824 // CSTUNTransaction::MeasureNewRTTSample |
|
825 // ----------------------------------------------------------------------------- |
|
826 // |
|
827 void CSTUNTransaction::MeasureNewRTTSample() |
|
828 { |
|
829 TTime curTime; |
|
830 curTime.HomeTime(); |
|
831 |
|
832 //Measured RTT ( Round-trip time ) |
|
833 TTimeIntervalMicroSeconds time = curTime.MicroSecondsFrom( iSendTime ); |
|
834 // change microsecs to millisecs |
|
835 TInt64 rttSample = time.Int64() / TInt64( KDivideFactor ); |
|
836 |
|
837 // rfc3489bis-06#section-7.1 |
|
838 // As with TCP, the usage of Karn's |
|
839 // algorithm is RECOMMENDED. When applied to STUN, it means that RTT |
|
840 // estimates SHOULD NOT be computed from STUN transactions which result |
|
841 // in the retransmission of a request. |
|
842 |
|
843 TBool retransmitted( EFalse ); |
|
844 |
|
845 if ( iRetransmitCompareValue < iSendCount ) |
|
846 { |
|
847 retransmitted = ETrue; |
|
848 rttSample = iRetransmitInterval; |
|
849 } |
|
850 |
|
851 iObserver.NewRTTSampleMeasured( rttSample, retransmitted ); |
|
852 } |
|
853 |
|
854 // ----------------------------------------------------------------------------- |
|
855 // CSTUNTransaction::__DbgTestInvariant |
|
856 // ----------------------------------------------------------------------------- |
|
857 // |
|
858 void CSTUNTransaction::__DbgTestInvariant() const |
|
859 { |
|
860 #if defined( _DEBUG ) |
|
861 if ( /*!iSender ||*/ |
|
862 iAddress.IsUnspecified() || |
|
863 iSendCount < 0 || |
|
864 iSendCount > KMaxRequestSentCount || |
|
865 iRetransmitInterval < 0 ) |
|
866 { |
|
867 __STUNTURNCLIENT( "CSTUNTransaction::__DbgTestInvariant()\ |
|
868 stage#1 panic" ) |
|
869 User::Invariant(); |
|
870 } |
|
871 #endif |
|
872 } |