|
1 /* |
|
2 * Copyright (c) 2002-2004 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: mmsconninit implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <in_sock.h> |
|
22 #include <es_enum.h> |
|
23 #include <e32property.h> |
|
24 #include <sacls.h> |
|
25 #include <mpmpropertydef.h> |
|
26 |
|
27 // USERINCLUDE FILES |
|
28 #include "mmsconninit.h" |
|
29 |
|
30 // EXTERNAL DATA STRUCTURES |
|
31 // EXTERNAL FUNCTION PROTOTYPES |
|
32 // CONSTANTS |
|
33 const TInt32 KMmsShortTimeout = 30; // seconds |
|
34 // Interval must be long enough to give the connection time to recover |
|
35 const TInt32 KMmsRetryInterval = 10; // seconds |
|
36 const TInt KMmsSecondsToMilliseconds = 1000000; |
|
37 // Only one retry - if that does not work, better reschedule the operation normally |
|
38 const TInt KMmsMaxRetryCount = 1; |
|
39 const TInt KMaxProxyPortLength = 6; |
|
40 _LIT( KHttpSchemePart1, "http" ); |
|
41 _LIT( KHttpSchemePart2, "://" ); |
|
42 const TInt KMmsScheme1Length = 4; |
|
43 const TInt KMmsHTTPSchemeLength = 7; |
|
44 |
|
45 |
|
46 // MACROS |
|
47 // LOCAL CONSTANTS AND MACROS |
|
48 // MODULE DATA STRUCTURES |
|
49 // LOCAL FUNCTION PROTOTYPES |
|
50 // ============================== LOCAL FUNCTIONS ============================== |
|
51 // ============================== MEMBER FUNCTIONS ============================= |
|
52 |
|
53 // ----------------------------------------------------------------------------- |
|
54 // CMmsConnectionInitiator |
|
55 // ----------------------------------------------------------------------------- |
|
56 // |
|
57 CMmsConnectionInitiator::CMmsConnectionInitiator() : |
|
58 CActive( EPriorityStandard ) |
|
59 { |
|
60 } |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // ConstructL |
|
64 // ----------------------------------------------------------------------------- |
|
65 // |
|
66 void CMmsConnectionInitiator::ConstructL() |
|
67 { |
|
68 CActiveScheduler::Add( this ); |
|
69 iTimerRunning = EFalse; |
|
70 } |
|
71 |
|
72 // ----------------------------------------------------------------------------- |
|
73 // NewL |
|
74 // ----------------------------------------------------------------------------- |
|
75 // |
|
76 EXPORT_C CMmsConnectionInitiator* CMmsConnectionInitiator::NewL() |
|
77 { |
|
78 CMmsConnectionInitiator* self = new ( ELeave ) CMmsConnectionInitiator; |
|
79 CleanupStack::PushL( self ); |
|
80 self->ConstructL(); |
|
81 CleanupStack::Pop( self ); |
|
82 #ifdef _MMSCONNINIT_LOGGING_ |
|
83 TMmsConnInitLogger::Log( _L("MmsConnInit constructed ") ); |
|
84 #endif |
|
85 return self; |
|
86 } |
|
87 |
|
88 // ----------------------------------------------------------------------------- |
|
89 // ~CMmsConnectionInitiator |
|
90 // ----------------------------------------------------------------------------- |
|
91 // |
|
92 CMmsConnectionInitiator::~CMmsConnectionInitiator() |
|
93 { |
|
94 // cancel closes our timer if it is running |
|
95 Cancel(); |
|
96 // iConnection, iClientStatus and iArray are owned by caller |
|
97 |
|
98 // Just to be sure the Access point property goes, delete it |
|
99 // Never mind the error - this is the best effort. |
|
100 // If it does not work, what can we do. Question mark. (To avoid "worrying commets") |
|
101 #ifdef _MMSCONNINIT_LOGGING_ |
|
102 TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKey") ); |
|
103 #endif |
|
104 RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS ); |
|
105 |
|
106 #ifdef _MMSCONNINIT_LOGGING_ |
|
107 TMmsConnInitLogger::Log( _L("MmsConnInit destroyed ") ); |
|
108 #endif |
|
109 } |
|
110 |
|
111 // ----------------------------------------------------------------------------- |
|
112 // ConnectL |
|
113 // ----------------------------------------------------------------------------- |
|
114 // |
|
115 EXPORT_C void CMmsConnectionInitiator::ConnectL( |
|
116 RConnection& aConnection, |
|
117 CArrayFixFlat<TUint32>& aAccessPointArray, |
|
118 TRequestStatus& aStatus ) |
|
119 { |
|
120 #ifdef _MMSCONNINIT_LOGGING_ |
|
121 TMmsConnInitLogger::Log( _L("MmsConnInit::ConnectL") ); |
|
122 #endif |
|
123 iClientStatus = &aStatus; |
|
124 iConnection = &aConnection; |
|
125 iArray = &aAccessPointArray; |
|
126 *iClientStatus = KRequestPending; |
|
127 iIndex = 0; |
|
128 iTimerRunning = EFalse; |
|
129 iRetryCount = 0; |
|
130 |
|
131 // No reason to continue if the array is empty |
|
132 if( aAccessPointArray.Count() == 0 ) |
|
133 { |
|
134 User::RequestComplete( iClientStatus, KErrArgument ); |
|
135 return; |
|
136 } |
|
137 |
|
138 if ( !CheckNetworkL() ) |
|
139 { |
|
140 User::RequestComplete( iClientStatus, KErrCouldNotConnect ); |
|
141 return; |
|
142 } |
|
143 |
|
144 // Let's not start the AO if we do not find IAP |
|
145 for( iIndex = 0; iIndex < iArray->Count(); iIndex++ ) |
|
146 { |
|
147 TUint32 ap; // IAP to be resolved |
|
148 // index is safe |
|
149 if( ( FindIapL( iArray->At( iIndex ), ap ) ) ) |
|
150 { |
|
151 // Let's override the preferences |
|
152 iPrefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); |
|
153 //Start the connection |
|
154 StartConnectionL( ap ); |
|
155 iStartTime.UniversalTime(); |
|
156 SetActive(); |
|
157 return; |
|
158 } |
|
159 // IAP not found but let's keep on looping |
|
160 } |
|
161 //We looped through the array and did not succeed |
|
162 //We do not have any error value in the iStatus because we |
|
163 //did not even try to connect |
|
164 User::RequestComplete( iClientStatus, KErrCouldNotConnect ); |
|
165 return; |
|
166 } |
|
167 |
|
168 // ----------------------------------------------------------------------------- |
|
169 // GetParametersL |
|
170 // ----------------------------------------------------------------------------- |
|
171 // |
|
172 EXPORT_C void CMmsConnectionInitiator::GetParametersL( |
|
173 TUint32 aAccessPointLink, |
|
174 TUint32& aAccessPoint, |
|
175 HBufC*& aServerUri, |
|
176 TBool& aProxyUsed, |
|
177 HBufC8*& aProxyAddress ) |
|
178 { |
|
179 // Every function reading the commsDB are trapped because |
|
180 // they may leave if the field is empty. We still may be |
|
181 // able to continue browsing the DB further. |
|
182 // Exception: Functions reading long text are not trapped |
|
183 // because they allocate memory. |
|
184 |
|
185 #ifdef _MMSCONNINIT_LOGGING_ |
|
186 TMmsConnInitLogger::Log( _L("MmsConnInit::GetParametersL") ); |
|
187 #endif |
|
188 |
|
189 // Initialise OUT parameters |
|
190 aServerUri = NULL; |
|
191 aAccessPoint = 0; |
|
192 aProxyUsed = EFalse; |
|
193 aProxyAddress = NULL; |
|
194 |
|
195 // Initialise used variables |
|
196 TInt error = KErrNone; |
|
197 TUint32 num32Value = 0; |
|
198 TBuf <KCommsDbSvrMaxFieldLength> textValue; |
|
199 TInt length = 0; |
|
200 CCommsDbTableView* view = NULL; |
|
201 |
|
202 // Connect to Database server and CommDb |
|
203 CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified ); |
|
204 CleanupStack::PushL( db ); |
|
205 |
|
206 // Start from WAP_ACCESS_POINT table -> opening view to it |
|
207 view = db->OpenViewMatchingUintLC( |
|
208 TPtrC( WAP_ACCESS_POINT ), |
|
209 TPtrC( COMMDB_ID ), |
|
210 aAccessPointLink ); |
|
211 |
|
212 // If no record for 'aAccessPointLink' there's nothing to look for |
|
213 if( view->GotoFirstRecord() != KErrNone ) |
|
214 { |
|
215 CleanupStack::PopAndDestroy( view ); |
|
216 CleanupStack::PopAndDestroy( db ); |
|
217 return; |
|
218 } |
|
219 |
|
220 // Get aServerUri (WAP_START_PAGE in CommDb) |
|
221 // ReadColumnLengthL only leaves if the column does not exist at all - |
|
222 // that means that the database structure is totally wrong, and we can't continue |
|
223 view->ReadColumnLengthL( TPtrC( WAP_START_PAGE ), length ); |
|
224 // ReadLongTextL only leaves if the column does not exist in the table |
|
225 // or we are out of memory. |
|
226 aServerUri = view->ReadLongTextLC( TPtrC( WAP_START_PAGE ) ); |
|
227 // If the function did not leave, we have aServerUri on the cleanup stack |
|
228 // It's length may be 0, but the pointer itself is not NULL |
|
229 if( length != 0 ) |
|
230 { |
|
231 CheckWapStartPageL( aServerUri ); // tries to ensure proper syntax |
|
232 } |
|
233 |
|
234 // Get link to bearer |
|
235 // This function only leaves if the column does not exist in the table |
|
236 // This means the structure of the database is incorrect, and we cannot continue |
|
237 view->ReadTextL( TPtrC( WAP_CURRENT_BEARER ), textValue ); |
|
238 |
|
239 // view must be deleted, but it is not on top of the CleanupStack |
|
240 CleanupStack::Pop( aServerUri ); |
|
241 CleanupStack::PopAndDestroy( view ); |
|
242 view = NULL; |
|
243 |
|
244 if( textValue.Length() == 0 ) |
|
245 { |
|
246 // Impossible to continue because bearer (textValue) is needed to browse further |
|
247 CleanupStack::PopAndDestroy( db ); |
|
248 return; |
|
249 } |
|
250 |
|
251 // Put aServerUri back on the cleanup stack |
|
252 CleanupStack::PushL( aServerUri ); |
|
253 |
|
254 // Create new view to bearer table |
|
255 view = db->OpenViewMatchingUintLC( |
|
256 textValue, |
|
257 TPtrC( WAP_ACCESS_POINT_ID ), |
|
258 aAccessPointLink ); |
|
259 |
|
260 // There should be only one record with aAccessPointLink |
|
261 if( view->GotoFirstRecord() != KErrNone ) |
|
262 { |
|
263 // If no record for 'aAccessPointLink' there's nothing to look for |
|
264 CleanupStack::PopAndDestroy( view ); // view |
|
265 CleanupStack::Pop( aServerUri ); |
|
266 CleanupStack::PopAndDestroy( db ); |
|
267 return; |
|
268 } |
|
269 |
|
270 // Get AccessPoint |
|
271 // This function leaves if the column has NULL value |
|
272 TRAP( error, view->ReadUintL( TPtrC( WAP_IAP ), num32Value ) ); |
|
273 |
|
274 // Current view not needed any more |
|
275 CleanupStack::PopAndDestroy( view ); // view |
|
276 view = NULL; |
|
277 |
|
278 if( error == KErrNone ) |
|
279 { |
|
280 aAccessPoint = num32Value; |
|
281 } |
|
282 else |
|
283 { |
|
284 CleanupStack::Pop( aServerUri ); |
|
285 CleanupStack::PopAndDestroy( db ); |
|
286 return; |
|
287 } |
|
288 |
|
289 // Create view to IAP table |
|
290 view = db->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aAccessPoint ); |
|
291 |
|
292 // There should be only one record with aAccessPoint |
|
293 if( view->GotoFirstRecord() != KErrNone ) |
|
294 { |
|
295 // no record found |
|
296 CleanupStack::PopAndDestroy( view ); // view |
|
297 CleanupStack::Pop( aServerUri ); |
|
298 CleanupStack::PopAndDestroy( db ); |
|
299 aAccessPoint = 0; // Client will know that the procedure failed |
|
300 return; |
|
301 } |
|
302 |
|
303 // Get servicetype and -identifier |
|
304 TRAP( error, |
|
305 { |
|
306 view->ReadTextL( TPtrC( IAP_SERVICE_TYPE ), textValue ); // read service type |
|
307 view->ReadUintL( TPtrC( IAP_SERVICE ), num32Value ); // read service identifier |
|
308 }); |
|
309 if( error ) |
|
310 { |
|
311 // Leave occurred, cleaning up |
|
312 CleanupStack::PopAndDestroy( view ); // view |
|
313 CleanupStack::Pop( aServerUri ); |
|
314 CleanupStack::PopAndDestroy( db ); |
|
315 aAccessPoint = 0; // Client will know that the procedure failed |
|
316 return; |
|
317 } |
|
318 |
|
319 // Current view not needed any more |
|
320 CleanupStack::PopAndDestroy( view ); |
|
321 view = NULL; |
|
322 |
|
323 // Create view to Proxy table |
|
324 view = db->OpenViewOnProxyRecordLC( num32Value, textValue ); |
|
325 // There should be only one record matching service identifier and service type |
|
326 if( view->GotoFirstRecord() != KErrNone ) |
|
327 { |
|
328 CleanupStack::PopAndDestroy( view ); // view |
|
329 CleanupStack::Pop( aServerUri ); |
|
330 CleanupStack::PopAndDestroy( db ); |
|
331 return; |
|
332 } |
|
333 |
|
334 // Get information whether proxy is used or not |
|
335 TRAP( error, view->ReadBoolL( TPtrC( PROXY_USE_PROXY_SERVER ), aProxyUsed ) ); |
|
336 if ( error != KErrNone ) |
|
337 { |
|
338 CleanupStack::PopAndDestroy( view ); // view |
|
339 CleanupStack::Pop( aServerUri ); |
|
340 CleanupStack::PopAndDestroy( db ); |
|
341 return; |
|
342 } |
|
343 |
|
344 // If proxy is to be used, get the related information |
|
345 if( aProxyUsed ) |
|
346 { |
|
347 // Get proxy port number |
|
348 TRAP( error, view->ReadUintL( TPtrC( PROXY_PORT_NUMBER ), num32Value ) ); |
|
349 if( error != KErrNone ) |
|
350 { |
|
351 CleanupStack::PopAndDestroy( view ); // view |
|
352 CleanupStack::Pop( aServerUri ); |
|
353 CleanupStack::PopAndDestroy( db ); |
|
354 return; |
|
355 } |
|
356 |
|
357 if( num32Value > KMaxTUint16 ) |
|
358 { |
|
359 // Proxy port has too big value, access point is invalid |
|
360 CleanupStack::PopAndDestroy( view ); // view |
|
361 CleanupStack::Pop( aServerUri ); |
|
362 CleanupStack::PopAndDestroy( db ); |
|
363 |
|
364 User::Leave( KErrTooBig ); |
|
365 } |
|
366 |
|
367 // Following LIT is the proxy port number beginning with ":" |
|
368 _LIT( KProxyPort,":%d" ); |
|
369 HBufC* tempProxyPort = NULL; |
|
370 HBufC* tempProxyServerName = NULL; |
|
371 tempProxyServerName = view->ReadLongTextLC( TPtrC( PROXY_SERVER_NAME ) ); |
|
372 tempProxyServerName->Des().Trim(); // remove possible spaces |
|
373 |
|
374 tempProxyPort = HBufC::NewLC( KMaxProxyPortLength ); |
|
375 TPtr ptr2( tempProxyPort -> Des() ); |
|
376 ptr2.Format( KProxyPort,num32Value ); |
|
377 |
|
378 // Create a TPtr object to aProxyAddress |
|
379 // Proxy address must always be us-ascii or we are in trouble. |
|
380 TPtr ptr( tempProxyServerName -> Des() ); |
|
381 aProxyAddress = HBufC8::NewLC( |
|
382 ( tempProxyServerName->Length() ) + ( tempProxyPort->Length() ) ); |
|
383 aProxyAddress->Des().Copy( ptr ); |
|
384 aProxyAddress->Des().Append( ptr2 ); |
|
385 CleanupStack::Pop( aProxyAddress ); |
|
386 CleanupStack::PopAndDestroy( tempProxyPort ); |
|
387 CleanupStack::PopAndDestroy( tempProxyServerName ); |
|
388 } // aProxyUsed |
|
389 |
|
390 CleanupStack::PopAndDestroy( view ); // view |
|
391 view = NULL; |
|
392 CleanupStack::Pop( aServerUri ); |
|
393 CleanupStack::PopAndDestroy( db ); |
|
394 |
|
395 #ifdef _MMSCONNINIT_LOGGING_ |
|
396 TPtr temp = aServerUri->Des(); |
|
397 TMmsConnInitLogger::Log( _L("aServerUri: %S"), &temp ); |
|
398 TMmsConnInitLogger::Log( _L("aAccessPoint: %d"), aAccessPoint ); |
|
399 TMmsConnInitLogger::Log( _L("aProxyUsed: %d"), aProxyUsed ); |
|
400 /* |
|
401 if( aProxyAddress != NULL ) |
|
402 { |
|
403 TMmsConnInitLogger::Log( _L("aProxyAddress: %S"), &temp ); |
|
404 } |
|
405 */ |
|
406 #endif |
|
407 } |
|
408 |
|
409 // ----------------------------------------------------------------------------- |
|
410 // CheckNetworkL |
|
411 // ----------------------------------------------------------------------------- |
|
412 // |
|
413 TBool CMmsConnectionInitiator::CheckNetworkL() |
|
414 { |
|
415 #ifdef __WINS__ |
|
416 // Emulator has network always "available" |
|
417 return ETrue; |
|
418 #endif // __WINS__ |
|
419 |
|
420 TInt value = 0; |
|
421 TInt error = RProperty::Get( KUidSystemCategory, KUidNetworkStatus.iUid, value ); |
|
422 User::LeaveIfError( error ); |
|
423 |
|
424 #ifdef _MMSCONNINIT_LOGGING_ |
|
425 if ( value == ESANetworkAvailable ) |
|
426 { |
|
427 TMmsConnInitLogger::Log( _L("Network available") ); |
|
428 } |
|
429 else |
|
430 { |
|
431 TMmsConnInitLogger::Log( _L("Network NOT available, value = %d"), value ); |
|
432 } |
|
433 #endif |
|
434 |
|
435 return ( value == ESANetworkAvailable ); |
|
436 } |
|
437 |
|
438 // ----------------------------------------------------------------------------- |
|
439 // CMmsConnectionInitiator::CheckWapStartPageL |
|
440 // |
|
441 // Private fuction used only by GetParametersL. Made just for splitting too big |
|
442 // GetParameters function. |
|
443 // Adds http scheme in the beginning of wap start page if it is missing. It does |
|
444 // not add it into comms database. |
|
445 // |
|
446 // ----------------------------------------------------------------------------- |
|
447 // |
|
448 void CMmsConnectionInitiator::CheckWapStartPageL(HBufC*& aUri) |
|
449 { |
|
450 |
|
451 aUri->Des().Trim(); // remove spaces |
|
452 |
|
453 if ( aUri->Find(KHttpSchemePart2) > 0) |
|
454 { |
|
455 ;// OK, nothing needs to be done; |
|
456 } |
|
457 else if (aUri->Find(KHttpSchemePart2) == 0) |
|
458 { |
|
459 // NOK, adding 'KHttpSchemePart1' to the beginning of the uri |
|
460 HBufC* tmp = HBufC::NewMaxLC( aUri->Length() + KMmsScheme1Length ); |
|
461 tmp->Des().Copy( KHttpSchemePart1() ); |
|
462 tmp->Des().Append( aUri->Des() ); |
|
463 CleanupStack::Pop( tmp ); |
|
464 CleanupStack::PopAndDestroy( aUri ); |
|
465 aUri = tmp; |
|
466 CleanupStack::PushL(aUri); |
|
467 |
|
468 } |
|
469 else // HttpScheme2 not found in this case |
|
470 { |
|
471 // NOK, adding 'KHttpScheme' to the beginning of the uri |
|
472 |
|
473 HBufC* tmp = HBufC::NewMaxLC( aUri->Length() + KMmsHTTPSchemeLength ); |
|
474 tmp->Des().Copy( KHttpSchemePart1() ); |
|
475 tmp->Des().Append( KHttpSchemePart2() ); |
|
476 tmp->Des().Append( aUri->Des() ); |
|
477 |
|
478 CleanupStack::Pop( tmp ); |
|
479 CleanupStack::PopAndDestroy( aUri ); |
|
480 aUri = tmp; |
|
481 CleanupStack::PushL(aUri); |
|
482 } |
|
483 } |
|
484 |
|
485 // ----------------------------------------------------------------------------- |
|
486 // CMmsConnectionInitiator::FindIapL |
|
487 // WAP Acces Point is given as in-parameter and IAP is |
|
488 // retruned as out-parameter |
|
489 // Return value is EFalse if something goes wrong |
|
490 // Leavings are trapped in case of error in reading CommsDb |
|
491 // ----------------------------------------------------------------------------- |
|
492 // |
|
493 TBool CMmsConnectionInitiator::FindIapL( TUint32 aWapAP, TUint32& aIap ) |
|
494 { |
|
495 aIap = 0; |
|
496 TUint32 num32Value = 0; |
|
497 TInt error = KErrNone; |
|
498 CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified ); |
|
499 CleanupStack::PushL( db ); |
|
500 CCommsDbTableView* view; |
|
501 |
|
502 TBuf<KCommsDbSvrMaxFieldLength> textValue; // Max limit defined by database |
|
503 |
|
504 // Start from the WAP access point table |
|
505 // If there is no WAP access point table, the function leaves. |
|
506 view=db->OpenViewMatchingUintLC( |
|
507 TPtrC( WAP_ACCESS_POINT ), |
|
508 TPtrC( COMMDB_ID ), |
|
509 aWapAP ); |
|
510 if ( view->GotoFirstRecord() != KErrNone ) |
|
511 { |
|
512 CleanupStack::PopAndDestroy( view ); |
|
513 CleanupStack::PopAndDestroy( db ); |
|
514 return EFalse; |
|
515 } |
|
516 |
|
517 // Link to bearer table |
|
518 TRAP( error, view->ReadTextL( TPtrC( WAP_CURRENT_BEARER ), textValue ) ); |
|
519 if ( error != KErrNone) |
|
520 { |
|
521 CleanupStack::PopAndDestroy( view ); |
|
522 CleanupStack::PopAndDestroy( db ); |
|
523 return EFalse; |
|
524 } |
|
525 |
|
526 CleanupStack::PopAndDestroy( view ); // view |
|
527 view = NULL; |
|
528 |
|
529 // Found WAP access point. Now we need the WAP bearer |
|
530 view=db->OpenViewMatchingUintLC( textValue, TPtrC( WAP_ACCESS_POINT_ID ), |
|
531 aWapAP ); |
|
532 if ( view->GotoFirstRecord() != KErrNone ) |
|
533 { |
|
534 CleanupStack::PopAndDestroy( view ); |
|
535 CleanupStack::PopAndDestroy( db ); |
|
536 return EFalse; |
|
537 } |
|
538 |
|
539 //Let's trap the leave if there is no IAP and try to continue normally |
|
540 TRAP( error, view->ReadUintL( TPtrC( WAP_IAP ), num32Value ) ); |
|
541 CleanupStack::PopAndDestroy( view ); |
|
542 CleanupStack::PopAndDestroy( db ); |
|
543 if ( error == KErrNone ) |
|
544 { |
|
545 aIap = num32Value; |
|
546 return ETrue; |
|
547 } |
|
548 else |
|
549 { |
|
550 return EFalse; |
|
551 } |
|
552 } |
|
553 |
|
554 // ----------------------------------------------------------------------------- |
|
555 // CMmsConnectionInitiator::StartConnectionL |
|
556 // Checks if there is already connections open and checks if the |
|
557 // connection could be reused or not. |
|
558 // ----------------------------------------------------------------------------- |
|
559 // |
|
560 void CMmsConnectionInitiator::StartConnectionL(TUint32 aIap) |
|
561 { |
|
562 #ifdef _MMSCONNINIT_LOGGING_ |
|
563 TMmsConnInitLogger::Log( _L("CMmsConnectionInitiator::StartConnectionL") ); |
|
564 #endif |
|
565 TUint count; |
|
566 TPckgBuf<TConnectionInfo> connInfo; |
|
567 TUint i; |
|
568 TUint32 iap; |
|
569 HBufC* gprsApn1 = NULL; |
|
570 HBufC* gprsApn2 = NULL; |
|
571 TUint32 pdpType1 = 0; |
|
572 TUint32 pdpType2 = 0; |
|
573 iap = aIap; |
|
574 |
|
575 #ifdef _MMSCONNINIT_LOGGING_ |
|
576 TMmsConnInitLogger::Log( _L("iConnection->EnumerateConnections") ); |
|
577 #endif |
|
578 iConnection->EnumerateConnections( count ); |
|
579 |
|
580 #ifdef _MMSCONNINIT_LOGGING_ |
|
581 TMmsConnInitLogger::Log( _L("Connection count: %d"),count); |
|
582 #endif |
|
583 |
|
584 if ( count > 0 && FindGprsParametersL( aIap,pdpType1,gprsApn1 ) ) |
|
585 { |
|
586 CleanupStack::PushL(gprsApn1); |
|
587 for ( i=1; i<=count; i++ ) |
|
588 { |
|
589 if ( gprsApn2 ) |
|
590 { |
|
591 delete gprsApn2; |
|
592 gprsApn2 = NULL; |
|
593 } |
|
594 #ifdef _MMSCONNINIT_LOGGING_ |
|
595 TMmsConnInitLogger::Log( _L("iConnection->GetConnectionInfo ") ); |
|
596 #endif |
|
597 iConnection->GetConnectionInfo( i,connInfo ); |
|
598 #ifdef _MMSCONNINIT_LOGGING_ |
|
599 TMmsConnInitLogger::Log( _L("FindGprsParametersL ") ); |
|
600 #endif |
|
601 if ( FindGprsParametersL( connInfo().iIapId,pdpType2,gprsApn2 ) |
|
602 && pdpType1 == pdpType2 |
|
603 && *gprsApn1 == *gprsApn2 ) |
|
604 { |
|
605 #ifdef _MMSCONNINIT_LOGGING_ |
|
606 TMmsConnInitLogger::Log( _L("APN MATCH !!!!!!!") ); |
|
607 #endif |
|
608 iap = connInfo().iIapId; |
|
609 } |
|
610 } |
|
611 } |
|
612 if ( gprsApn2 ) |
|
613 { |
|
614 delete gprsApn2; |
|
615 } |
|
616 if ( gprsApn1 ) |
|
617 { |
|
618 CleanupStack::PopAndDestroy( gprsApn1 ); |
|
619 } |
|
620 |
|
621 iPrefs.SetIapId( iap ); |
|
622 #ifdef _MMSCONNINIT_LOGGING_ |
|
623 TMmsConnInitLogger::Log( _L("iConnection->Start ") ); |
|
624 #endif |
|
625 TInt error = RProperty::Define( KMPMCathegory, KMPMPropertyKeyMMS, KMPMPropertyTypeMMS ); |
|
626 if ( error == KErrNone || error == KErrAlreadyExists ) |
|
627 { |
|
628 // If the setting of the value does not succeed, a disconnect dialog |
|
629 // may be displayed - but there is nothing we can do about it. |
|
630 // We try our best. |
|
631 #ifdef _MMSCONNINIT_LOGGING_ |
|
632 TMmsConnInitLogger::Log( _L("setting KMPMProperty key to %d "), iap ); |
|
633 #endif |
|
634 error = RProperty::Set( KMPMCathegory, KMPMPropertyKeyMMS, iap ); |
|
635 } |
|
636 // iConnection cannot be active when we come here. |
|
637 // And it is not possible to ask ir RConnection is active |
|
638 iConnection->Start( iPrefs, iStatus ); |
|
639 return; |
|
640 } |
|
641 |
|
642 // ----------------------------------------------------------------------------- |
|
643 // CMmsConnectionInitiator::FindGprsParametersL |
|
644 // Solves PDP type and GPRS Access Point. |
|
645 // ----------------------------------------------------------------------------- |
|
646 |
|
647 TBool CMmsConnectionInitiator::FindGprsParametersL( |
|
648 TUint32 aIap, TUint32& aPdpType, HBufC*& aGprsApn ) |
|
649 { |
|
650 #ifdef _MMSCONNINIT_LOGGING_ |
|
651 TMmsConnInitLogger::Log( _L("CMmsConnectionInitiator::FindGprsParameters") ); |
|
652 TMmsConnInitLogger::Log( _L("IAP to analyze: %d"),aIap); |
|
653 #endif |
|
654 TUint32 service=0; |
|
655 TBuf <KCommsDbSvrMaxFieldLength> textValue; |
|
656 CCommsDbTableView* view = NULL; |
|
657 |
|
658 CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified ); |
|
659 CleanupStack::PushL( db ); |
|
660 view = db->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aIap ); |
|
661 if ( view->GotoFirstRecord() == KErrNone ) |
|
662 { |
|
663 view->ReadTextL( TPtrC( IAP_SERVICE_TYPE ), textValue ); |
|
664 #ifdef _MMSCONNINIT_LOGGING_ |
|
665 TMmsConnInitLogger::Log (_L("IAP_SERVICE_TYPE: ")); |
|
666 TMmsConnInitLogger::Log(textValue); |
|
667 #endif |
|
668 if ( textValue.Compare( TPtrC( OUTGOING_GPRS ) ) != 0 ) |
|
669 { |
|
670 CleanupStack::PopAndDestroy( view ); |
|
671 CleanupStack::PopAndDestroy( db ); |
|
672 return EFalse; |
|
673 } |
|
674 view->ReadUintL( TPtrC( IAP_SERVICE ), service ); |
|
675 } |
|
676 else |
|
677 { |
|
678 CleanupStack::PopAndDestroy( view ); |
|
679 CleanupStack::PopAndDestroy( db ); |
|
680 return EFalse; |
|
681 } |
|
682 CleanupStack::PopAndDestroy( view ); //view |
|
683 view = NULL; |
|
684 |
|
685 view = db->OpenViewMatchingUintLC( textValue, TPtrC( COMMDB_ID ), service ); |
|
686 if ( view->GotoFirstRecord() == KErrNone ) |
|
687 { |
|
688 aGprsApn = view->ReadLongTextLC( TPtrC( GPRS_APN ) ); |
|
689 view->ReadUintL( TPtrC( GPRS_PDP_TYPE ),aPdpType ); |
|
690 #ifdef _MMSCONNINIT_LOGGING_ |
|
691 TMmsConnInitLogger::Log( _L("GPRS_APN: ")); |
|
692 TMmsConnInitLogger::Log(aGprsApn->Des()); |
|
693 TMmsConnInitLogger::Log( _L("aPdpType: %d"),aPdpType); |
|
694 #endif |
|
695 CleanupStack::Pop( aGprsApn ); |
|
696 CleanupStack::PopAndDestroy( view ); |
|
697 CleanupStack::PopAndDestroy( db ); |
|
698 } |
|
699 else |
|
700 { |
|
701 CleanupStack::PopAndDestroy( view ); |
|
702 CleanupStack::PopAndDestroy( db ); |
|
703 return EFalse; |
|
704 } |
|
705 return ETrue; |
|
706 } |
|
707 |
|
708 // ----------------------------------------------------------------------------- |
|
709 // RunL |
|
710 // ----------------------------------------------------------------------------- |
|
711 // |
|
712 void CMmsConnectionInitiator::RunL() |
|
713 { |
|
714 // immediately release the access point |
|
715 #ifdef _MMSCONNINIT_LOGGING_ |
|
716 TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKeyMMS") ); |
|
717 #endif |
|
718 RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS ); |
|
719 |
|
720 iConnection->Progress( iProgress ); |
|
721 #ifdef _MMSCONNINIT_LOGGING_ |
|
722 TMmsConnInitLogger::Log( _L("MmsConnInit::RunL, status: %d"), iStatus.Int() ); |
|
723 TMmsConnInitLogger::Log( _L(" - progress stage: %d, progress error: %d"), iProgress.iStage, iProgress.iError ); |
|
724 #endif |
|
725 |
|
726 // In error situation, set iStatus to the error |
|
727 // error form iProgress overrides status only if status is KErrNone |
|
728 // The behavior of lower level components has changed. |
|
729 // We are trying to adjust our behavior to the new situation. |
|
730 |
|
731 if ( iTimerRunning ) |
|
732 { |
|
733 // own timer timed out |
|
734 iTimer.Close(); |
|
735 iStatus = KErrCompletion; |
|
736 iTimerRunning = EFalse; |
|
737 } |
|
738 |
|
739 if ( iStatus.Int() == KErrNone ) |
|
740 { |
|
741 iStatus = iProgress.iError; |
|
742 } |
|
743 |
|
744 if ( iStatus.Int() == KErrNotFound || iStatus.Int() == KErrGeneral ) |
|
745 { |
|
746 // We should never pass KErrNotFound upwards as it will |
|
747 // prevent retry loop, and might prevent fetching altogether. |
|
748 // KErrGeneral does not mean anything, so we try if we can find |
|
749 // a better error code from progress. |
|
750 if ( iProgress.iError < KErrGeneral ) |
|
751 { |
|
752 // We have some error code in iProgress, and it is not |
|
753 // KErrNotFound or KErrGeneral |
|
754 iStatus = iProgress.iError; |
|
755 } |
|
756 else |
|
757 { |
|
758 // This is better than KErrNotFound. |
|
759 // It does not tell why the connection was not created, |
|
760 // but at least it leads to retry loop |
|
761 iStatus = KErrCouldNotConnect; |
|
762 } |
|
763 } |
|
764 |
|
765 if( iStatus.Int() == KErrNone ) |
|
766 { |
|
767 // iConnection.start completes with no error |
|
768 // In this succesfull case we set the client status |
|
769 // to index+1 of the AP array |
|
770 #ifdef _MMSCONNINIT_LOGGING_ |
|
771 TMmsConnInitLogger::Log( _L("- Connected") ); |
|
772 #endif |
|
773 User::RequestComplete( iClientStatus, ( iIndex + 1 ) ); |
|
774 return; |
|
775 } |
|
776 else // status not equal to KErrNone |
|
777 { |
|
778 TTime now; |
|
779 now.UniversalTime(); |
|
780 TTimeIntervalSeconds timeout = 0; |
|
781 TInt overflow; |
|
782 if ( iStatus.Int() == KErrTimedOut ) |
|
783 { |
|
784 #ifdef _MMSCONNINIT_LOGGING_ |
|
785 TMmsConnInitLogger::Log( _L("- Timed out") ); |
|
786 #endif |
|
787 overflow = now.SecondsFrom( iStartTime, timeout ); |
|
788 if ( overflow == KErrNone && |
|
789 timeout.Int() < KMmsShortTimeout && |
|
790 iRetryCount < KMmsMaxRetryCount ) |
|
791 { |
|
792 // worth retrying after a few seconds |
|
793 iRetryCount++; |
|
794 TInt error = iTimer.CreateLocal(); |
|
795 if ( error == KErrNone ) |
|
796 { |
|
797 // timer wants microseconds |
|
798 // iTimer cannot be running as it was closed just a while ago |
|
799 // And we just said "CreateLocal()" so this is a brand new timer. |
|
800 iTimer.After( iStatus, KMmsRetryInterval * KMmsSecondsToMilliseconds ); |
|
801 iTimerRunning = ETrue; |
|
802 SetActive(); |
|
803 return; |
|
804 } |
|
805 } |
|
806 } |
|
807 |
|
808 #ifdef _MMSCONNINIT_LOGGING_ |
|
809 TMmsConnInitLogger::Log( _L("- Not connected") ); |
|
810 #endif |
|
811 // Because we now completed with an error we must re-issue the |
|
812 // request if there are still items in the array |
|
813 TUint32 ap; //IAP to be resolved |
|
814 if ( iStatus != KErrCompletion ) |
|
815 { |
|
816 // KErrCompletion means our timer completed |
|
817 // and we must retry the same access point. |
|
818 // If we have some other error, we must try next access point |
|
819 iIndex++; |
|
820 } |
|
821 else |
|
822 { |
|
823 #ifdef _MMSCONNINIT_LOGGING_ |
|
824 TMmsConnInitLogger::Log( _L("- Timer completed - retry %d"), iRetryCount ); |
|
825 #endif |
|
826 } |
|
827 for( iIndex = iIndex; iIndex < iArray->Count(); iIndex++ ) |
|
828 { |
|
829 // index is safe |
|
830 if( ( FindIapL( iArray->At( iIndex ), ap ) ) ) |
|
831 { |
|
832 StartConnectionL( ap ); |
|
833 SetActive(); |
|
834 return; |
|
835 } |
|
836 // Loop until AP found |
|
837 } |
|
838 // Looped through the whole array with no success |
|
839 User::RequestComplete( iClientStatus, iStatus.Int() ); |
|
840 return; |
|
841 } |
|
842 } |
|
843 |
|
844 // --------------------------------------------------------- |
|
845 // |
|
846 // --------------------------------------------------------- |
|
847 // |
|
848 TInt CMmsConnectionInitiator::RunError(TInt aError) |
|
849 { |
|
850 User::RequestComplete( iClientStatus, aError ); |
|
851 return KErrNone; |
|
852 } |
|
853 |
|
854 // ----------------------------------------------------------------------------- |
|
855 // CMmsConnectionInitiator::DoCancel |
|
856 // Cancels any outstanding request |
|
857 // ----------------------------------------------------------------------------- |
|
858 // |
|
859 void CMmsConnectionInitiator::DoCancel() |
|
860 { |
|
861 //This function is called by Cancel() if there is an |
|
862 //request outstanding. |
|
863 #ifdef _MMSCONNINIT_LOGGING_ |
|
864 TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKeyMMS") ); |
|
865 #endif |
|
866 RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS ); |
|
867 if ( iTimerRunning ) |
|
868 { |
|
869 iTimer.Cancel(); |
|
870 iTimer.Close(); |
|
871 iTimerRunning = EFalse; |
|
872 } |
|
873 iConnection->Close(); |
|
874 User::RequestComplete( iClientStatus, KErrCancel ); |
|
875 #ifdef _MMSCONNINIT_LOGGING_ |
|
876 TMmsConnInitLogger::Log( _L("MmsConnInit cancelled") ); |
|
877 #endif |
|
878 } |
|
879 |
|
880 // ----------------------------------------------------------------------------- |
|
881 #ifdef _MMSCONNINIT_LOGGING_ |
|
882 const TInt KLogBufferLength = 256; |
|
883 _LIT(KLogDir, "mmss"); |
|
884 _LIT(KLogFile, "mmsconninit.txt"); |
|
885 |
|
886 void TMmsConnInitLogger::Log(TRefByValue<const TDesC> aFmt,...) |
|
887 { |
|
888 VA_LIST list; |
|
889 VA_START(list, aFmt); |
|
890 |
|
891 // Print to log file |
|
892 TBuf<KLogBufferLength> buf; |
|
893 buf.FormatList(aFmt, list); |
|
894 |
|
895 // Write to log file |
|
896 RFileLogger::Write(KLogDir, KLogFile, EFileLoggingModeAppend, buf); |
|
897 } |
|
898 #endif |
|
899 |
|
900 // =========================== OTHER EXPORTED FUNCTIONS ======================== |
|
901 |
|
902 // End of File |