|
1 /* |
|
2 * Copyright (c) 2006-2009 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: sip connection |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 |
|
23 #ifdef _DEBUG |
|
24 #include <f32file.h> |
|
25 #endif |
|
26 |
|
27 #include <badesca.h> |
|
28 |
|
29 // sip api |
|
30 #include <sip.h> |
|
31 #include <sipconnection.h> |
|
32 #include <sipconnectionobserver.h> |
|
33 #include <sipresponseelements.h> |
|
34 #include <siprequestelements.h> |
|
35 #include <sipclienttransaction.h> |
|
36 #include <siprefresh.h> |
|
37 #include <sipmessageelements.h> |
|
38 #include <sipsubscribedialogassoc.h> |
|
39 #include <sipregistrationcontext.h> |
|
40 |
|
41 // sip codec api |
|
42 #include <sipfromheader.h> |
|
43 #include <siptoheader.h> |
|
44 #include <sipexpiresheader.h> |
|
45 #include <sipeventheader.h> |
|
46 #include <sipcontenttypeheader.h> |
|
47 #include <sipaddress.h> |
|
48 #include <sipstrings.h> |
|
49 #include <sipstrconsts.h> |
|
50 #include <sipextensionheader.h> |
|
51 #include <sipsubscriptionstateheader.h> |
|
52 #include <sipsupportedheader.h> |
|
53 #include <sipacceptheader.h> |
|
54 |
|
55 #include <cvimpstsettingsstore.h> |
|
56 |
|
57 // own simple |
|
58 #include "simplesipconnection.h" |
|
59 #include "simplesipconnectionobserver.h" |
|
60 #include "simplesipprofileobserver.h" |
|
61 #include "simplerefreshtimer.h" |
|
62 #include "msimpleenginerequest.h" |
|
63 #include "simpleerrors.h" |
|
64 |
|
65 #ifdef _DEBUG |
|
66 #include "simpledebugutils.h" |
|
67 #ifdef __LOCAL_MODE |
|
68 // INTERNAL TEST SUITE |
|
69 #include "simplelocalmodeutils.h" |
|
70 #endif |
|
71 #endif |
|
72 |
|
73 _LIT8 ( KSimpleWINFO, "winfo"); |
|
74 _LIT8 ( KSimplePRESENCE_LOW, "presence"); |
|
75 _LIT8 ( KSimpleEventlist, "eventlist"); |
|
76 _LIT8 ( KSimpleId, "id"); |
|
77 _LIT8 ( KSimpleAnonymous, "\"Anonymous\" <sip:anonymous@anonymous.invalid>"); |
|
78 _LIT8 ( KSimpleDeactivated, "deactivated" ); |
|
79 _LIT8 ( KSimpleProbation, "probation" ); |
|
80 _LIT8 ( KSimpleRejected, "rejected" ); |
|
81 _LIT8 ( KSimpleTimeout, "timeout" ); |
|
82 _LIT8 ( KSimpleGiveup, "giveup" ); |
|
83 _LIT8 ( KSimpleNoresource, "Noresource" ); |
|
84 _LIT8 ( KSipPrefix, "sip:" ); |
|
85 |
|
86 // ================= MEMBER FUNCTIONS ======================= |
|
87 // |
|
88 |
|
89 // ---------------------------------------------------------- |
|
90 // CSimpleSipConnection::CSimpleSipConnection |
|
91 // ---------------------------------------------------------- |
|
92 // |
|
93 CSimpleSipConnection::CSimpleSipConnection() |
|
94 : iSip(NULL), iSipConnection(NULL), iConnectionObserver(NULL), |
|
95 iSipState( ESimpleSipInactive ), |
|
96 iRequestList(CSimpleRequest::LinkOffset()), |
|
97 iCurrentNbrSubs( 0 ) |
|
98 { |
|
99 } |
|
100 |
|
101 // ---------------------------------------------------------- |
|
102 // CSimpleSipConnection::~CSimpleSipConnection |
|
103 // ---------------------------------------------------------- |
|
104 // |
|
105 EXPORT_C CSimpleSipConnection::~CSimpleSipConnection() |
|
106 { |
|
107 #ifdef _DEBUG |
|
108 TSimpleLogger::Log(_L("SipConnection: DESTRUCTOR this=%d" ), (TInt)this ); |
|
109 iFs.Close(); |
|
110 #endif |
|
111 delete iSipConnection; |
|
112 delete iProfileObserver; |
|
113 delete iConnectionObserver; |
|
114 delete iSip; |
|
115 DeleteRequests(); |
|
116 DeleteRequests( CSimpleRequest::EReqReceiveIM ); |
|
117 SIPStrings::Close(); |
|
118 } |
|
119 |
|
120 // ---------------------------------------------------------- |
|
121 // CSimpleSipConnection::NewL |
|
122 // ---------------------------------------------------------- |
|
123 // |
|
124 EXPORT_C CSimpleSipConnection* CSimpleSipConnection::NewL() |
|
125 { |
|
126 CSimpleSipConnection* self = new (ELeave) CSimpleSipConnection; |
|
127 CleanupStack::PushL( self ); |
|
128 self->ConstructL(); |
|
129 CleanupStack::Pop( self ); |
|
130 return self; |
|
131 } |
|
132 |
|
133 // ---------------------------------------------------------- |
|
134 // CSimpleSipConnection::ConstructL |
|
135 // ---------------------------------------------------------- |
|
136 // |
|
137 void CSimpleSipConnection::ConstructL() |
|
138 { |
|
139 #ifdef _DEBUG |
|
140 TSimpleLogger::Log( |
|
141 _L("SipConnection: ConstructL 20-01-07 this=%d" ), (TInt)this ); |
|
142 #endif |
|
143 |
|
144 iConnectionObserver = CSimpleSipConnectionObserver::NewL( *this); |
|
145 SIPStrings::OpenL(); |
|
146 // read static cenrep settings |
|
147 iSettings.ReadCentRepSettings(); |
|
148 |
|
149 #ifdef _DEBUG |
|
150 // read ini file for debug version settings |
|
151 (void)iFs.Connect(); |
|
152 TRAP_IGNORE(iSettings.ReadIniFileL( iFs )); |
|
153 #endif |
|
154 } |
|
155 |
|
156 // ---------------------------------------------------------- |
|
157 // CSimpleSipConnection::DispatchReqL |
|
158 // ---------------------------------------------------------- |
|
159 // |
|
160 EXPORT_C void CSimpleSipConnection::DispatchReqL( MSimpleEngineRequest& aReq ) |
|
161 { |
|
162 MSimpleEngineRequest::TSimpleRequest type = aReq.RequestType(); |
|
163 |
|
164 #ifdef _DEBUG |
|
165 TSimpleLogger::Log(_L("SipConnection: DispatchReqL type=%d this=%d" ), |
|
166 type, (TInt)this ); |
|
167 #endif |
|
168 |
|
169 switch ( type ) |
|
170 { |
|
171 case MSimpleEngineRequest::ERegister: |
|
172 aReq.SetRefreshTime( 0 ); |
|
173 RegisterL( aReq ); |
|
174 break; |
|
175 case MSimpleEngineRequest::ESendIM: |
|
176 aReq.SetRefreshTime( 0 ); |
|
177 SendInstantMessageL( aReq ); |
|
178 break; |
|
179 case MSimpleEngineRequest::EReceiveIM: |
|
180 aReq.SetRefreshTime( 0 ); |
|
181 RequestInstantMessageReceivingL( aReq ); |
|
182 break; |
|
183 case MSimpleEngineRequest::EStartPublish: |
|
184 aReq.SetRefreshTime( iSettings.ExpiryPuhlish() ); |
|
185 StartPublishL( aReq ); |
|
186 break; |
|
187 case MSimpleEngineRequest::EPublishModify: |
|
188 ModifyPublishL( aReq ); |
|
189 break; |
|
190 case MSimpleEngineRequest::ESubscribe: |
|
191 aReq.SetRefreshTime( iSettings.ExpiryWatcher() ); |
|
192 SubscribeL( aReq); |
|
193 break; |
|
194 case MSimpleEngineRequest::ESubscribeStop: |
|
195 aReq.SetRefreshTime( 0 ); |
|
196 StopSubscribeL( aReq ); |
|
197 break; |
|
198 case MSimpleEngineRequest::ESubscribeGet: |
|
199 aReq.SetRefreshTime( 0 ); |
|
200 SubscribeL( aReq ); |
|
201 break; |
|
202 case MSimpleEngineRequest::ESubscribeWinfo: |
|
203 aReq.SetRefreshTime( iSettings.ExpiryWinfo() ); |
|
204 SubscribeWinfoL( aReq ); |
|
205 break; |
|
206 case MSimpleEngineRequest::ESubscribeLista: |
|
207 aReq.SetRefreshTime( iSettings.ExpiryWatcher() ); |
|
208 SubscribeListL( aReq ); |
|
209 break; |
|
210 case MSimpleEngineRequest::EStopPublish: |
|
211 aReq.SetRefreshTime( 0 ); |
|
212 StopPublishL( aReq ); |
|
213 break; |
|
214 case MSimpleEngineRequest::EListenEvents: |
|
215 aReq.SetRefreshTime( 0 ); |
|
216 ListenStatusL( aReq ); |
|
217 break; |
|
218 case MSimpleEngineRequest::EDestroy: |
|
219 DeleteRequest( aReq ); |
|
220 break; |
|
221 case MSimpleEngineRequest::EDestroyStart: |
|
222 DeleteRequestStart( aReq ); |
|
223 break; |
|
224 default: |
|
225 User::Leave( KErrNotSupported ); |
|
226 break; |
|
227 } |
|
228 } |
|
229 |
|
230 // ---------------------------------------------------------- |
|
231 // CSimpleSipConnection::SIPStatus |
|
232 // ---------------------------------------------------------- |
|
233 // |
|
234 EXPORT_C TUint CSimpleSipConnection::SIPStatus( |
|
235 TInt aOpId, TInt& aRetryAfter ) |
|
236 { |
|
237 #ifdef _DEBUG |
|
238 TSimpleLogger::Log(_L("SipConnection: SIPStatus this=%d" ), (TInt)this); |
|
239 #endif |
|
240 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
241 rIter.SetToFirst(); |
|
242 |
|
243 aRetryAfter = 0; |
|
244 |
|
245 while ( rIter ) |
|
246 { |
|
247 CSimpleRequest* req = rIter; |
|
248 rIter++; //lint !e1757 |
|
249 MSimpleEngineRequest& mr = req->Request(); |
|
250 if ( mr.OpId( ) == aOpId ) |
|
251 { |
|
252 aRetryAfter = req->RetryAfter(); |
|
253 return req->Status(); |
|
254 } |
|
255 } |
|
256 return 0; |
|
257 } |
|
258 |
|
259 // ---------------------------------------------------------- |
|
260 // CSimpleSipConnection::SIPState |
|
261 // ---------------------------------------------------------- |
|
262 // |
|
263 EXPORT_C TSimpleSipState CSimpleSipConnection::SIPState( ) |
|
264 { |
|
265 #ifdef _DEBUG |
|
266 TSimpleLogger::Log(_L("SipConnection: SIPState returns %d this=%d" ), |
|
267 iSipState, (TInt)this ); |
|
268 #endif |
|
269 return iSipState; |
|
270 } |
|
271 |
|
272 // ---------------------------------------------------------- |
|
273 // CSimpleSipConnection::CurrentSIPIdentityL |
|
274 // ---------------------------------------------------------- |
|
275 // |
|
276 EXPORT_C TPtrC8 CSimpleSipConnection::CurrentSIPIdentityL() |
|
277 { |
|
278 return iProfileObserver->GiveUserAorL(); |
|
279 } |
|
280 |
|
281 // ---------------------------------------------------------- |
|
282 // CSimpleSipConnection::SipSubscriptionState |
|
283 // ---------------------------------------------------------- |
|
284 // |
|
285 EXPORT_C MSimpleEngineRequest::TSimpleSipSubscriptionState CSimpleSipConnection::SipSubscriptionState( |
|
286 MSimpleEngineRequest& aReq ) |
|
287 { |
|
288 MSimpleEngineRequest::TSimpleSipSubscriptionState retVal = MSimpleEngineRequest::ESimpleStateNone; |
|
289 |
|
290 CSimpleRequest* r = GetCliRequest( aReq ); |
|
291 if ( r ) |
|
292 { |
|
293 retVal = r->SipSubscriptionState(); |
|
294 } |
|
295 else |
|
296 { |
|
297 } |
|
298 |
|
299 return retVal; |
|
300 } |
|
301 |
|
302 // ---------------------------------------------------------- |
|
303 // CSimpleSipConnection::RegisterL |
|
304 // ---------------------------------------------------------- |
|
305 // |
|
306 void CSimpleSipConnection::RegisterL( MSimpleEngineRequest& aReq ) |
|
307 { |
|
308 #ifdef _DEBUG |
|
309 TSimpleLogger::Log(_L("SipConnection: RegisterL" )); |
|
310 #endif |
|
311 // Check if already registered |
|
312 switch ( iSipState ) |
|
313 { |
|
314 case ESimpleSipInactive: |
|
315 { |
|
316 if ( !aReq.Aux() ) |
|
317 { |
|
318 // Default profile used |
|
319 RegisterDefaultL( aReq ); |
|
320 } |
|
321 else |
|
322 { |
|
323 RegisterAnyL( aReq ); |
|
324 } |
|
325 } |
|
326 break; |
|
327 case ESimpleSipActive: |
|
328 case ESimpleSipSuspend: |
|
329 // The sip connection is already registered, |
|
330 // return the callback. |
|
331 aReq.Complete( KErrNone ); |
|
332 break; |
|
333 case ESimpleSipIdle: |
|
334 { |
|
335 // already initiated, just wait |
|
336 // Save the request to wait a response |
|
337 CSimpleRequest* simpleR = CSimpleRequest::NewL( |
|
338 *this, aReq, CSimpleRequest::EReqRegister, aReq.RefreshTime()); |
|
339 iRequestList.AddLast( *simpleR ); |
|
340 } |
|
341 break; |
|
342 case ESimpleSipUnavailable: |
|
343 default: |
|
344 User::Leave( KErrNotFound ); |
|
345 break; |
|
346 }; //lint !e960 |
|
347 } |
|
348 |
|
349 // ---------------------------------------------------------- |
|
350 // CSimpleSipConnection::ListenStatusL |
|
351 // ---------------------------------------------------------- |
|
352 // |
|
353 void CSimpleSipConnection::ListenStatusL( MSimpleEngineRequest& aReq ) |
|
354 { |
|
355 #ifdef _DEBUG |
|
356 TSimpleLogger::Log(_L("SipConnection: ListenStatusL" )); |
|
357 #endif |
|
358 // Save the request to wait a response |
|
359 CSimpleRequest* simpleR = CSimpleRequest::NewL( |
|
360 *this, aReq, CSimpleRequest::EReqListenEvents, aReq.RefreshTime() ); |
|
361 iRequestList.AddLast( *simpleR ); |
|
362 } |
|
363 |
|
364 // ---------------------------------------------------------- |
|
365 // CSimpleSipConnection::RequestInstantMessageReceivingL |
|
366 // ---------------------------------------------------------- |
|
367 // |
|
368 void CSimpleSipConnection::RequestInstantMessageReceivingL( |
|
369 MSimpleEngineRequest& aReq ) |
|
370 { |
|
371 #ifdef _DEBUG |
|
372 TSimpleLogger::Log( _L( |
|
373 "CSimpleSipConnection::RequestInstantMessageReceivingL - Start" ) ); |
|
374 #endif |
|
375 |
|
376 // Create the request |
|
377 CSimpleRequest* request = CSimpleRequest::NewL( *this, |
|
378 aReq, CSimpleRequest::EReqReceiveIM, aReq.RefreshTime() ); |
|
379 |
|
380 // Save the request into queue |
|
381 iRequestList.AddLast( *request ); |
|
382 |
|
383 #ifdef _DEBUG |
|
384 TSimpleLogger::Log( _L( |
|
385 "CSimpleSipConnection::RequestInstantMessageReceivingL - End" ) ); |
|
386 #endif |
|
387 } |
|
388 |
|
389 // ---------------------------------------------------------- |
|
390 // CSimpleSipConnection::SendInstantMessageL |
|
391 // ---------------------------------------------------------- |
|
392 // |
|
393 void CSimpleSipConnection::SendInstantMessageL( MSimpleEngineRequest& aReq ) |
|
394 { |
|
395 #ifdef _DEBUG |
|
396 TSimpleLogger::Log( |
|
397 _L( "CSimpleSipConnection::SendInstantMessageL - Start" ) ); |
|
398 #endif |
|
399 |
|
400 // Create the request |
|
401 CSimpleRequest* request = CSimpleRequest::NewL( *this, aReq, |
|
402 CSimpleRequest::EReqSendIM, aReq.RefreshTime() ); |
|
403 CleanupStack::PushL( request ); // CS: 1 |
|
404 |
|
405 request->SetDataL( aReq.RequestData() ); |
|
406 request->SetRequestContentTypeL( aReq.RequestContentType() ); |
|
407 request->SetRefreshTime( aReq.RefreshTime() ); |
|
408 |
|
409 if ( ESimpleSipActive == iSipState ) |
|
410 { |
|
411 // Set request state |
|
412 request->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
413 const TDesC8& aContent = request->Data(); |
|
414 |
|
415 if ( !iSipConnection || ESimpleSipActive != iSipState || |
|
416 !iProfileObserver ) |
|
417 { |
|
418 User::Leave( KErrNotReady ); |
|
419 } |
|
420 |
|
421 MSIPRegistrationContext* regContext = iProfileObserver-> |
|
422 ProfileContext(); |
|
423 |
|
424 if ( !regContext ) |
|
425 { |
|
426 User::Leave( KErrNotReady ); |
|
427 } |
|
428 |
|
429 // Check CLIENT-OBJ-DATA-LIMIT |
|
430 TUint myLimit = iSettings.ObjLimit(); |
|
431 |
|
432 if ( myLimit && ( TUint )aContent.Size() > myLimit ) |
|
433 { |
|
434 // This is too big mesasge, an error is returned |
|
435 User::Leave( KSimpleErrSettingsLimit ); |
|
436 } |
|
437 |
|
438 // Get request URI from a request |
|
439 TUriParser8 parser; |
|
440 HBufC8* temp = HBufC8::NewLC( KSipPrefix().Length() + |
|
441 aReq.Recipient().Length() ); // CS: 2 |
|
442 temp->Des().Copy( KSipPrefix() ); |
|
443 temp->Des().Append( aReq.Recipient() ); |
|
444 User::LeaveIfError( parser.Parse( *temp )); |
|
445 CUri8* uri = CUri8::NewL( parser ); |
|
446 |
|
447 // Start to fill header, Remote URI |
|
448 CSIPRequestElements* elems = CSIPRequestElements::NewL( uri ); |
|
449 CleanupStack::PushL( elems ); // CS: 3 |
|
450 |
|
451 TUriParser8 parser3; |
|
452 User::LeaveIfError( parser3.Parse( iProfileObserver-> |
|
453 GiveUserAorL() )); |
|
454 uri = CUri8::NewL( parser3 ); |
|
455 CSIPAddress* sipAddress = CSIPAddress::NewL( uri ); |
|
456 |
|
457 // From Header |
|
458 CSIPFromHeader* fromH = CSIPFromHeader::NewL( sipAddress ); |
|
459 elems->SetFromHeaderL( fromH ); // fromH, ownership given to elems |
|
460 |
|
461 uri = CUri8::NewL( parser ); |
|
462 CSIPAddress* addr = CSIPAddress::NewL( uri ); |
|
463 // To Header |
|
464 CSIPToHeader* toHeader = CSIPToHeader::NewL( addr ); |
|
465 elems->SetToHeaderL( toHeader ); |
|
466 |
|
467 CSIPMessageElements& mesElems = elems->MessageElements(); |
|
468 |
|
469 // Add Expires Header |
|
470 if ( aReq.RefreshTime() ) |
|
471 { |
|
472 RPointerArray<CSIPHeaderBase> headers; |
|
473 CleanupClosePushL( headers ); // CS: 4 |
|
474 |
|
475 CSIPExpiresHeader* exprH = new (ELeave) CSIPExpiresHeader( |
|
476 aReq.RefreshTime() ); |
|
477 CleanupStack::PushL( exprH ); // CS: 5 |
|
478 User::LeaveIfError( headers.Append( exprH ) ); |
|
479 CleanupStack::Pop( exprH ); // CS: 4 |
|
480 |
|
481 mesElems.SetUserHeadersL( headers ); |
|
482 // headers ownership given to mesElems |
|
483 CleanupStack::Pop( &headers ); // CS: 3 |
|
484 } |
|
485 |
|
486 // Set content type and content |
|
487 HBufC8* buffer = aContent.AllocLC(); // CS: 4 |
|
488 CSIPContentTypeHeader* contTypeH = CSIPContentTypeHeader::NewL( |
|
489 KSimpleMediaType, KSimpleMediaSubType ); |
|
490 CleanupStack::Pop( buffer ); // CS: 3 |
|
491 mesElems.SetContentL( buffer, contTypeH ); |
|
492 // buffer ownership given to mesElems |
|
493 // contTypeH ownership given to mesElems |
|
494 |
|
495 // Set method |
|
496 elems->SetMethodL( SIPStrings::StringF( SipStrConsts::EMessage ) ); |
|
497 |
|
498 CleanupStack::Pop( elems ); // CS: 2 |
|
499 // Send the request transaction |
|
500 // elems, ownership given |
|
501 CSIPClientTransaction* sipTrans = iSipConnection->SendRequestL( elems, |
|
502 *regContext ); |
|
503 |
|
504 // Save SIP client transaction |
|
505 request->SetTransaction( sipTrans ); |
|
506 |
|
507 CleanupStack::PopAndDestroy( temp ); // CS: 1 |
|
508 |
|
509 // Start refresh timer, it's used for garbage collection too. |
|
510 request->StartRefreshTimer(); |
|
511 } |
|
512 else if ( iSipState == ESimpleSipSuspend ) |
|
513 { |
|
514 request->SetReqState( CSimpleRequest::ESimplePendingInit ); |
|
515 } |
|
516 else |
|
517 { |
|
518 User::Leave( KErrNotReady ); |
|
519 } |
|
520 |
|
521 // Save the request into queue |
|
522 iRequestList.AddLast( *request ); |
|
523 CleanupStack::Pop( request ); // CS: 0 |
|
524 |
|
525 // Update SOURCE-THROTTLE-PUBLISH time |
|
526 if ( iSettings.Throttle() ) |
|
527 { |
|
528 request->SetThrottleTime( iSettings.Throttle() ); |
|
529 } |
|
530 |
|
531 // Start timer to detect infinite wait situation |
|
532 request->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
533 |
|
534 #ifdef _DEBUG |
|
535 TSimpleLogger::Log( |
|
536 _L( "CSimpleSipConnection::SendInstantMessageL - End" ) ); |
|
537 #endif |
|
538 } |
|
539 |
|
540 // ---------------------------------------------------------- |
|
541 // CSimpleSipConnection::StartPublishL |
|
542 // ---------------------------------------------------------- |
|
543 // |
|
544 void CSimpleSipConnection::StartPublishL( |
|
545 MSimpleEngineRequest& aReq ) |
|
546 { |
|
547 #ifdef _DEBUG |
|
548 TSimpleLogger::Log(_L("SipConnection: StartPublishL" )); |
|
549 TSimpleLogger::Dump( aReq.RequestData(), iFs, 0 ); |
|
550 #endif |
|
551 |
|
552 // create the request |
|
553 CSimpleRequest* r = CSimpleRequest::NewL( *this, |
|
554 aReq, CSimpleRequest::EReqPublish, aReq.RefreshTime() ); |
|
555 CleanupStack::PushL( r ); |
|
556 r->SetDataL( aReq.RequestData() ); |
|
557 r->SetRequestContentTypeL( aReq.RequestContentType() ); |
|
558 |
|
559 // Set ETag if given |
|
560 if ( aReq.ETag().Length() ) |
|
561 { |
|
562 HBufC8* etagBuf = aReq.ETag().AllocL(); |
|
563 // Ownership is transferred |
|
564 r->SetETag( etagBuf ); |
|
565 } |
|
566 |
|
567 // save refresh time |
|
568 r->SetRefreshTime( aReq.RefreshTime() ); |
|
569 |
|
570 if ( iSipState == ESimpleSipActive ) |
|
571 { |
|
572 // set request state |
|
573 r->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
574 // Do the SIP Publish transaction |
|
575 CSIPClientTransaction* sipTrans = DoPublishL( |
|
576 iProfileObserver->GiveUserAorL(), |
|
577 aReq.RefreshTime(), |
|
578 r->Data(), |
|
579 r->ETag(), r->RequestContentType() ); |
|
580 // Save SIP client transaction |
|
581 r->SetTransaction( sipTrans ); |
|
582 |
|
583 // Start re-fresh timer, it's used for garbage collection too. |
|
584 // expires [ no refresh ] |
|
585 r->StartRefreshTimer(); |
|
586 } |
|
587 else if ( iSipState == ESimpleSipSuspend ) |
|
588 { |
|
589 r->SetReqState( CSimpleRequest::ESimplePendingInit ); |
|
590 } |
|
591 else |
|
592 { |
|
593 User::Leave( KErrNotReady ); |
|
594 } |
|
595 |
|
596 // Save the request into queue |
|
597 iRequestList.AddLast( *r ); |
|
598 CleanupStack::Pop( r ); |
|
599 |
|
600 // update SOURCE-THROTTLE-PUBLISH time |
|
601 if ( iSettings.Throttle() ) |
|
602 { |
|
603 r->SetThrottleTime( iSettings.Throttle() ); |
|
604 } |
|
605 |
|
606 // Start timer to detect infinite wait situation |
|
607 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
608 } |
|
609 |
|
610 // ---------------------------------------------------------- |
|
611 // CSimpleSipConnection::ModifyPublishL |
|
612 // ---------------------------------------------------------- |
|
613 // |
|
614 void CSimpleSipConnection::ModifyPublishL( |
|
615 MSimpleEngineRequest& aReq ) |
|
616 { |
|
617 #ifdef _DEBUG |
|
618 TSimpleLogger::Log(_L("SipConnection: ModifyPublishL" )); |
|
619 TSimpleLogger::Dump( aReq.RequestData(), iFs, 0 ); |
|
620 #endif |
|
621 |
|
622 // Get initial SIP transaction in order to get ETag value. |
|
623 CSimpleRequest* r = GetCliRequest( aReq ); |
|
624 if ( !r || r->ETag().Length() == 0 ) |
|
625 { |
|
626 User::Leave( KErrNotFound ); |
|
627 } |
|
628 |
|
629 // Check the request state is valid |
|
630 CSimpleRequest::TSimpleReqState myState = r->ReqState(); |
|
631 if ( myState != CSimpleRequest::ESimpleActive && |
|
632 myState != CSimpleRequest::ESimplePending && |
|
633 myState != CSimpleRequest::ESimpleRunning ) |
|
634 { |
|
635 User::Leave( KErrNotReady ); |
|
636 } |
|
637 |
|
638 // initialize SIP status |
|
639 r->SetStatus( 0 ); |
|
640 |
|
641 // check SOURCE-THROTTLE-PUBLISH |
|
642 TTime myTime; |
|
643 myTime.HomeTime(); |
|
644 if ( iSettings.Throttle() && myTime < r->ThrottleTime() ) |
|
645 { |
|
646 // Leave if not enough time elapsed since last publish |
|
647 // for this publication. |
|
648 User::Leave( KSimpleErrSettingsLimit ); |
|
649 } |
|
650 |
|
651 // send PUBLISH modify transaction if network is available |
|
652 if ( iSipState == ESimpleSipActive && |
|
653 myState != CSimpleRequest::ESimpleRunning ) |
|
654 { |
|
655 // set state |
|
656 r->SetReqState( CSimpleRequest::ESimpleRunning ); |
|
657 r->SetDataL( aReq.RequestData() ); |
|
658 r->SetRequestContentTypeL( aReq.RequestContentType() ); |
|
659 |
|
660 CSIPClientTransaction* sipTrans = DoPublishL( |
|
661 iProfileObserver->GiveUserAorL(), |
|
662 aReq.RefreshTime(), |
|
663 r->Data(), |
|
664 r->ETag(), r->RequestContentType() ); |
|
665 |
|
666 // save latest client transaction |
|
667 r->SetTransaction( sipTrans ); |
|
668 |
|
669 // Re-fresh timer is started in ok response, not yet here. |
|
670 |
|
671 // update SOURCE-THROTTLE-PUBLISH time |
|
672 if ( iSettings.Throttle() ) |
|
673 { |
|
674 r->SetThrottleTime( iSettings.Throttle() ); |
|
675 } |
|
676 } |
|
677 else if ( iSipState == ESimpleSipActive && |
|
678 myState == CSimpleRequest::ESimpleRunning ) |
|
679 { |
|
680 // not to send the ETag only. |
|
681 r->AddPendingState( CSimpleRequest::EPendingModify ); |
|
682 r->SetDataL( aReq.RequestData() ); |
|
683 } |
|
684 else if ( iSipState == ESimpleSipSuspend ) |
|
685 { |
|
686 // set state |
|
687 r->SetReqState( CSimpleRequest::ESimplePending ); |
|
688 // not to send the ETag only. |
|
689 r->AddPendingState( CSimpleRequest::EPendingModify ); |
|
690 r->SetDataL( aReq.RequestData() ); |
|
691 } |
|
692 else |
|
693 { |
|
694 // very rare situation |
|
695 User::Leave( KErrNotReady ); |
|
696 } |
|
697 |
|
698 // start expiry timer to detect infinite wait situation |
|
699 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
700 |
|
701 #ifdef _DEBUG |
|
702 TBuf<100> myETag; |
|
703 myETag.Copy( r->ETag() ); |
|
704 TSimpleLogger::Log(_L("SipConnection: ModifyPublishL ETag=%S" ), &myETag ); |
|
705 #endif |
|
706 } |
|
707 |
|
708 // ---------------------------------------------------------- |
|
709 // CSimpleSipConnection::StartToRefreshL |
|
710 // ---------------------------------------------------------- |
|
711 // |
|
712 void CSimpleSipConnection::StartToRefreshL( CSimpleRequest& aReq ) |
|
713 { |
|
714 #ifdef _DEBUG |
|
715 TSimpleLogger::Log(_L("SipConnection: StartToRefresh")); |
|
716 #endif |
|
717 |
|
718 // This refreshes PUBLISH request or makes garbage collection for |
|
719 // subscription without refresh. |
|
720 |
|
721 // There are two cases: normal re-publish |
|
722 // or expiration of publication |
|
723 |
|
724 if ( aReq.Match( CSimpleRequest::EReqPublish ) ) |
|
725 { |
|
726 // refresh[ network ] |
|
727 // time to retry |
|
728 // expires[ no refresh ] |
|
729 // expires |
|
730 DoRefreshPublishL( aReq ); |
|
731 } |
|
732 else if ( aReq.Match( CSimpleRequest::EReqSubscribe ) || |
|
733 aReq.Match( CSimpleRequest::EReqSubscribeList ) || |
|
734 aReq.Match( CSimpleRequest::EReqSubscribeWinfo )) |
|
735 { |
|
736 DoRefreshSubscribe( aReq ); |
|
737 } |
|
738 else |
|
739 { |
|
740 // No other cases |
|
741 } |
|
742 } |
|
743 |
|
744 // ---------------------------------------------------------- |
|
745 // CSimpleSipConnection::StopPublishL |
|
746 // ---------------------------------------------------------- |
|
747 // |
|
748 void CSimpleSipConnection::StopPublishL( |
|
749 MSimpleEngineRequest& aReq ) |
|
750 { |
|
751 #ifdef _DEBUG |
|
752 TSimpleLogger::Log(_L("SipConnection: StopPublishL" )); |
|
753 #endif |
|
754 |
|
755 CSIPClientTransaction* sipTrans = NULL; |
|
756 |
|
757 TBool stopETagScratch (EFalse); |
|
758 |
|
759 // Get SIP transaction in order to get ETag value. |
|
760 CSimpleRequest* r = GetCliRequest( aReq ); |
|
761 if ( !r && aReq.ETag().Length() == 0 ) |
|
762 { |
|
763 User::Leave( KErrNotFound ); |
|
764 } |
|
765 else if ( !r ) |
|
766 { |
|
767 // create the request |
|
768 r = CSimpleRequest::NewL( *this, |
|
769 aReq, CSimpleRequest::EReqPublish, aReq.RefreshTime() ); |
|
770 CleanupStack::PushL( r ); |
|
771 stopETagScratch = ETrue; |
|
772 } |
|
773 |
|
774 // Set ETag if given |
|
775 if ( aReq.ETag().Length() ) |
|
776 { |
|
777 HBufC8* etagBuf = aReq.ETag().AllocL(); |
|
778 // Ownership is transferred |
|
779 r->SetETag( etagBuf ); |
|
780 r->SetGivenETag( ETrue ); |
|
781 } |
|
782 |
|
783 // initialize SIP status |
|
784 r->SetStatus( 0 ); |
|
785 |
|
786 // refresh timer not needed |
|
787 r->StopRefreshTimer(); |
|
788 |
|
789 // set state |
|
790 r->SetReqState( CSimpleRequest::ESimpleStopping ); |
|
791 |
|
792 // Check if the transaction is pending or running |
|
793 if ( r->ETag().Length() == 0 ) |
|
794 { |
|
795 r->SetReqState( CSimpleRequest::ESimpleComplete ); |
|
796 r->Complete( KErrNone ); |
|
797 return; |
|
798 } |
|
799 |
|
800 // send PUBLISH transaction |
|
801 TRAPD( errx, sipTrans = DoPublishL( |
|
802 iProfileObserver->GiveUserAorL(), |
|
803 0, // 0 epiry headers value |
|
804 KNullDesC8, // request data |
|
805 r->ETag(), r->RequestContentType() )); |
|
806 if ( errx ) |
|
807 { |
|
808 // In error case complete the request immediately |
|
809 r->Complete( errx ); |
|
810 return; |
|
811 } |
|
812 |
|
813 // save latest client transaction |
|
814 r->SetTransaction( sipTrans ); |
|
815 |
|
816 // start expiry timer to detect infinite wait situation |
|
817 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
818 |
|
819 if ( stopETagScratch ) |
|
820 { |
|
821 // Save the request into queue |
|
822 iRequestList.AddLast( *r ); |
|
823 CleanupStack::Pop( r ); |
|
824 } |
|
825 } |
|
826 |
|
827 // ---------------------------------------------------------- |
|
828 // CSimpleSipConnection::SubscribeL |
|
829 // ---------------------------------------------------------- |
|
830 // |
|
831 void CSimpleSipConnection::SubscribeL( |
|
832 MSimpleEngineRequest& aReq ) |
|
833 { |
|
834 #ifdef _DEBUG |
|
835 TSimpleLogger::Log(_L("SipConnection: SubscribeL" )); |
|
836 #endif |
|
837 |
|
838 CSIPSubscribeDialogAssoc* subsDialog = NULL; |
|
839 |
|
840 // create the request |
|
841 CSimpleRequest* r = CSimpleRequest::NewL( *this, |
|
842 aReq, CSimpleRequest::EReqSubscribe, aReq.RefreshTime() ); |
|
843 CleanupStack::PushL( r ); |
|
844 |
|
845 if ( iSipState == ESimpleSipActive ) |
|
846 { |
|
847 r->SetDataL( aReq.RequestData() ); |
|
848 r->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
849 CSIPClientTransaction* sipTrans = DoSubscribeL( |
|
850 aReq.RemoteURI(), |
|
851 aReq.RefreshTime(), |
|
852 r->Data(), |
|
853 subsDialog, |
|
854 aReq.IsRefresh(), |
|
855 ESubsRegular, |
|
856 aReq.Aux() ? ETrue : EFalse ); |
|
857 // save SIP Dialog and SIP client transaction |
|
858 r->SetDialog( subsDialog ); |
|
859 r->SetTransaction( sipTrans ); |
|
860 } |
|
861 else if ( iSipState == ESimpleSipSuspend ) |
|
862 { |
|
863 r->SetReqState( CSimpleRequest::ESimplePendingInit ); |
|
864 } |
|
865 else |
|
866 { |
|
867 User::Leave( KErrNotReady ); |
|
868 } |
|
869 |
|
870 CleanupStack::Pop( r ); |
|
871 iRequestList.AddLast( *r ); |
|
872 |
|
873 // start timer to detect infinite wait situation |
|
874 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
875 |
|
876 if ( !aReq.IsRefresh() ) |
|
877 { |
|
878 // Start refresh timer for garbage colletion for |
|
879 // subscription not needing refresh. |
|
880 TUint myTime = ( aReq.RefreshTime() > iSettings.ExpiryApi() ? |
|
881 aReq.RefreshTime() : iSettings.ExpiryApi() ); |
|
882 r->SetRefreshTime( myTime ); |
|
883 r->StartRefreshTimer(); |
|
884 } |
|
885 // increase subscription counter |
|
886 IncreaseNbrSubs(); |
|
887 } |
|
888 |
|
889 // ---------------------------------------------------------- |
|
890 // CSimpleSipConnection::SubscribeListL |
|
891 // ---------------------------------------------------------- |
|
892 // |
|
893 void CSimpleSipConnection::SubscribeListL( |
|
894 MSimpleEngineRequest& aReq ) |
|
895 { |
|
896 #ifdef _DEBUG |
|
897 TSimpleLogger::Log(_L("SipConnection: SubscribeListL" )); |
|
898 #endif |
|
899 |
|
900 CSIPSubscribeDialogAssoc* subsDialog = NULL; |
|
901 |
|
902 // create the request |
|
903 CSimpleRequest* r = CSimpleRequest::NewL( *this, |
|
904 aReq, CSimpleRequest::EReqSubscribeList, aReq.RefreshTime() ); |
|
905 CleanupStack::PushL( r ); |
|
906 |
|
907 if ( iSipState == ESimpleSipActive ) |
|
908 { |
|
909 r->SetDataL( aReq.RequestData() ); |
|
910 r->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
911 CSIPClientTransaction* sipTrans = DoSubscribeL( |
|
912 aReq.RemoteURI(), |
|
913 aReq.RefreshTime(), |
|
914 r->Data(), |
|
915 subsDialog, |
|
916 aReq.IsRefresh(), |
|
917 ESubsList, |
|
918 aReq.Aux() ? ETrue : EFalse ); |
|
919 // save SIP Dialog and SIP client transaction |
|
920 r->SetDialog( subsDialog ); |
|
921 r->SetTransaction( sipTrans ); |
|
922 } |
|
923 else if ( iSipState == ESimpleSipUnavailable || iSipState == ESimpleSipIdle ) |
|
924 { |
|
925 User::Leave( KErrNotReady ); |
|
926 } |
|
927 else |
|
928 { |
|
929 r->SetReqState( CSimpleRequest::ESimplePendingInit ); |
|
930 } |
|
931 |
|
932 CleanupStack::Pop( r ); |
|
933 iRequestList.AddLast( *r ); |
|
934 |
|
935 // Start timer to detect infinite wait situation |
|
936 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
937 |
|
938 if ( !aReq.IsRefresh() ) |
|
939 { |
|
940 // Start refresh timer for garbage colletion for |
|
941 // subscription not needing refresh. |
|
942 TUint myTime = ( aReq.RefreshTime() > iSettings.ExpiryApi() ? |
|
943 aReq.RefreshTime() : iSettings.ExpiryApi() ); |
|
944 r->SetRefreshTime( myTime ); |
|
945 r->StartRefreshTimer(); |
|
946 } |
|
947 // increase subscription counter |
|
948 IncreaseNbrSubs(); |
|
949 } |
|
950 |
|
951 // ---------------------------------------------------------- |
|
952 // CSimpleSipConnection::SubscribeWinfoL |
|
953 // ---------------------------------------------------------- |
|
954 // |
|
955 void CSimpleSipConnection::SubscribeWinfoL( |
|
956 MSimpleEngineRequest& aReq ) |
|
957 { |
|
958 #ifdef _DEBUG |
|
959 TSimpleLogger::Log(_L("SipConnection: SubscribeWinfoL" )); |
|
960 #endif |
|
961 // get request-URI from SIP profiles |
|
962 TPtrC8 aor = iProfileObserver->GiveUserAorL(); |
|
963 aReq.SetRemoteURIL( aor ); |
|
964 |
|
965 CSIPSubscribeDialogAssoc* subsDialog = NULL; |
|
966 |
|
967 // create the request |
|
968 CSimpleRequest* r = CSimpleRequest::NewL( *this, |
|
969 aReq, CSimpleRequest::EReqSubscribeWinfo, aReq.RefreshTime() ); |
|
970 CleanupStack::PushL( r ); |
|
971 |
|
972 if ( iSipState == ESimpleSipActive ) |
|
973 { |
|
974 r->SetDataL( aReq.RequestData() ); |
|
975 r->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
976 CSIPClientTransaction* sipTrans = DoSubscribeL( |
|
977 aReq.RemoteURI(), |
|
978 aReq.RefreshTime(), |
|
979 r->Data(), |
|
980 subsDialog, |
|
981 ETrue, |
|
982 ESubsWinfo, |
|
983 EFalse ); |
|
984 // save SIP Dialog and SIP client transaction |
|
985 r->SetDialog( subsDialog ); |
|
986 r->SetTransaction( sipTrans ); |
|
987 } |
|
988 else if ( iSipState == ESimpleSipUnavailable || iSipState == ESimpleSipIdle ) |
|
989 { |
|
990 User::Leave( KErrNotReady ); |
|
991 } |
|
992 else |
|
993 { |
|
994 r->SetReqState( CSimpleRequest::ESimplePendingInit ); |
|
995 } |
|
996 |
|
997 CleanupStack::Pop( r ); |
|
998 iRequestList.AddLast( *r ); |
|
999 |
|
1000 // Start timer to detect infinite wait situation |
|
1001 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
1002 } |
|
1003 |
|
1004 // ---------------------------------------------------------- |
|
1005 // CSimpleSipConnection::StopSubscribeL |
|
1006 // ---------------------------------------------------------- |
|
1007 // |
|
1008 void CSimpleSipConnection::StopSubscribeL( |
|
1009 MSimpleEngineRequest& aReq ) |
|
1010 { |
|
1011 |
|
1012 #ifdef _DEBUG |
|
1013 TSimpleLogger::Log(_L("SipConnection: StopSubscribeL" )); |
|
1014 #endif |
|
1015 |
|
1016 // Get SIP transaction |
|
1017 CSimpleRequest* r = GetCliRequest( aReq ); |
|
1018 if ( !r ) |
|
1019 { |
|
1020 User::Leave( KErrNotFound ); |
|
1021 } |
|
1022 |
|
1023 CSIPSubscribeDialogAssoc* dialog = r->Dialog(); |
|
1024 if ( !dialog ) |
|
1025 { |
|
1026 User::Leave(KErrNotFound); |
|
1027 } |
|
1028 |
|
1029 if ( r->ReqState() == CSimpleRequest::ESimpleReTry || |
|
1030 r->ReqState() == CSimpleRequest::ESimplePendingInit || |
|
1031 r->ReqState() == CSimpleRequest::ESimplePending ) |
|
1032 { |
|
1033 // There is not active SIP dialog, |
|
1034 // therefore real stopping is not needed. |
|
1035 r->SetReqState( CSimpleRequest::ESimpleStopping ); |
|
1036 r->Request().SetResponseMethod( MSimpleEngineRequest::EUnknownResponse ); |
|
1037 r->Complete( KErrCompletion ); |
|
1038 return; |
|
1039 } |
|
1040 else if ( r->ReqState() == CSimpleRequest::ESimpleDeleting ) |
|
1041 { |
|
1042 // there is no active subscription |
|
1043 User::Leave( KErrNotFound ); |
|
1044 } |
|
1045 |
|
1046 // modify the old request entity |
|
1047 r->SetTransaction( NULL ); |
|
1048 |
|
1049 // create new unsubscribe transaction in the dialog |
|
1050 // Add accepted header |
|
1051 CSIPMessageElements* mesElems = CSIPMessageElements::NewLC(); |
|
1052 RPointerArray<CSIPHeaderBase> headers; |
|
1053 CleanupClosePushL( headers ); |
|
1054 // Accept header with application/pidf+xml is |
|
1055 // added for reqular subscription and list subscription |
|
1056 CSIPAcceptHeader* acceH = NULL; |
|
1057 TInt popCount(0); |
|
1058 |
|
1059 if ( r->Match( CSimpleRequest::EReqSubscribe ) || |
|
1060 r->Match( CSimpleRequest::EReqSubscribeList )) |
|
1061 { |
|
1062 acceH = CSIPAcceptHeader::NewLC( |
|
1063 KSimpleApplicationType, KSimplePidfSubType ); |
|
1064 User::LeaveIfError( headers.Append( acceH )); |
|
1065 ++popCount; |
|
1066 } |
|
1067 if ( r->Match( CSimpleRequest::EReqSubscribeList )) |
|
1068 { |
|
1069 acceH = CSIPAcceptHeader::NewLC( |
|
1070 KSimpleApplicationType, KSimpleListSubType ); |
|
1071 User::LeaveIfError( headers.Append( acceH )); |
|
1072 ++popCount; |
|
1073 |
|
1074 acceH = CSIPAcceptHeader::NewLC( |
|
1075 KSimpleMultiType, KSimpleMultipartSubType ); |
|
1076 User::LeaveIfError( headers.Append( acceH )); |
|
1077 ++popCount; |
|
1078 |
|
1079 // add supported header with value eventlist |
|
1080 RPointerArray<CSIPSupportedHeader> suppHs = |
|
1081 CSIPSupportedHeader::DecodeL( KSimpleEventlist); |
|
1082 for( TInt count=0; count < suppHs.Count(); count++ ) |
|
1083 { |
|
1084 User::LeaveIfError( headers.Append( suppHs[count] )); |
|
1085 } |
|
1086 suppHs.Close(); |
|
1087 } |
|
1088 if ( r->Match( CSimpleRequest::EReqSubscribeWinfo )) |
|
1089 { |
|
1090 acceH = CSIPAcceptHeader::NewLC( |
|
1091 KSimpleApplicationType, KSimpleWinfoSubType ); |
|
1092 User::LeaveIfError( headers.Append( acceH )); |
|
1093 ++popCount; |
|
1094 } |
|
1095 |
|
1096 // --------------------------------------------------------- |
|
1097 #ifdef _DEBUG |
|
1098 #ifdef __LOCAL_MODE |
|
1099 /** |
|
1100 * INTERNAL TEST SUITE |
|
1101 */ |
|
1102 CSimpleLocalModeUtils::AddTestHeaderL( headers ); |
|
1103 #endif |
|
1104 #endif |
|
1105 // --------------------------------------------------------- |
|
1106 |
|
1107 // add content |
|
1108 mesElems->SetUserHeadersL( headers ); |
|
1109 |
|
1110 // Pop AccessHeaders |
|
1111 CleanupStack::Pop( popCount ); |
|
1112 CleanupStack::PopAndDestroy( &headers ); |
|
1113 |
|
1114 // Send SUBSCRIBE message |
|
1115 CSIPClientTransaction* sipTrans = dialog->SendUnsubscribeL( mesElems ); |
|
1116 CleanupStack::Pop( mesElems ); |
|
1117 |
|
1118 // save client transaction |
|
1119 r->SetTransaction( sipTrans ); |
|
1120 |
|
1121 // Start timer to detect infinite wait situation |
|
1122 r->SetReqState( CSimpleRequest::ESimpleStopping ); |
|
1123 r->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
1124 } |
|
1125 |
|
1126 // ---------------------------------------------------------- |
|
1127 // CSimpleSipConnection::IncomingRequest |
|
1128 // ---------------------------------------------------------- |
|
1129 // |
|
1130 void CSimpleSipConnection::IncomingRequest( TUint32 /*aIapId*/, |
|
1131 CSIPServerTransaction* /*aTransaction*/) |
|
1132 { |
|
1133 // Nothing to do. |
|
1134 #ifdef _DEBUG |
|
1135 TSimpleLogger::Log(_L("SipConnection: IncomingRequest" )); |
|
1136 #endif |
|
1137 } |
|
1138 |
|
1139 // ---------------------------------------------------------- |
|
1140 // CSimpleSipConnection::TimedOut |
|
1141 // ---------------------------------------------------------- |
|
1142 // |
|
1143 void CSimpleSipConnection::TimedOut( CSIPServerTransaction& /*aTransaction*/) |
|
1144 { |
|
1145 // Nothing to do. |
|
1146 #ifdef _DEBUG |
|
1147 TSimpleLogger::Log(_L("SipConnection: TimeOut" )); |
|
1148 #endif |
|
1149 } |
|
1150 |
|
1151 // ---------------------------------------------------------- |
|
1152 // CSimpleSipConnection::ConnectionStateChange |
|
1153 // ---------------------------------------------------------- |
|
1154 // |
|
1155 void CSimpleSipConnection::ConnectionStateChange( |
|
1156 TSimpleSipState aState, TInt aSipError ) |
|
1157 { |
|
1158 #ifdef _DEBUG |
|
1159 TSimpleLogger::Log(_L("SipConnection: ConnectionStateChange %d->%d"), |
|
1160 iSipState, aState); |
|
1161 #endif |
|
1162 |
|
1163 // re-try to get connection |
|
1164 TSimpleSipState oldState = iSipState; |
|
1165 |
|
1166 RecognizeSipState( aState ); |
|
1167 |
|
1168 // Complete status event |
|
1169 if ( oldState != iSipState ) |
|
1170 { |
|
1171 CompleteStatusRequest(); |
|
1172 } |
|
1173 |
|
1174 // Profile observer gives active event and then the connection can be started to create. |
|
1175 if ( oldState == ESimpleSipIdle && aState == ESimpleSipActive ) |
|
1176 { |
|
1177 TRAPD( err, iSipConnection = iProfileObserver->GiveConnectionL() ); |
|
1178 if ( !err ) |
|
1179 { |
|
1180 SetSipState( ESimpleSipActive ); |
|
1181 // complete client requests |
|
1182 CompleteRegisterRequests( KErrNone ); |
|
1183 } |
|
1184 else if ( err != KErrNotReady ) |
|
1185 { |
|
1186 // error callback to SimpleEngine |
|
1187 SetSipState( ESimpleSipInactive ); |
|
1188 CompleteRegisterRequests( err ); |
|
1189 } |
|
1190 else |
|
1191 { |
|
1192 // KErrNotReady is a normal error indicating |
|
1193 // pending initialization. |
|
1194 } |
|
1195 } |
|
1196 else if ( iSipState == ESimpleSipUnavailable ) |
|
1197 { |
|
1198 iCurrentNbrSubs = 0; |
|
1199 // Complete all pending register requests with an error code |
|
1200 TInt retErr = aSipError ? aSipError : KErrDisconnected; |
|
1201 CompleteRegisterRequests( retErr ); |
|
1202 // Complete all active subscriptions and publications and |
|
1203 // call API callbacks. KErrDisconnected has a special handling |
|
1204 // in CSimpleRequest::Complete(). |
|
1205 CompleteRegularRequests( KErrDisconnected ); |
|
1206 } |
|
1207 else if ( iSipState == ESimpleSipInactive ) |
|
1208 { |
|
1209 iCurrentNbrSubs = 0; |
|
1210 // Complete all pending register requests with an error code |
|
1211 TInt retErr = aSipError ? aSipError : KErrDisconnected; |
|
1212 CompleteRegisterRequests( retErr ); |
|
1213 // All the dialogs and transactions are lost. |
|
1214 // Registeration is done automatically when state is active again. |
|
1215 // Complete all active subscriptions and publications and |
|
1216 // call API callbacks now. KErrDisconnected has a special handling |
|
1217 // in CSimpleRequest::Complete(). |
|
1218 CompleteRegularRequests( KErrDisconnected ); |
|
1219 } |
|
1220 else if ( iSipState == ESimpleSipSuspend ) |
|
1221 { |
|
1222 // Wait till the active state |
|
1223 } |
|
1224 else if ( oldState == ESimpleSipSuspend && iSipState == ESimpleSipActive ) |
|
1225 { |
|
1226 // Scan all the pending requests and start to proceed them |
|
1227 HandlePendings(); |
|
1228 } |
|
1229 else |
|
1230 { |
|
1231 // nothing to do |
|
1232 } |
|
1233 } |
|
1234 |
|
1235 // ---------------------------------------------------------- |
|
1236 // CSimpleSipConnection::HandleReceivedMessage |
|
1237 // ---------------------------------------------------------- |
|
1238 // |
|
1239 TInt CSimpleSipConnection::HandleReceivedMessage( const TDesC8& aFrom, |
|
1240 const TDesC8& aContent ) |
|
1241 { |
|
1242 #ifdef _DEBUG |
|
1243 TSimpleLogger::Log( _L("CSimpleSipConnection::HandleReceivedMessage") ); |
|
1244 #endif |
|
1245 TInt error( KErrNone ); |
|
1246 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1247 rIter.SetToFirst(); |
|
1248 |
|
1249 while ( rIter ) |
|
1250 { |
|
1251 CSimpleRequest* req = rIter; |
|
1252 rIter++; //lint !e1757 |
|
1253 |
|
1254 if ( req->Match( CSimpleRequest::EReqReceiveIM ) ) |
|
1255 { |
|
1256 TRAP( error, DoHandleReceivedMessageL( aFrom, aContent, *req ) ) |
|
1257 } |
|
1258 } |
|
1259 |
|
1260 // KErrNoMemory is returned here if error occurred when allocating |
|
1261 // memory for heap descriptors in DoHandleReceivedMessageL |
|
1262 return error; |
|
1263 } |
|
1264 |
|
1265 // ---------------------------------------------------------- |
|
1266 // CSimpleSipConnection::ConnectionChanged |
|
1267 // ---------------------------------------------------------- |
|
1268 // |
|
1269 void CSimpleSipConnection::ConnectionChanged() |
|
1270 { |
|
1271 #ifdef _DEBUG |
|
1272 TSimpleLogger::Log(_L("SipConnection: ConnectionChanged")); |
|
1273 if( iSipConnection ) |
|
1274 { |
|
1275 TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : old conn state %d (internal:%d)"), iSipConnection->State(), iSipState ); |
|
1276 TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : old IAP %d"), iSipConnection->IapId() ); |
|
1277 } |
|
1278 #endif |
|
1279 |
|
1280 iCurrentNbrSubs = 0; |
|
1281 CSIPConnection* conn = NULL; |
|
1282 TRAPD( err, conn = iProfileObserver->GiveConnectionL() ); |
|
1283 if( !err ) |
|
1284 { |
|
1285 delete iSipConnection; |
|
1286 iSipConnection = conn; |
|
1287 #ifdef _DEBUG |
|
1288 TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : new conn state %d"), iSipConnection->State() ); |
|
1289 TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : new IAP %d"), iSipConnection->IapId() ); |
|
1290 #endif |
|
1291 } |
|
1292 #ifdef _DEBUG |
|
1293 else |
|
1294 { |
|
1295 TSimpleLogger::Log(_L("SipConnection: ConnectionChanged : Get SIP connection error %d"), err ); |
|
1296 } |
|
1297 #endif |
|
1298 |
|
1299 if( iSipConnection ) |
|
1300 { |
|
1301 if( iSipState != iSipConnection->State() ) |
|
1302 { |
|
1303 iConnectionObserver->ConnectionStateChanged( iSipConnection->State() ); |
|
1304 } |
|
1305 } |
|
1306 } |
|
1307 |
|
1308 // ---------------------------------------------------------- |
|
1309 // CSimpleSipConnection::StartToCheckExpiryL |
|
1310 // ---------------------------------------------------------- |
|
1311 // |
|
1312 void CSimpleSipConnection::StartToCheckExpiryL( CSimpleRequest& aReq ) |
|
1313 { |
|
1314 #ifdef _DEBUG |
|
1315 TSimpleLogger::Log(_L("SipConnection: StartToCheckExpiryL")); |
|
1316 #endif |
|
1317 |
|
1318 // This is expired |
|
1319 aReq.Complete( KErrTimedOut ); |
|
1320 } |
|
1321 |
|
1322 // ---------------------------------------------------------- |
|
1323 // CSimpleSipConnection::GetRequest |
|
1324 // ---------------------------------------------------------- |
|
1325 // |
|
1326 CSimpleRequest* CSimpleSipConnection::GetRequest( |
|
1327 CSIPClientTransaction& aTrans ) |
|
1328 { |
|
1329 // Search the correspoding request element |
|
1330 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1331 rIter.SetToFirst(); |
|
1332 |
|
1333 while ( rIter ) |
|
1334 { |
|
1335 CSimpleRequest* req = rIter; |
|
1336 rIter++; //lint !e1757 |
|
1337 if ( req->Match( aTrans )) |
|
1338 { |
|
1339 return req; |
|
1340 } |
|
1341 } |
|
1342 |
|
1343 return (CSimpleRequest*)NULL; |
|
1344 } |
|
1345 |
|
1346 // ---------------------------------------------------------- |
|
1347 // CSimpleSipConnection::GetCliRequest |
|
1348 // ---------------------------------------------------------- |
|
1349 // |
|
1350 CSimpleRequest* CSimpleSipConnection::GetCliRequest( |
|
1351 MSimpleEngineRequest& aReq ) |
|
1352 { |
|
1353 // Search the correspoding request element |
|
1354 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1355 rIter.SetToFirst(); |
|
1356 |
|
1357 while ( rIter ) |
|
1358 { |
|
1359 CSimpleRequest* req = rIter; |
|
1360 rIter++; //lint !e1757 |
|
1361 if ( req->Match( aReq )) |
|
1362 { |
|
1363 return req; |
|
1364 } |
|
1365 } |
|
1366 |
|
1367 return (CSimpleRequest*)NULL; |
|
1368 } |
|
1369 |
|
1370 // ---------------------------------------------------------- |
|
1371 // CSimpleSipConnection::GetdDialogRequest |
|
1372 // ---------------------------------------------------------- |
|
1373 // |
|
1374 CSimpleRequest* CSimpleSipConnection::GetdDialogRequest( const CSIPDialog& aDialog ) |
|
1375 { |
|
1376 // Search the correspoding request element |
|
1377 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1378 rIter.SetToFirst(); |
|
1379 |
|
1380 while ( rIter ) |
|
1381 { |
|
1382 CSimpleRequest* req = rIter; |
|
1383 rIter++; //lint !e1757 |
|
1384 if ( req->Match( aDialog )) |
|
1385 { |
|
1386 return req; |
|
1387 } |
|
1388 } |
|
1389 |
|
1390 return (CSimpleRequest*)NULL; |
|
1391 } |
|
1392 |
|
1393 // ----------------------------------------------------------------------------- |
|
1394 // CSimpleSipConnection::DeleteRequests |
|
1395 // ----------------------------------------------------------------------------- |
|
1396 void CSimpleSipConnection::DeleteRequests() |
|
1397 { |
|
1398 #ifdef _DEBUG |
|
1399 TSimpleLogger::Log(_L("SipConnection: DeleteRequests" )); |
|
1400 #endif |
|
1401 // Delete all buffered transaction requests |
|
1402 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1403 rIter.SetToFirst(); |
|
1404 |
|
1405 while ( rIter ) |
|
1406 { |
|
1407 CSimpleRequest* req = rIter; |
|
1408 rIter++; //lint !e1757 |
|
1409 |
|
1410 // open request EReqReceiveIM should not be deleted |
|
1411 // will be deleted only when im message received |
|
1412 // or destructor is called. |
|
1413 if ( !req->Match( CSimpleRequest::EReqReceiveIM ) ) |
|
1414 { |
|
1415 req->Destroy(); |
|
1416 } |
|
1417 } |
|
1418 } |
|
1419 |
|
1420 // ----------------------------------------------------------------------------- |
|
1421 // CSimpleSipConnection::DeleteRequests |
|
1422 // ----------------------------------------------------------------------------- |
|
1423 void CSimpleSipConnection::DeleteRequests( |
|
1424 CSimpleRequest::TSimpleSipReqType aRequestType ) |
|
1425 { |
|
1426 #ifdef _DEBUG |
|
1427 TSimpleLogger::Log(_L("SipConnection: DeleteRequests type=%d" ), |
|
1428 aRequestType ); |
|
1429 #endif |
|
1430 // Delete buffered transaction requests match to the aRequestType |
|
1431 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1432 rIter.SetToFirst(); |
|
1433 |
|
1434 while ( rIter ) |
|
1435 { |
|
1436 CSimpleRequest* req = rIter; |
|
1437 rIter++; //lint !e1757 |
|
1438 |
|
1439 if ( req->Match( aRequestType ) ) |
|
1440 { |
|
1441 req->Destroy(); |
|
1442 } |
|
1443 } |
|
1444 } |
|
1445 |
|
1446 // ----------------------------------------------------------------------------- |
|
1447 // CSimpleSipConnection::DeleteRequest |
|
1448 // ----------------------------------------------------------------------------- |
|
1449 void CSimpleSipConnection::DeleteRequest( MSimpleEngineRequest& aReq ) |
|
1450 { |
|
1451 #ifdef _DEBUG |
|
1452 TSimpleLogger::Log(_L("SipConnection: DeleteRequest" )); |
|
1453 #endif |
|
1454 |
|
1455 CSimpleRequest* r = CSimpleSipConnection::GetCliRequest( aReq ); |
|
1456 if ( r ) |
|
1457 { |
|
1458 if ( r->Match( CSimpleRequest::EReqSubscribe ) || |
|
1459 r->Match( CSimpleRequest::EReqSubscribeList ) ) |
|
1460 { |
|
1461 DecreaseNbrSubs(); |
|
1462 } |
|
1463 r->Destroy(); |
|
1464 } |
|
1465 } |
|
1466 |
|
1467 // ----------------------------------------------------------------------------- |
|
1468 // CSimpleSipConnection::DeleteRequestStart |
|
1469 // ----------------------------------------------------------------------------- |
|
1470 void CSimpleSipConnection::DeleteRequestStart( MSimpleEngineRequest& aReq ) |
|
1471 { |
|
1472 #ifdef _DEBUG |
|
1473 TSimpleLogger::Log(_L("SipConnection: DeleteRequestStart" )); |
|
1474 #endif |
|
1475 |
|
1476 CSimpleRequest* r = CSimpleSipConnection::GetCliRequest( aReq ); |
|
1477 if ( r ) |
|
1478 { |
|
1479 if ( r->Match( CSimpleRequest::EReqSubscribe ) || |
|
1480 r->Match( CSimpleRequest::EReqSubscribeList )) |
|
1481 { |
|
1482 DecreaseNbrSubs(); |
|
1483 } |
|
1484 r->DestroyStart(); |
|
1485 } |
|
1486 } |
|
1487 |
|
1488 // ----------------------------------------------------------------------------- |
|
1489 // CSimpleSipConnection::CompleteRegisterRequests |
|
1490 // ----------------------------------------------------------------------------- |
|
1491 void CSimpleSipConnection::CompleteRegisterRequests( TInt aStatus ) |
|
1492 { |
|
1493 #ifdef _DEBUG |
|
1494 TSimpleLogger::Log(_L("SipConnection: CompleteRegisterRequests %d" ), aStatus); |
|
1495 #endif |
|
1496 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1497 rIter.SetToFirst(); |
|
1498 |
|
1499 while ( rIter ) |
|
1500 { |
|
1501 CSimpleRequest* req = rIter; |
|
1502 rIter++; //lint !e1757 |
|
1503 if ( req->Match( CSimpleRequest::EReqRegister )) |
|
1504 { |
|
1505 req->Complete( aStatus ); |
|
1506 // Open request can be deletetd after completion. |
|
1507 req->Destroy(); |
|
1508 } |
|
1509 } |
|
1510 } |
|
1511 |
|
1512 // ----------------------------------------------------------------------------- |
|
1513 // CSimpleSipConnection::CompleteRegularRequests |
|
1514 // ----------------------------------------------------------------------------- |
|
1515 void CSimpleSipConnection::CompleteRegularRequests( TInt aStatus ) |
|
1516 { |
|
1517 #ifdef _DEBUG |
|
1518 TSimpleLogger::Log(_L("SipConnection: CompleteRegularRequests %d" ), aStatus); |
|
1519 #endif |
|
1520 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1521 rIter.SetToFirst(); |
|
1522 |
|
1523 while ( rIter ) |
|
1524 { |
|
1525 CSimpleRequest* req = rIter; |
|
1526 rIter++; //lint !e1757 |
|
1527 if ( req->Match( CSimpleRequest::EReqPublish ) || |
|
1528 req->Match( CSimpleRequest::EReqSubscribe ) || |
|
1529 req->Match( CSimpleRequest::EReqSubscribeList ) || |
|
1530 req->Match( CSimpleRequest::EReqSubscribeWinfo )) |
|
1531 { |
|
1532 req->SetReason( KErrNone ); |
|
1533 req->Request().SetResponseMethod( MSimpleEngineRequest::EUnknownResponse ); |
|
1534 req->Complete( aStatus ); |
|
1535 } |
|
1536 } |
|
1537 } |
|
1538 |
|
1539 // ----------------------------------------------------------------------------- |
|
1540 // CSimpleSipConnection::CompleteStatusRequest |
|
1541 // ----------------------------------------------------------------------------- |
|
1542 void CSimpleSipConnection::CompleteStatusRequest( ) |
|
1543 { |
|
1544 #ifdef _DEBUG |
|
1545 TSimpleLogger::Log(_L("SipConnection: CompleteStatusRequest" ) ); |
|
1546 #endif |
|
1547 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
1548 rIter.SetToFirst(); |
|
1549 |
|
1550 while ( rIter ) |
|
1551 { |
|
1552 CSimpleRequest* req = rIter; |
|
1553 rIter++; //lint !e1757 |
|
1554 if ( req->Match( CSimpleRequest::EReqListenEvents )) |
|
1555 { |
|
1556 req->CompleteEvent( ); |
|
1557 return; |
|
1558 } |
|
1559 } |
|
1560 } |
|
1561 |
|
1562 // ---------------------------------------------------------- |
|
1563 // CSimpleSipConnection::DoPublishL |
|
1564 // ---------------------------------------------------------- |
|
1565 // |
|
1566 CSIPClientTransaction* CSimpleSipConnection::DoPublishL( |
|
1567 const TDesC8& aRemoteURI, TInt aExpiry, |
|
1568 const TDesC8& aContent, const TDesC8& aSipIfMatch, |
|
1569 const TDesC8& aContentType ) |
|
1570 { |
|
1571 #ifdef _DEBUG |
|
1572 TBuf<100> testBuf; |
|
1573 testBuf.Copy( aSipIfMatch ); |
|
1574 TSimpleLogger::Log(_L("SipConnection: DoPublishL expiry=%d sip-if-match=%S" ), |
|
1575 aExpiry, &testBuf); |
|
1576 #endif |
|
1577 |
|
1578 TBool multi( EFalse ); |
|
1579 |
|
1580 if ( aContent.Length() && |
|
1581 aContentType.CompareF( KSimpleDocumentType )) |
|
1582 { |
|
1583 // content exists and not pidf+xml (not refresh) |
|
1584 multi = ETrue; |
|
1585 } |
|
1586 |
|
1587 if ( !iSipConnection || iSipState != ESimpleSipActive || !iProfileObserver ) |
|
1588 { |
|
1589 User::Leave( KErrNotReady ); |
|
1590 } |
|
1591 |
|
1592 MSIPRegistrationContext* regContext = iProfileObserver->ProfileContext(); |
|
1593 if ( !regContext ) |
|
1594 { |
|
1595 User::Leave( KErrNotReady ); |
|
1596 } |
|
1597 |
|
1598 // Check CLIENT-OBJ-DATA-LIMIT |
|
1599 TUint myLimit = iSettings.ObjLimit(); |
|
1600 // Breakpoint: |
|
1601 if ( myLimit && (TUint)aContent.Size() > myLimit ) |
|
1602 { |
|
1603 // This is too big mesasge, an error is returned |
|
1604 User::Leave( KSimpleErrSettingsLimit ); |
|
1605 } |
|
1606 |
|
1607 // get request uri from a request |
|
1608 TUriParser8 parser; |
|
1609 User::LeaveIfError( parser.Parse( aRemoteURI )); |
|
1610 CUri8* uri = CUri8::NewLC( parser ); |
|
1611 |
|
1612 // Start to fill headres, Remote URI |
|
1613 CSIPRequestElements* elems = CSIPRequestElements::NewL(uri); |
|
1614 CleanupStack::Pop( uri); // ownership given to elems |
|
1615 CleanupStack::PushL( elems ); |
|
1616 // To header not needed when remote uri set |
|
1617 |
|
1618 uri = CUri8::NewLC( parser ); |
|
1619 CSIPAddress* sipAddress = CSIPAddress::NewL( uri ); |
|
1620 CleanupStack::Pop( uri ); // ownership given to sipAddress |
|
1621 CleanupStack::PushL( sipAddress ); |
|
1622 |
|
1623 // From header |
|
1624 CSIPFromHeader* fromH = CSIPFromHeader::NewL( sipAddress ); |
|
1625 CleanupStack::Pop( sipAddress ); // ownership given to FromHeader |
|
1626 CleanupStack::PushL( fromH ); |
|
1627 elems->SetFromHeaderL( fromH ); |
|
1628 CleanupStack::Pop( fromH ); // fromH, ownership given to elems |
|
1629 |
|
1630 // start to add other headers |
|
1631 RPointerArray<CSIPHeaderBase> headers; |
|
1632 CleanupClosePushL(headers); |
|
1633 |
|
1634 // Expires header |
|
1635 CSIPExpiresHeader* exprH = new (ELeave) CSIPExpiresHeader(aExpiry); |
|
1636 CleanupStack::PushL( exprH ); |
|
1637 User::LeaveIfError( headers.Append( exprH )); |
|
1638 CleanupStack::Pop( exprH ); // exprH |
|
1639 |
|
1640 // Event header |
|
1641 CSIPEventHeader* eventH = CSIPEventHeader::NewLC( KSimplePRESENCE_LOW ); |
|
1642 User::LeaveIfError( headers.Append( eventH )); |
|
1643 CleanupStack::Pop( eventH ); // eventH |
|
1644 |
|
1645 // create SIP-ETAG header with CSIPExtensionHeader |
|
1646 if ( aSipIfMatch.Length() ) |
|
1647 { |
|
1648 CSIPExtensionHeader* etagH = CSIPExtensionHeader::NewLC( |
|
1649 KSimpleSipIfMatch, aSipIfMatch ); |
|
1650 User::LeaveIfError( headers.Append( etagH )); |
|
1651 CleanupStack::Pop( etagH ); // etagH |
|
1652 } |
|
1653 |
|
1654 // --------------------------------------------------------- |
|
1655 #ifdef _DEBUG |
|
1656 #ifdef __LOCAL_MODE |
|
1657 /** |
|
1658 * INTERNAL TEST SUITE |
|
1659 */ |
|
1660 CSimpleLocalModeUtils::AddTestHeaderL( headers ); |
|
1661 #endif |
|
1662 #endif |
|
1663 // --------------------------------------------------------- |
|
1664 |
|
1665 CSIPMessageElements& mesElems = elems->MessageElements(); |
|
1666 mesElems.SetUserHeadersL( headers ); |
|
1667 CleanupStack::PopAndDestroy( &headers ); |
|
1668 |
|
1669 // set Content type and content |
|
1670 |
|
1671 CSIPContentTypeHeader* contTypeH = NULL; |
|
1672 if ( aContent.Length() ) //lint !e830 |
|
1673 { |
|
1674 if ( multi ) |
|
1675 { |
|
1676 // Set CID and Boundary parameters as well |
|
1677 // *************************************** |
|
1678 /* |
|
1679 HBufC8* contentTypeB = HBufC8::NewLC( |
|
1680 NSimpleDocument::NSimpleMulti::KContentTypeSize + |
|
1681 NSimpleDocument::KSimpleBoundarySize ); // << contentTypeB |
|
1682 TPtr8 typeAppend( contentTypeB->Des() ); |
|
1683 TBuf8<10> temppi; |
|
1684 temppi.Copy( NSimpleDocument::KSimpleBoundary ); |
|
1685 typeAppend.Format( NSimpleDocument::NSimpleMulti::KContentType, &temppi ); |
|
1686 */ |
|
1687 |
|
1688 TBuf8<200> temppi; |
|
1689 temppi.Copy( NSimpleDocument::NSimpleMulti::KContentTypeFullValue ); |
|
1690 |
|
1691 contTypeH = CSIPContentTypeHeader::DecodeL( temppi ); |
|
1692 // CleanupStack::PopAndDestroy( contentTypeB ); // >> contentTypeB |
|
1693 CleanupStack::PushL( contTypeH ); // << contTypeH |
|
1694 } |
|
1695 else |
|
1696 { |
|
1697 contTypeH = CSIPContentTypeHeader::NewLC( |
|
1698 KSimpleApplicationType, KSimplePidfSubType ); // // << contTypeH |
|
1699 } |
|
1700 |
|
1701 // copy content from a request parameter |
|
1702 HBufC8* buffer = aContent.AllocLC(); |
|
1703 mesElems.SetContentL( buffer, contTypeH ); // >> contTypeH |
|
1704 // buffer ownership given to mesElems |
|
1705 CleanupStack::Pop( buffer ); |
|
1706 // contTypeH ownership given to mesElems |
|
1707 CleanupStack::Pop( contTypeH ); |
|
1708 } |
|
1709 else |
|
1710 { |
|
1711 // No need to insert content, there wasn't any. |
|
1712 } |
|
1713 |
|
1714 // set method |
|
1715 RStringF method = SIPStrings::Pool().OpenFStringL( KSimplePUBLISH ); |
|
1716 CleanupClosePushL( method ); |
|
1717 elems->SetMethodL( method ); |
|
1718 |
|
1719 // Send the request transaction |
|
1720 CSIPClientTransaction* sipTrans = iSipConnection->SendRequestL( elems, *regContext ); |
|
1721 // PopAndDestroy calls method.Close() |
|
1722 CleanupStack::PopAndDestroy( &method ); |
|
1723 CleanupStack::Pop( elems ); // elems, ownership given |
|
1724 return sipTrans; |
|
1725 } |
|
1726 |
|
1727 // ---------------------------------------------------------- |
|
1728 // CSimpleSipConnection::HandlePublishRespL |
|
1729 // ---------------------------------------------------------- |
|
1730 // |
|
1731 void CSimpleSipConnection::HandlePublishRespL( |
|
1732 const CSIPMessageElements& aMesElems, CSimpleRequest* aReq ) |
|
1733 { |
|
1734 #ifdef _DEBUG |
|
1735 TSimpleLogger::Log(_L("SipConnection: HandlePublishRespL" )); |
|
1736 #endif |
|
1737 TBool ETagReceived(EFalse); |
|
1738 RStringF extensionName = SIPStrings::Pool().OpenFStringL( KSimpleETag ); |
|
1739 CleanupClosePushL( extensionName ); |
|
1740 const RPointerArray<CSIPHeaderBase>& userHs = aMesElems.UserHeaders(); |
|
1741 for ( TInt i = 0; i < userHs.Count(); i++ ) |
|
1742 { |
|
1743 const CSIPHeaderBase* header = userHs[ i ]; |
|
1744 if ( header->Name() == extensionName ) |
|
1745 { |
|
1746 HBufC8* hValue = header->ToTextValueL(); |
|
1747 // hValue ownership is transferred |
|
1748 aReq->SetETag( hValue ); |
|
1749 // store etag to vimpstsettingstore |
|
1750 StoreETagL( *hValue ); |
|
1751 ETagReceived = ETrue; |
|
1752 } |
|
1753 else if ( header->Name() == SIPStrings::StringF( SipStrConsts::EExpiresHeader)) |
|
1754 { |
|
1755 // Save the new refresh time. |
|
1756 // Start the timer later in CSimplerequest::Complete() |
|
1757 CSIPExpiresHeader* eH = (CSIPExpiresHeader*)header; |
|
1758 TUint expires = eH->Value(); |
|
1759 aReq->SetRefreshTime( expires ); |
|
1760 } |
|
1761 else |
|
1762 { |
|
1763 // We igonre other than Expires and ETag headers |
|
1764 } |
|
1765 } |
|
1766 if ( !ETagReceived || !aReq->RefreshTime() ) |
|
1767 { |
|
1768 // Remove old ETag if nore received or if the expires header was 0 in our request. |
|
1769 aReq->SetETag( NULL ); |
|
1770 //TPtrC8 nullETag = nullETag.Alloc( KNullDesC8 ); |
|
1771 TBufC8<1> nullETag( KNullDesC8 ); |
|
1772 HBufC8* buf; |
|
1773 buf = nullETag.Alloc(); |
|
1774 StoreETagL( *buf ); |
|
1775 delete buf; |
|
1776 } |
|
1777 // PopAndDestroy calls extensionName.Close() |
|
1778 CleanupStack::PopAndDestroy( &extensionName ); |
|
1779 } |
|
1780 |
|
1781 // ---------------------------------------------------------- |
|
1782 // CSimpleSipConnection::HandleDialogRequestL |
|
1783 // ---------------------------------------------------------- |
|
1784 // |
|
1785 void CSimpleSipConnection::HandleDialogRequestL( |
|
1786 const CSIPMessageElements& aMesElems, CSimpleRequest& aReq, |
|
1787 const TDesC8& aMethod ) |
|
1788 { |
|
1789 #ifdef _DEBUG |
|
1790 TBuf<20> myBuf; |
|
1791 myBuf.Copy( aMethod ); |
|
1792 TSimpleLogger::Log(_L("SipConnection: HandleDialogRequestL %S" ), &myBuf); |
|
1793 CSIPRefresh* sipR = aReq.Refresh(); |
|
1794 if ( sipR ) |
|
1795 { |
|
1796 TSimpleLogger::Log(_L("SIPREFRESH STATE = %d" ), sipR->State() ); |
|
1797 } |
|
1798 #endif |
|
1799 |
|
1800 _LIT8( KMyActive, "active"); |
|
1801 _LIT8( KMyPending, "pending"); |
|
1802 |
|
1803 if ( aMethod.CompareF( KSimpleNOTIFY )) |
|
1804 { |
|
1805 // Only NOTIFY is handled. |
|
1806 return; |
|
1807 } |
|
1808 |
|
1809 aReq.Request().SetResponseMethod( MSimpleEngineRequest::ENotify ); |
|
1810 aReq.SetReason( KErrNone ); |
|
1811 |
|
1812 // Start to search subscription-state header |
|
1813 const RPointerArray<CSIPHeaderBase>& userHs = aMesElems.UserHeaders(); |
|
1814 for ( TInt i = 0; i < userHs.Count(); i++ ) |
|
1815 { |
|
1816 const CSIPHeaderBase* header = userHs[ i ]; |
|
1817 if ( header->Name() == SIPStrings::StringF( SipStrConsts::ESubscriptionStateHeader)) |
|
1818 { |
|
1819 CSIPSubscriptionStateHeader* stateH = |
|
1820 (CSIPSubscriptionStateHeader*)header; |
|
1821 TPtrC8 p = stateH->SubStateValue(); |
|
1822 #ifdef _DEBUG |
|
1823 myBuf.Copy( p); |
|
1824 TSimpleLogger::Log(_L("SipConnection: Subscription-State = %S" ), &myBuf); |
|
1825 #endif |
|
1826 if ( !p.CompareF( KMyActive )) |
|
1827 { |
|
1828 // "active" Notification received |
|
1829 aReq.ResetErrCount(); |
|
1830 aReq.Complete( KErrNone ); |
|
1831 } |
|
1832 else if ( !p.CompareF( KMyPending )) |
|
1833 { |
|
1834 // "pending" Notification received |
|
1835 aReq.ResetErrCount(); |
|
1836 aReq.Complete( KSimpleErrPending ); |
|
1837 } |
|
1838 else // KMyTerminated |
|
1839 { |
|
1840 // "terminated" |
|
1841 |
|
1842 aReq.PlusErrCount(); |
|
1843 |
|
1844 // Get the value of reason parameter if any exists. |
|
1845 RStringF value; |
|
1846 value = stateH->ParamValue( SIPStrings::StringF( |
|
1847 SipStrConsts::EReason )); |
|
1848 DoSetResponseReason( value.DesC(), aReq ); |
|
1849 |
|
1850 // Get retry-after parameter |
|
1851 TInt retryAfter = stateH->RetryAfterParameter(); |
|
1852 if ( retryAfter < 0 ) |
|
1853 { |
|
1854 retryAfter = 0; |
|
1855 } |
|
1856 aReq.SetRetryAfter( retryAfter ); |
|
1857 |
|
1858 // Retry in certain situations and do not send |
|
1859 // the final error to the client yet. |
|
1860 |
|
1861 // Detect an error loop if server always returns "terminated" |
|
1862 // Certain errors are serious, and no reason to retry. |
|
1863 if ( aReq.ErrCount() > 1 || |
|
1864 IsPermanentReason( aReq.Reason() ) || |
|
1865 !(aReq.Request().IsRefresh()) || |
|
1866 aReq.ReqState() != CSimpleRequest::ESimpleActiveSubs ) |
|
1867 { |
|
1868 // Complete the client request. |
|
1869 // KErrCompletion has a special handling in a client observer. |
|
1870 // Set the reason code too. |
|
1871 DoSetResponseReason2( aReq.Reason(), aReq.Request() ); |
|
1872 aReq.Complete( KErrCompletion ); |
|
1873 } |
|
1874 else // ESimpleActiveSubs, no fatal error |
|
1875 { |
|
1876 // terminated[ refresh ] |
|
1877 // Retry later |
|
1878 // Notice that permanent reason is handled above |
|
1879 // also for ESimpleActiveSubs |
|
1880 // |
|
1881 DoSetResponseReason2( aReq.Reason(), aReq.Request() ); |
|
1882 // CSimpleRequest::Complete handles this case even when re-tried |
|
1883 // without API callback.. |
|
1884 aReq.Complete( KSimpleErrTemporary ); |
|
1885 } |
|
1886 } |
|
1887 // No need to scan rest of the SIP headers |
|
1888 return; |
|
1889 } |
|
1890 } |
|
1891 } |
|
1892 |
|
1893 // ---------------------------------------------------------- |
|
1894 // CSimpleSipConnection::DoSubscribeL |
|
1895 // ---------------------------------------------------------- |
|
1896 // |
|
1897 CSIPClientTransaction* CSimpleSipConnection::DoSubscribeL( |
|
1898 const TDesC8& aRemoteURI, TInt aExpiry, |
|
1899 const TDesC8& aContent, |
|
1900 CSIPSubscribeDialogAssoc*& aSubsDialog, |
|
1901 TBool aRefresh, |
|
1902 TSimpleSubsType aType, |
|
1903 TBool aAnonymous ) |
|
1904 { |
|
1905 #ifdef _DEBUG |
|
1906 TSimpleLogger::Log(_L("SipConnection: DoSubscribeL expiry=%d" ), aExpiry); |
|
1907 #endif |
|
1908 |
|
1909 // array grow granularity |
|
1910 const TInt KMyGran = 10; |
|
1911 |
|
1912 if ( !iSipConnection || iSipState != ESimpleSipActive ) |
|
1913 { |
|
1914 #ifdef _DEBUG |
|
1915 TSimpleLogger::Log(_L("SipConnection: DoSubscribeL LEAVES **" )); |
|
1916 #endif |
|
1917 User::Leave( KErrNotReady ); |
|
1918 } |
|
1919 |
|
1920 TUint myLimit = iSettings.MaxSubscriptions(); |
|
1921 // Breakpoint: |
|
1922 if ( myLimit && iCurrentNbrSubs >= myLimit && aType != ESubsWinfo ) |
|
1923 { |
|
1924 User::Leave( KSimpleErrSettingsLimit ); |
|
1925 } |
|
1926 |
|
1927 // get request (remote) uri from a request |
|
1928 TUriParser8 parser; |
|
1929 User::LeaveIfError( parser.Parse( aRemoteURI )); |
|
1930 CUri8* uri = CUri8::NewLC( parser ); |
|
1931 |
|
1932 // Event header |
|
1933 CSIPEventHeader* eventH = NULL; |
|
1934 if ( aType == ESubsRegular || aType == ESubsList ) |
|
1935 { |
|
1936 eventH = CSIPEventHeader::NewLC( KSimplePRESENCE_LOW ); |
|
1937 } |
|
1938 else // if ( aType == ESubsWinfo ) |
|
1939 { |
|
1940 eventH = CSIPEventHeader::NewLC( KSimplePRESENCE_LOW ); |
|
1941 CDesC8ArrayFlat* flat = new (ELeave) CDesC8ArrayFlat( KMyGran ); |
|
1942 CleanupStack::PushL( flat ); |
|
1943 flat->AppendL( KSimpleWINFO ); |
|
1944 eventH->SetEventTemplatesL( *flat ); |
|
1945 CleanupStack::PopAndDestroy( flat ); |
|
1946 } |
|
1947 |
|
1948 // From header |
|
1949 // Create is if anonymous request, otherwise use SIP Profile AOR |
|
1950 CSIPFromHeader* fromH = NULL; |
|
1951 |
|
1952 if ( aAnonymous ) |
|
1953 { |
|
1954 // Generate From header |
|
1955 fromH = CSIPFromHeader::DecodeL( KSimpleAnonymous ); |
|
1956 } |
|
1957 CleanupStack::PushL( fromH ); |
|
1958 |
|
1959 // Subscribe Dialog |
|
1960 CSIPSubscribeDialogAssoc* sda = CSIPSubscribeDialogAssoc::NewL( |
|
1961 *iSipConnection, uri, *iProfileObserver->ProfileContext(), |
|
1962 eventH, fromH ); |
|
1963 |
|
1964 CleanupStack::Pop( fromH ); |
|
1965 CleanupStack::Pop( eventH ); |
|
1966 CleanupStack::Pop( uri ); |
|
1967 CleanupStack::PushL( sda ); |
|
1968 |
|
1969 // start to add other headers |
|
1970 CSIPMessageElements* mesElems = CSIPMessageElements::NewLC(); |
|
1971 RPointerArray<CSIPHeaderBase> headers; |
|
1972 CleanupClosePushL( headers ); |
|
1973 |
|
1974 // Expires header |
|
1975 CSIPExpiresHeader* exprH = new (ELeave) CSIPExpiresHeader(aExpiry); |
|
1976 CleanupStack::PushL( exprH ); |
|
1977 User::LeaveIfError( headers.Append( exprH )); |
|
1978 |
|
1979 // Accept header with application/pidf+xml is |
|
1980 // added for reqular subscription and list subscription |
|
1981 CSIPAcceptHeader* acceH = NULL; |
|
1982 if ( aType != ESubsWinfo ) |
|
1983 { |
|
1984 acceH = CSIPAcceptHeader::NewLC( |
|
1985 KSimpleApplicationType, KSimplePidfSubType ); |
|
1986 User::LeaveIfError( headers.Append( acceH )); |
|
1987 |
|
1988 // notice: allow multipart/related always! |
|
1989 acceH = CSIPAcceptHeader::NewLC( |
|
1990 KSimpleMultiType, KSimpleMultipartSubType ); |
|
1991 User::LeaveIfError( headers.Append( acceH )); |
|
1992 } |
|
1993 |
|
1994 if ( aType == ESubsList ) |
|
1995 { |
|
1996 acceH = CSIPAcceptHeader::NewLC( |
|
1997 KSimpleApplicationType, KSimpleListSubType ); |
|
1998 User::LeaveIfError( headers.Append( acceH )); |
|
1999 |
|
2000 // add supported header with value eventlist |
|
2001 RPointerArray<CSIPSupportedHeader> suppHs = |
|
2002 CSIPSupportedHeader::DecodeL( KSimpleEventlist); |
|
2003 for( TInt count=0; count < suppHs.Count(); count++ ) |
|
2004 { |
|
2005 User::LeaveIfError( headers.Append( suppHs[count] )); |
|
2006 } |
|
2007 suppHs.Close(); |
|
2008 } |
|
2009 |
|
2010 if ( aType == ESubsWinfo ) |
|
2011 { |
|
2012 acceH = CSIPAcceptHeader::NewLC( |
|
2013 KSimpleApplicationType, KSimpleWinfoSubType ); |
|
2014 User::LeaveIfError( headers.Append( acceH )); |
|
2015 } |
|
2016 |
|
2017 // For anonymous request add Privacy and P-Preferred-Identity headers |
|
2018 CSIPExtensionHeader* privacyH = NULL; |
|
2019 CSIPExtensionHeader* pPIH = NULL; |
|
2020 HBufC8* myBuffer = NULL; |
|
2021 if ( aAnonymous ) |
|
2022 { |
|
2023 privacyH = CSIPExtensionHeader::NewLC( |
|
2024 KSimplePrivacy, KSimpleId ); |
|
2025 User::LeaveIfError( headers.Append( privacyH )); |
|
2026 TInt aorLength = iProfileObserver->GiveUserAorL().Length(); |
|
2027 myBuffer = HBufC8::NewLC( aorLength + 2 ); // room for brackets |
|
2028 *myBuffer = _L8("<"); |
|
2029 myBuffer->Des().Append( iProfileObserver->GiveUserAorL() ); |
|
2030 myBuffer->Des().Append( _L8(">")); |
|
2031 pPIH = CSIPExtensionHeader::NewLC( |
|
2032 KSimplePIdentity, myBuffer->Des() ); |
|
2033 User::LeaveIfError( headers.Append( pPIH )); |
|
2034 } |
|
2035 |
|
2036 // --------------------------------------------------------- |
|
2037 |
|
2038 #ifdef _DEBUG |
|
2039 #ifdef __LOCAL_MODE |
|
2040 /** |
|
2041 * INTERNAL TEST SUITE |
|
2042 */ |
|
2043 CSimpleLocalModeUtils::AddTestHeaderL(headers); |
|
2044 #endif |
|
2045 #endif |
|
2046 // --------------------------------------------------------- |
|
2047 |
|
2048 // add content and create refresh entity |
|
2049 mesElems->SetUserHeadersL( headers ); |
|
2050 // ownership of elements is given to mesElems |
|
2051 if ( aAnonymous ) |
|
2052 { |
|
2053 CleanupStack::Pop( pPIH ); |
|
2054 CleanupStack::PopAndDestroy( myBuffer ); |
|
2055 CleanupStack::Pop( privacyH ); |
|
2056 } |
|
2057 if ( aType == ESubsList ) |
|
2058 { |
|
2059 CleanupStack::Pop( 3 ); // 3 * acceH |
|
2060 } |
|
2061 else if ( aType == ESubsRegular ) |
|
2062 { |
|
2063 CleanupStack::Pop( 2 ); // 2 * acceH |
|
2064 } |
|
2065 else // ESubsWinfo |
|
2066 { |
|
2067 CleanupStack::Pop( 1 ); // 1 * acceH |
|
2068 } |
|
2069 CleanupStack::Pop( exprH ); |
|
2070 CleanupStack::PopAndDestroy( &headers ); |
|
2071 |
|
2072 // set Content type and content |
|
2073 if ( aContent.Length() ) |
|
2074 { |
|
2075 CSIPContentTypeHeader* contTypeH = CSIPContentTypeHeader::NewLC( |
|
2076 KSimpleApplicationType, KSimpleSubscribeSubType ); |
|
2077 // copy content from a request parameter |
|
2078 HBufC8* buffer = aContent.AllocLC(); |
|
2079 mesElems->SetContentL( buffer, contTypeH ); |
|
2080 // buffer ownership given to mesElems |
|
2081 CleanupStack::Pop( buffer ); |
|
2082 // contTypeH ownership given to mesElems |
|
2083 CleanupStack::Pop( contTypeH ); |
|
2084 } |
|
2085 |
|
2086 CSIPRefresh* refresh = NULL; |
|
2087 if ( aExpiry && aRefresh ) |
|
2088 { |
|
2089 refresh = CSIPRefresh::NewLC(); |
|
2090 } |
|
2091 // Refresh gets its value from expires header. |
|
2092 CSIPClientTransaction* sipTrans = sda->SendSubscribeL( mesElems, refresh ); |
|
2093 if ( refresh ) |
|
2094 { |
|
2095 CleanupStack::Pop( refresh ); |
|
2096 } |
|
2097 CleanupStack::Pop( mesElems ); |
|
2098 // CSIPSubscribeDialogAssoc must not be deleted until it is ubsubscribed |
|
2099 CleanupStack::Pop( sda ); |
|
2100 aSubsDialog = sda; |
|
2101 |
|
2102 return sipTrans; |
|
2103 } |
|
2104 |
|
2105 // ---------------------------------------------------------- |
|
2106 // CSimpleSipConnection::RegisterDefaultL |
|
2107 // ---------------------------------------------------------- |
|
2108 // |
|
2109 void CSimpleSipConnection::RegisterDefaultL( MSimpleEngineRequest& aReq ) |
|
2110 { |
|
2111 #ifdef _DEBUG |
|
2112 TSimpleLogger::Log(_L("SipConnection: RegisterDefaultL" )); |
|
2113 #endif |
|
2114 iProfileObserver->RegisterDefaultProfileL(); |
|
2115 SetSipState( ESimpleSipIdle ); |
|
2116 TRAPD( err, iSipConnection = iProfileObserver->GiveConnectionL() ); |
|
2117 if ( !err ) |
|
2118 { |
|
2119 SetSipState( ESimpleSipActive ); |
|
2120 aReq.Complete( KErrNone ); |
|
2121 } |
|
2122 else if ( err != KErrNotReady ) |
|
2123 { |
|
2124 // KErrNotReady is a normal error indicating |
|
2125 // pending initialization |
|
2126 User::Leave( err ); |
|
2127 } |
|
2128 else |
|
2129 { |
|
2130 // KErrNotReady situation |
|
2131 } |
|
2132 // Save the request to wait a response |
|
2133 CSimpleRequest* simpleR = CSimpleRequest::NewL( |
|
2134 *this, aReq, CSimpleRequest::EReqRegister, aReq.RefreshTime() ); |
|
2135 iRequestList.AddLast( *simpleR ); |
|
2136 // Start timer to detect infinite wait situation |
|
2137 simpleR->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
2138 } |
|
2139 |
|
2140 // ---------------------------------------------------------- |
|
2141 // CSimpleSipConnection::RegisterAnyL |
|
2142 // ---------------------------------------------------------- |
|
2143 // |
|
2144 void CSimpleSipConnection::RegisterAnyL( MSimpleEngineRequest& aReq ) |
|
2145 { |
|
2146 #ifdef _DEBUG |
|
2147 TSimpleLogger::Log(_L("SipConnection: RegisterAnyL" )); |
|
2148 #endif |
|
2149 |
|
2150 iSettings.ReadOTASettingsL( aReq.Aux() ); |
|
2151 |
|
2152 TInt32 uniqueId = iSettings.SipProfileId(); |
|
2153 TUid uniqueUid; |
|
2154 uniqueUid.iUid = uniqueId; |
|
2155 |
|
2156 if ( !iSip && !iProfileObserver ) |
|
2157 { |
|
2158 iSip = CSIP::NewL( uniqueUid, *this ); |
|
2159 |
|
2160 iProfileObserver = CSimpleSipProfileObserver::NewL( |
|
2161 iSip, *iConnectionObserver); |
|
2162 } |
|
2163 |
|
2164 iProfileObserver->RegisterGivenProfileL( iSettings.SipProfileId() ); |
|
2165 SetSipState( ESimpleSipIdle ); |
|
2166 TRAPD( err, iSipConnection = iProfileObserver->GiveConnectionL() ); |
|
2167 if ( !err ) |
|
2168 { |
|
2169 SetSipState( ESimpleSipActive ); |
|
2170 aReq.Complete( KErrNone ); |
|
2171 } |
|
2172 else if ( err != KErrNotReady ) |
|
2173 { |
|
2174 // KErrNotReady is a normal error indicating |
|
2175 // pending initialization |
|
2176 User::Leave( err ); |
|
2177 } |
|
2178 else |
|
2179 { |
|
2180 // KErrNotReady situation |
|
2181 } |
|
2182 // Save the request to wait a response |
|
2183 CSimpleRequest* simpleR = CSimpleRequest::NewL( |
|
2184 *this, aReq, CSimpleRequest::EReqRegister, aReq.RefreshTime() ); |
|
2185 iRequestList.AddLast( *simpleR ); |
|
2186 // Start timer to detect infinite wait situation |
|
2187 simpleR->StartExpiryTimer( iSettings.ExpiryApi() ); |
|
2188 } |
|
2189 |
|
2190 // ---------------------------------------------------------- |
|
2191 // CSimpleSipConnection::SetSipState |
|
2192 // ---------------------------------------------------------- |
|
2193 // |
|
2194 void CSimpleSipConnection::SetSipState( TSimpleSipState aState ) |
|
2195 { |
|
2196 #ifdef _DEBUG |
|
2197 TSimpleLogger::Log(_L("SipConnection: SetSipState %d this=%d" ), aState, (TInt)this ); |
|
2198 #endif |
|
2199 iSipState = aState; |
|
2200 } |
|
2201 |
|
2202 // ---------------------------------------------------------- |
|
2203 // CSimpleSipConnection::DoSetResponseReason |
|
2204 // ---------------------------------------------------------- |
|
2205 // |
|
2206 void CSimpleSipConnection::DoSetResponseReason( |
|
2207 const TDesC8& aReason, CSimpleRequest& aR ) |
|
2208 { |
|
2209 if ( aReason.Length() == 0 ) |
|
2210 { |
|
2211 aR.SetReason( KErrNone ); |
|
2212 } |
|
2213 else if ( !aReason.CompareF( KSimpleRejected )) |
|
2214 { |
|
2215 aR.SetReason( KSimpleErrRejected ); |
|
2216 } |
|
2217 else if ( !aReason.CompareF( KSimpleTimeout )) |
|
2218 { |
|
2219 aR.SetReason( KSimpleErrTimeout ); |
|
2220 } |
|
2221 else if ( !aReason.CompareF( KSimpleDeactivated )) |
|
2222 { |
|
2223 aR.SetReason( KSimpleErrDeactivated ); |
|
2224 } |
|
2225 else if ( !aReason.CompareF( KSimpleProbation )) |
|
2226 { |
|
2227 aR.SetReason( KSimpleErrProbation ); |
|
2228 } |
|
2229 else if ( !aReason.CompareF( KSimpleNoresource )) |
|
2230 { |
|
2231 aR.SetReason( KSimpleErrNoresource ); |
|
2232 } |
|
2233 else if ( !aReason.CompareF( KSimpleGiveup )) |
|
2234 { |
|
2235 aR.SetReason( KSimpleErrGiveup); |
|
2236 } |
|
2237 else |
|
2238 { |
|
2239 aR.SetReason( KErrNone ); |
|
2240 } |
|
2241 } |
|
2242 |
|
2243 // ---------------------------------------------------------- |
|
2244 // CSimpleSipConnection::DoSetResponseReason2 |
|
2245 // ---------------------------------------------------------- |
|
2246 // |
|
2247 void CSimpleSipConnection::DoSetResponseReason2( |
|
2248 TInt aReason, MSimpleEngineRequest& aR ) |
|
2249 { |
|
2250 switch ( aReason ) |
|
2251 { |
|
2252 case KSimpleErrRejected: |
|
2253 aR.SetResponseReason( MSimpleEngineRequest::ERejected ); |
|
2254 break; |
|
2255 case KSimpleErrTimeout: |
|
2256 aR.SetResponseReason( MSimpleEngineRequest::ETimeout ); |
|
2257 break; |
|
2258 case KSimpleErrDeactivated: |
|
2259 aR.SetResponseReason( MSimpleEngineRequest::EDeactivated ); |
|
2260 break; |
|
2261 case KSimpleErrProbation: |
|
2262 aR.SetResponseReason( MSimpleEngineRequest::EProbation ); |
|
2263 break; |
|
2264 case KSimpleErrNoresource: |
|
2265 aR.SetResponseReason( MSimpleEngineRequest::ENoresource ); |
|
2266 break; |
|
2267 case KSimpleErrGiveup: |
|
2268 aR.SetResponseReason( MSimpleEngineRequest::EGiveup ); |
|
2269 break; |
|
2270 default: |
|
2271 aR.SetResponseReason( MSimpleEngineRequest::ENoReason ); |
|
2272 } |
|
2273 } |
|
2274 |
|
2275 // ---------------------------------------------------------- |
|
2276 // CSimpleSipConnection::IsPermanentReason |
|
2277 // ---------------------------------------------------------- |
|
2278 // |
|
2279 TBool CSimpleSipConnection::IsPermanentReason( TInt aReason ) |
|
2280 { |
|
2281 switch ( aReason ) |
|
2282 { |
|
2283 case KSimpleErrPending: |
|
2284 case KSimpleErrDeactivated: |
|
2285 case KSimpleErrProbation: |
|
2286 case KSimpleErrTimeout: |
|
2287 case KSimpleErrGiveup: |
|
2288 case KSimpleErrTemporary: |
|
2289 return EFalse; |
|
2290 default: |
|
2291 return ETrue; |
|
2292 } |
|
2293 } |
|
2294 |
|
2295 // ---------------------------------------------------------- |
|
2296 // CSimpleSipConnection::IncreaseNbrSubs |
|
2297 // ---------------------------------------------------------- |
|
2298 // |
|
2299 void CSimpleSipConnection::IncreaseNbrSubs() |
|
2300 { |
|
2301 ++iCurrentNbrSubs; |
|
2302 #ifdef _DEBUG |
|
2303 TSimpleLogger::Log(_L("SipConnection: ++iCurrentNbrSubs %d" ), |
|
2304 iCurrentNbrSubs ); |
|
2305 #endif |
|
2306 } |
|
2307 |
|
2308 // ---------------------------------------------------------- |
|
2309 // CSimpleSipConnection::DecreaseNbrSubs |
|
2310 // ---------------------------------------------------------- |
|
2311 // |
|
2312 void CSimpleSipConnection::DecreaseNbrSubs() |
|
2313 { |
|
2314 if ( iCurrentNbrSubs ) |
|
2315 { |
|
2316 --iCurrentNbrSubs; |
|
2317 } |
|
2318 #ifdef _DEBUG |
|
2319 TSimpleLogger::Log(_L("SipConnection: --iCurrentNbrSubs %d" ), |
|
2320 iCurrentNbrSubs ); |
|
2321 #endif |
|
2322 } |
|
2323 |
|
2324 // ---------------------------------------------------------- |
|
2325 // CSimpleSipConnection::DoRefreshPublishL |
|
2326 // ---------------------------------------------------------- |
|
2327 // |
|
2328 void CSimpleSipConnection::DoRefreshPublishL( CSimpleRequest& aReq ) |
|
2329 { |
|
2330 #ifdef _DEBUG |
|
2331 TSimpleLogger::Log(_L("SipConnection: DoRefreshPublishL")); |
|
2332 #endif |
|
2333 |
|
2334 CSimpleRequest::TSimpleReqState orig = aReq.ReqState(); |
|
2335 |
|
2336 // First, handle |
|
2337 // expires [ no refresh ] |
|
2338 if ( !aReq.Request().IsRefresh() && orig==CSimpleRequest::ESimpleActive ) |
|
2339 { |
|
2340 aReq.SetStatus( 0 ); |
|
2341 aReq.Complete( KErrTimedOut ); |
|
2342 return; |
|
2343 } |
|
2344 if ( orig == CSimpleRequest::ESimpleRunningInit ) |
|
2345 { |
|
2346 // This might happen with short expiry time when there is no response |
|
2347 // from a network. |
|
2348 aReq.SetStatus( 0 ); |
|
2349 aReq.Complete( KErrTimedOut ); |
|
2350 return; |
|
2351 } |
|
2352 else if ( orig == CSimpleRequest::ESimplePending ) |
|
2353 { |
|
2354 // If refresh is already once set to pending,then this publication is terminated (expired) |
|
2355 if ( aReq.PendingState() == CSimpleRequest::EPendingRefresh || |
|
2356 aReq.PendingState() == CSimpleRequest::EPendingModifyAndRefresh ) |
|
2357 { |
|
2358 // special error code that terminates the whole publication. |
|
2359 aReq.Complete( KErrCompletion ); |
|
2360 return; |
|
2361 } |
|
2362 |
|
2363 } |
|
2364 else if ( orig != CSimpleRequest::ESimpleActive ) |
|
2365 { |
|
2366 // special error code that terminates the whole publication. |
|
2367 aReq.Complete( KErrCompletion ); |
|
2368 return; |
|
2369 } |
|
2370 |
|
2371 if ( iSipState == ESimpleSipActive ) |
|
2372 { |
|
2373 // set request state |
|
2374 aReq.SetReqState( CSimpleRequest::ESimpleRunning ); |
|
2375 TInt errx = DoSendPendingPublish( aReq ); |
|
2376 if ( errx ) |
|
2377 { |
|
2378 // Error changes the state and calls API callback when needed |
|
2379 aReq.Complete( errx ); |
|
2380 } |
|
2381 else |
|
2382 { |
|
2383 // start refresh timer to detect expiry of publication |
|
2384 aReq.StartRefreshTimer( aReq.RetryExpiryTime() ); |
|
2385 // Do not start expiry timer |
|
2386 } |
|
2387 } |
|
2388 else if ( iSipState == ESimpleSipSuspend ) |
|
2389 { |
|
2390 // no network available |
|
2391 // refresh [ no network ] |
|
2392 // start refresh timer to detect expiry of publication |
|
2393 aReq.StartRefreshTimer( aReq.RetryExpiryTime() ); |
|
2394 // Do not start expiry timer |
|
2395 aReq.SetReqState( CSimpleRequest::ESimplePending ); |
|
2396 aReq.AddPendingState( CSimpleRequest::EPendingRefresh ); |
|
2397 } |
|
2398 else |
|
2399 { |
|
2400 User::Leave( KErrNotReady ); |
|
2401 } |
|
2402 |
|
2403 // DO NOT update SOURCE-THROTTLE-PUBLISH time |
|
2404 } |
|
2405 |
|
2406 // ---------------------------------------------------------- |
|
2407 // CSimpleSipConnection::DoRefreshSubscribe |
|
2408 // ---------------------------------------------------------- |
|
2409 // |
|
2410 void CSimpleSipConnection::DoRefreshSubscribe( CSimpleRequest& aReq ) |
|
2411 { |
|
2412 #ifdef _DEBUG |
|
2413 TSimpleLogger::Log(_L("SipConnection: DoRefreshSubscribe")); |
|
2414 #endif |
|
2415 |
|
2416 if ( !aReq.Request().IsRefresh() ) |
|
2417 { |
|
2418 #ifdef _DEBUG |
|
2419 TSimpleLogger::Log(_L("SipConnection: Refresh EXPIRED **")); |
|
2420 #endif |
|
2421 // This is expired and no need to refresh |
|
2422 aReq.Complete( KErrTimedOut ); |
|
2423 } |
|
2424 |
|
2425 aReq.StartExpiryTimer( aReq.RetryExpiryTime() ); |
|
2426 |
|
2427 if ( iSipState != ESimpleSipActive ) |
|
2428 { |
|
2429 if ( aReq.ReqState() == CSimpleRequest::ESimpleReTry ) |
|
2430 { |
|
2431 // time to retry [ no network ] |
|
2432 aReq.SetReqState( CSimpleRequest::ESimplePending ); |
|
2433 // expiry timer i already runnig |
|
2434 } |
|
2435 } |
|
2436 else |
|
2437 { |
|
2438 if ( aReq.ReqState() == CSimpleRequest::ESimplePending || |
|
2439 aReq.ReqState() == CSimpleRequest::ESimpleReTry ) |
|
2440 { |
|
2441 // time to retry / SIP req |
|
2442 // recreate a dialog |
|
2443 aReq.SetReqState( CSimpleRequest::ESimpleDialogReCre ); |
|
2444 TRAPD( errx, DoCreateDialogL( aReq ) ); |
|
2445 if ( errx ) |
|
2446 { |
|
2447 // error |
|
2448 // This will call API callback |
|
2449 // Original error has been SIP error |
|
2450 aReq.SetReqState( CSimpleRequest::ESimpleFailed ); |
|
2451 aReq.Complete( KSimpleErrTemporary ); |
|
2452 } |
|
2453 else |
|
2454 { |
|
2455 // waiting OK resp |
|
2456 } |
|
2457 } |
|
2458 } |
|
2459 } |
|
2460 |
|
2461 // ---------------------------------------------------------- |
|
2462 // CSimpleSipConnection::DoCreateDialogL |
|
2463 // ---------------------------------------------------------- |
|
2464 // |
|
2465 void CSimpleSipConnection::DoCreateDialogL( CSimpleRequest& aReq ) |
|
2466 { |
|
2467 #ifdef _DEBUG |
|
2468 TSimpleLogger::Log(_L("SipConnection: DoCreateDialogL")); |
|
2469 #endif |
|
2470 |
|
2471 CSIPSubscribeDialogAssoc* subsDialog = NULL; |
|
2472 CSIPClientTransaction* sipTrans = NULL; |
|
2473 |
|
2474 // Check whether regular subscription or WINFO subscription is needed. |
|
2475 MSimpleEngineRequest::TSimpleRequest reqType= aReq.Request().RequestType(); |
|
2476 TSimpleSubsType subsType = ESubsRegular; |
|
2477 if ( reqType == MSimpleEngineRequest::ESubscribeLista ) |
|
2478 { |
|
2479 subsType = ESubsList; |
|
2480 } |
|
2481 else if ( reqType == MSimpleEngineRequest::ESubscribeWinfo ) |
|
2482 { |
|
2483 subsType = ESubsWinfo; |
|
2484 } |
|
2485 |
|
2486 // send SIP request |
|
2487 sipTrans = DoSubscribeL( |
|
2488 aReq.Request().RemoteURI(), |
|
2489 aReq.Request().RefreshTime(), |
|
2490 aReq.Data(), |
|
2491 subsDialog, |
|
2492 aReq.Request().IsRefresh(), |
|
2493 subsType, |
|
2494 aReq.Request().Aux() ? ETrue : EFalse ); |
|
2495 |
|
2496 // save SIP Dialog and SIP client transaction |
|
2497 aReq.SetDialog( subsDialog ); |
|
2498 aReq.SetTransaction( sipTrans ); |
|
2499 |
|
2500 } |
|
2501 |
|
2502 // ---------------------------------------------------------- |
|
2503 // CSimpleSipConnection::DoSendPendingPublish |
|
2504 // ---------------------------------------------------------- |
|
2505 // |
|
2506 TInt CSimpleSipConnection::DoSendPendingPublish( |
|
2507 CSimpleRequest& aReq ) |
|
2508 { |
|
2509 #ifdef _DEBUG |
|
2510 TSimpleLogger::Log(_L("SipConnection: DoSendPendingPublish" )); |
|
2511 #endif |
|
2512 |
|
2513 // Do the SIP Publish transaction |
|
2514 TBool sendData = aReq.PendingState() == CSimpleRequest::EPendingModify || |
|
2515 aReq.PendingState() == CSimpleRequest::EPendingModifyAndRefresh ? |
|
2516 ETrue : EFalse; |
|
2517 TPtrC8 myData = sendData ? aReq.Data() : TPtrC8(); |
|
2518 CSIPClientTransaction* sipTrans = NULL; |
|
2519 TRAPD( errx, sipTrans = DoPublishL( |
|
2520 iProfileObserver->GiveUserAorL(), |
|
2521 aReq.Request().RefreshTime(), |
|
2522 myData, |
|
2523 aReq.ETag(), aReq.RequestContentType() )); |
|
2524 if ( errx ) |
|
2525 { |
|
2526 return errx; |
|
2527 } |
|
2528 // Save SIP client transaction |
|
2529 aReq.SetTransaction( sipTrans ); |
|
2530 |
|
2531 aReq.SetPendingState( CSimpleRequest::ENoPending ); |
|
2532 |
|
2533 // Do not update SOURCE-THROTTLE-PUBLISH time |
|
2534 |
|
2535 // Expiry timer is already running |
|
2536 |
|
2537 return KErrNone; |
|
2538 } |
|
2539 |
|
2540 // ---------------------------------------------------------- |
|
2541 // CSimpleSipConnection::HandlePendings |
|
2542 // ---------------------------------------------------------- |
|
2543 // |
|
2544 void CSimpleSipConnection::HandlePendings( ) |
|
2545 { |
|
2546 TInt errx( KErrNone ); |
|
2547 TDblQueIter<CSimpleRequest> rIter( iRequestList ); |
|
2548 rIter.SetToFirst(); |
|
2549 |
|
2550 while ( rIter ) |
|
2551 { |
|
2552 CSimpleRequest* req = rIter; |
|
2553 rIter++; //lint !e1757 |
|
2554 |
|
2555 if ( req->Match( CSimpleRequest::EReqSubscribe ) || |
|
2556 req->Match( CSimpleRequest::EReqSubscribeList ) || |
|
2557 req->Match( CSimpleRequest::EReqSubscribeWinfo )) |
|
2558 { |
|
2559 // Subscritions |
|
2560 // Set new request state |
|
2561 if ( req->ReqState() == CSimpleRequest::ESimplePendingInit ) |
|
2562 { |
|
2563 req->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
2564 } |
|
2565 else if ( req->ReqState() == CSimpleRequest::ESimplePending ) |
|
2566 { |
|
2567 req->SetReqState( CSimpleRequest::ESimpleDialogReCre ); |
|
2568 } |
|
2569 else |
|
2570 { |
|
2571 // other states do not need network recovery |
|
2572 break; |
|
2573 } |
|
2574 |
|
2575 // create new dialog |
|
2576 TRAP( errx, DoCreateDialogL( *req ) ); |
|
2577 if ( errx ) |
|
2578 { |
|
2579 // error |
|
2580 // This will call API callback |
|
2581 req->SetReqState( CSimpleRequest::ESimpleFailed ); |
|
2582 req->Complete( errx ); |
|
2583 } |
|
2584 else |
|
2585 { |
|
2586 // Start to wait response from SIP stack. |
|
2587 // Expiry timer is already runnig to detect infinite wait situation |
|
2588 } |
|
2589 } |
|
2590 else if ( req->Match( CSimpleRequest::EReqPublish ) ) |
|
2591 { |
|
2592 // Publications |
|
2593 if ( req->ReqState() == CSimpleRequest::ESimplePendingInit ) |
|
2594 { |
|
2595 req->SetReqState( CSimpleRequest::ESimpleRunningInit ); |
|
2596 } |
|
2597 else if ( req->ReqState() == CSimpleRequest::ESimplePending ) |
|
2598 { |
|
2599 req->SetReqState( CSimpleRequest::ESimpleRunning ); |
|
2600 } |
|
2601 else |
|
2602 { |
|
2603 // other states do not need network recovery |
|
2604 break; |
|
2605 } |
|
2606 // retry publication |
|
2607 if ( DoSendPendingPublish( *req ) ) |
|
2608 { |
|
2609 // error |
|
2610 // This will call API callback |
|
2611 req->SetReqState( CSimpleRequest::ESimpleFailed ); |
|
2612 req->Complete( errx ); |
|
2613 } |
|
2614 else |
|
2615 { |
|
2616 // Start to wait response from SIP stack. |
|
2617 // Expiry timer is already runnig to detect infinite wait situation |
|
2618 } |
|
2619 } |
|
2620 } // while |
|
2621 } |
|
2622 |
|
2623 // ---------------------------------------------------------- |
|
2624 // CSimpleSipConnection::RecognizeSipState |
|
2625 // ---------------------------------------------------------- |
|
2626 // |
|
2627 void CSimpleSipConnection::RecognizeSipState( |
|
2628 TSimpleSipState aState ) |
|
2629 { |
|
2630 if ( aState == ESimpleSipActive ) |
|
2631 { |
|
2632 // Check that both SIP Profile and SIP connection are ready. |
|
2633 // iProfileObserver is created in ConstructL. |
|
2634 if ( iProfileObserver->IsProfileActive() && |
|
2635 iSipConnection && |
|
2636 iSipConnection->State() == CSIPConnection::EActive ) |
|
2637 { |
|
2638 SetSipState( aState ); |
|
2639 } |
|
2640 } |
|
2641 else |
|
2642 { |
|
2643 SetSipState( aState ); |
|
2644 } |
|
2645 } |
|
2646 |
|
2647 // ---------------------------------------------------------- |
|
2648 // CSimpleSipConnection::DoHandleReceivedMessageL |
|
2649 // ---------------------------------------------------------- |
|
2650 // |
|
2651 void CSimpleSipConnection::DoHandleReceivedMessageL( const TDesC8& aFrom, |
|
2652 const TDesC8& aContent, CSimpleRequest& aRequest ) |
|
2653 { |
|
2654 #ifdef _DEBUG |
|
2655 TSimpleLogger::Log( _L( |
|
2656 "CSimpleSipConnection::DoHandleReceivedMessageL - Start" ) ); |
|
2657 #endif |
|
2658 aRequest.SetReason( KErrNone ); |
|
2659 aRequest.SetRecipientL( aFrom ); |
|
2660 aRequest.SetDataL( aContent ); |
|
2661 aRequest.Complete( KErrNone ); |
|
2662 // Open request can be deleted after completion. |
|
2663 aRequest.Destroy(); |
|
2664 #ifdef _DEBUG |
|
2665 TSimpleLogger::Log( _L( |
|
2666 "CSimpleSipConnection::DoHandleReceivedMessageL - End" ) ); |
|
2667 #endif |
|
2668 } |
|
2669 |
|
2670 // ----------------------------------------------------------------------------- |
|
2671 // CSimpleRequest::SetServiceId |
|
2672 // ----------------------------------------------------------------------------- |
|
2673 EXPORT_C void CSimpleSipConnection::SetServiceId( TInt32 aServiceId ) |
|
2674 { |
|
2675 #ifdef _DEBUG |
|
2676 TSimpleLogger::Log( _L( |
|
2677 "CSimpleSipConnection::SetServiceId old serviceId = %d, new serviceId = %d" ), |
|
2678 iServiceId, aServiceId ); |
|
2679 #endif |
|
2680 iServiceId = aServiceId; |
|
2681 } |
|
2682 |
|
2683 // ----------------------------------------------------------------------------- |
|
2684 // CSimpleRequest::StoreETag |
|
2685 // ----------------------------------------------------------------------------- |
|
2686 void CSimpleSipConnection::StoreETagL( HBufC8& aETag ) |
|
2687 { |
|
2688 #ifdef _DEBUG |
|
2689 TBuf<255> printDocumentId; |
|
2690 printDocumentId.Copy( aETag ); |
|
2691 TSimpleLogger::Log(_L("CSimpleSipConnection: StoreETag ETag = %S, serviceId = %d" ), |
|
2692 &printDocumentId, iServiceId ); |
|
2693 #endif |
|
2694 MVIMPSTSettingsStore* settings = CVIMPSTSettingsStore::NewLC(); |
|
2695 |
|
2696 // Store ETag to uiservicetabsettings |
|
2697 User::LeaveIfError( settings->SetL( |
|
2698 iServiceId, EServicePresenceSessionIdentifier, aETag ) ); |
|
2699 |
|
2700 CleanupStack::PopAndDestroy(); //settings |
|
2701 } |
|
2702 |