|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // CSipStateMachine implementation file. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #include <e32cons.h> |
|
24 #include <e32base.h> |
|
25 |
|
26 #include "SipStateMachine.h" |
|
27 #include "StateIdle.h" |
|
28 #include "StateSessionInitiation.h" |
|
29 #include "StateSessionEstablished.h" |
|
30 #include "StateSessionTerminate.h" |
|
31 |
|
32 EXPORT_C CSipStateMachine * CSipStateMachine::NewL(CSIPTransitionEngine * aTe, MSIPStateMachineClient* aClient, TBool aSMDirection) |
|
33 /** |
|
34 SIP State Machine Instantiation function |
|
35 */ |
|
36 { |
|
37 CSipStateMachine * SipSm = new(ELeave) CSipStateMachine(aTe, aClient, aSMDirection); |
|
38 CleanupStack::PushL (SipSm); |
|
39 SipSm->ConstructL(); |
|
40 CleanupStack::Pop (SipSm); |
|
41 return SipSm; |
|
42 } |
|
43 |
|
44 void CSipStateMachine::ConstructL() |
|
45 /** |
|
46 This Function will startup the state machine with a default |
|
47 state |
|
48 */ |
|
49 { |
|
50 // Tell the TE there's another StateMachine wishing to speak to it. |
|
51 // Remek: Where do you remove it??? Cos i couldn't find !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|
52 iTe->AddStateMachineL(this); |
|
53 |
|
54 // Initialize booleans |
|
55 iClientStimulus = EFalse; |
|
56 iServerStimulus = EFalse; |
|
57 iServerErrorStimulus = EFalse; |
|
58 iCallTerminateCallback = ETrue; |
|
59 iDeleteMeNow = EFalse; |
|
60 isInviteSM = EFalse; |
|
61 isSubscribeSM = EFalse; |
|
62 |
|
63 iCallTerminateCode.iErrorCode = KErrNone; |
|
64 iCallTerminateCode.iSipCode = KErrNone; |
|
65 |
|
66 // Construct States |
|
67 iStateIdle = CStateIdle::NewL(this); |
|
68 CleanupStack::PushL (iStateIdle); |
|
69 |
|
70 iCommandCntx.iCommandState = iStateIdle; |
|
71 iCommandCntx.iClientTx = NULL; |
|
72 iCommandCntx.iCancelClientTx = NULL; |
|
73 iCommandCntx.iServerTx = NULL; |
|
74 iCommandCntx.iRegBinding = NULL; |
|
75 iCommandCntx.iDialogAssoc = NULL; |
|
76 |
|
77 |
|
78 iStateSessionInit = CStateSessionInitiation::NewL(this); |
|
79 CleanupStack::PushL(iStateSessionInit); |
|
80 iStateSessionEstablished = CStateSessionEstablished::NewL(this); |
|
81 CleanupStack::PushL(iStateSessionEstablished); |
|
82 iStateSessionTerminate = CStateSessionTerminate::NewL(this); |
|
83 CleanupStack::PushL(iStateSessionTerminate); |
|
84 |
|
85 iActiveState = iStateIdle; |
|
86 |
|
87 this->Start(&iStatus, NULL) ; |
|
88 // Maithra's fix : For stray signal |
|
89 MakeActive(); |
|
90 // Pop From Cleanup Stack |
|
91 CleanupStack::Pop(4, iStateIdle); |
|
92 } |
|
93 |
|
94 CSipStateMachine::CSipStateMachine(CSIPTransitionEngine * aTe, MSIPStateMachineClient* aClient,TBool aSMDirection) |
|
95 :CActive(EPriorityStandard), |
|
96 iTe(aTe), |
|
97 iClient(aClient), |
|
98 iIncomingStateMachine (aSMDirection) |
|
99 /** |
|
100 constructor |
|
101 */ |
|
102 { |
|
103 // Open Logs |
|
104 __FLOG_OPEN(_L8("SipStateMachine"), _L8("StateMachine")); |
|
105 __FLOG_1(_L("[SipStateMachine]:[%x]::CSipStateMachine() "), this); |
|
106 |
|
107 if(this->IsAdded() == EFalse) |
|
108 { |
|
109 CActiveScheduler::Add(this); |
|
110 } |
|
111 } |
|
112 |
|
113 |
|
114 CSipStateMachine::~CSipStateMachine() |
|
115 /** |
|
116 destructor |
|
117 */ |
|
118 { |
|
119 //Clean-up the iCommand Context |
|
120 Cleanup(); |
|
121 iSipMsgBundle.Close(); |
|
122 // delete States |
|
123 delete iStateIdle; |
|
124 delete iStateSessionInit; |
|
125 delete iStateSessionEstablished; |
|
126 delete iStateSessionTerminate; |
|
127 // Close Logging |
|
128 __FLOG_0(_L("[SipStateMachine]: CSipStateMachine::~CSipStateMachine()")); |
|
129 __FLOG_CLOSE; |
|
130 } |
|
131 |
|
132 EXPORT_C void CSipStateMachine::DeleteWhenReady() |
|
133 /** |
|
134 This function will mark the state machine that the CallTerminated callback |
|
135 should not be called, and state machine should delete itself gracefully when |
|
136 completed the operation |
|
137 */ |
|
138 { |
|
139 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::DeleteWhenReady()"),this); |
|
140 iClient = NULL; |
|
141 iCallTerminateCallback = EFalse; |
|
142 iDeleteMeNow = ETrue; |
|
143 // send the signal to state machine |
|
144 if(iActiveState == NULL) |
|
145 { |
|
146 MakeActive(); |
|
147 MarkRequestComplete(KErrNone); |
|
148 } |
|
149 } |
|
150 |
|
151 EXPORT_C TSipParams & CSipStateMachine::GetSipParams() |
|
152 /** |
|
153 Returns the SIP parameters |
|
154 */ |
|
155 { |
|
156 return iSipParams; |
|
157 } |
|
158 |
|
159 EXPORT_C TInt CSipStateMachine::AcceptCall() |
|
160 /** |
|
161 Accepts and incoming call |
|
162 */ |
|
163 { |
|
164 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::AcceptCall()"),this); |
|
165 // This will always be invite as of now. The implementation of the function needs |
|
166 // changes when more functionality would be added onto this SM machine to handle more |
|
167 // SIp works |
|
168 isInviteSM = ETrue; |
|
169 return SendSIPResponse(TSipHLConsts::EResponseInvite); |
|
170 } |
|
171 |
|
172 EXPORT_C TInt CSipStateMachine::StartCall() |
|
173 /** |
|
174 Start an outgoing call |
|
175 */ |
|
176 { |
|
177 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::StartCall()"),this); |
|
178 if(iSipParams.iRequest == TSipHLConsts::ERequestInvite) |
|
179 { |
|
180 isInviteSM = ETrue; |
|
181 return SendSIPRequest(TSipHLConsts::ERequestInvite); |
|
182 } |
|
183 else if(iSipParams.iRequest == TSipHLConsts::ERequestSubscribe) |
|
184 { |
|
185 isSubscribeSM = ETrue; |
|
186 return SendSIPRequest(TSipHLConsts::ERequestSubscribe); |
|
187 } |
|
188 else |
|
189 { |
|
190 iActiveState = NULL; |
|
191 return KErrNotSupported; |
|
192 } |
|
193 } |
|
194 |
|
195 EXPORT_C TInt CSipStateMachine::StopCall() |
|
196 /** |
|
197 Terminate an established connection |
|
198 */ |
|
199 { |
|
200 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::StopCall()"),this); |
|
201 if(isSubscribeSM) |
|
202 { |
|
203 return SendSIPRequest(TSipHLConsts::ERequestUnSubscribe); |
|
204 } |
|
205 else if(isInviteSM) |
|
206 { |
|
207 return SendSIPRequest(TSipHLConsts::ERequestBye); |
|
208 } |
|
209 else |
|
210 { |
|
211 return KErrNotSupported; |
|
212 } |
|
213 } |
|
214 |
|
215 EXPORT_C TInt CSipStateMachine::RejectCall() |
|
216 /** |
|
217 Rejects an incoming call |
|
218 */ |
|
219 { |
|
220 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::RejectCall()"),this); |
|
221 return SendSIPResponse(TSipHLConsts::EResponseInviteReject); |
|
222 } |
|
223 |
|
224 TInt CSipStateMachine::SendSIPRequest(TSipHLConsts::SIP_REQUESTS aRequest) |
|
225 /** |
|
226 Sends a SIP request of a particular type |
|
227 */ |
|
228 { |
|
229 if(iActiveState == NULL) |
|
230 return KErrNotReady; |
|
231 iActiveState->ResetRequestResponse(); |
|
232 iActiveState->SetClientRequest(aRequest); |
|
233 iClientStimulus = ETrue; |
|
234 if (iSuspendRequest) |
|
235 { |
|
236 SetSuspendRequest(EFalse); |
|
237 } |
|
238 |
|
239 MakeActive(); |
|
240 MarkRequestComplete(KErrNone); |
|
241 return KErrNone; |
|
242 } |
|
243 |
|
244 TInt CSipStateMachine::SendSIPResponse(TSipHLConsts::SIP_RESPONSES aResponse) |
|
245 /** |
|
246 Sends a SIP response of a particular type |
|
247 */ |
|
248 { |
|
249 if(iActiveState == NULL) |
|
250 { |
|
251 return KErrNotReady; |
|
252 } |
|
253 |
|
254 iActiveState->ResetRequestResponse(); |
|
255 iActiveState->SetClientResponse(aResponse); |
|
256 iClientStimulus = ETrue; |
|
257 if (iSuspendRequest) |
|
258 { |
|
259 SetSuspendRequest(EFalse); |
|
260 } |
|
261 |
|
262 MakeActive(); |
|
263 MarkRequestComplete(KErrNone); |
|
264 return KErrNone; |
|
265 } |
|
266 |
|
267 |
|
268 void CSipStateMachine::Start( TRequestStatus* aClientStatus, CSipStateBase* aErrorState ) |
|
269 /** |
|
270 Starts the state machine |
|
271 */ |
|
272 { |
|
273 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::Start()"),this); |
|
274 iClientStatus = aClientStatus; |
|
275 iErrorState = aErrorState; |
|
276 iSuspendRequest = EFalse; |
|
277 |
|
278 if (iClientStatus != NULL) |
|
279 { |
|
280 *iClientStatus = KRequestPending; |
|
281 } |
|
282 |
|
283 // we will not call RunL explicitly over here, That means the SM will be |
|
284 // created in suspended mode. |
|
285 } |
|
286 |
|
287 void CSipStateMachine::IncomingResponse(TSipMsgBundle aMsgBundle) |
|
288 /** |
|
289 Handles the incoming response inside a dialog |
|
290 */ |
|
291 { |
|
292 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingResponse()"),this); |
|
293 iActiveState->ResetRequestResponse(); |
|
294 iActiveState->SetServerResponse(aMsgBundle.iResponse); |
|
295 // wake up the State Machine if suspended and pass the response back to the state |
|
296 if (iSuspendRequest) |
|
297 { |
|
298 SetSuspendRequest(EFalse); |
|
299 } |
|
300 |
|
301 iServerStimulus = ETrue; |
|
302 iSipMsgBundle.Append(aMsgBundle); |
|
303 MakeActive(); |
|
304 MarkRequestComplete(KErrNone); |
|
305 } |
|
306 void CSipStateMachine::IncomingRequestInsideDialog(TSipMsgBundle aMsgBundle) |
|
307 /** |
|
308 Incoming Request inside established dialog |
|
309 */ |
|
310 { |
|
311 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingResponseInsideDialog()"),this); |
|
312 iActiveState->ResetRequestResponse(); |
|
313 iActiveState->SetServerRequest(aMsgBundle.iRequest); |
|
314 // Delete the earlier server transaction if any as earlier transaction comes on outside a |
|
315 // dialog and not needed as new server transaction that comes with ACK / or inside dialoog |
|
316 // will be used |
|
317 if(iCommandCntx.iServerTx != NULL) |
|
318 { |
|
319 delete iCommandCntx.iServerTx; |
|
320 iCommandCntx.iServerTx = NULL; |
|
321 } |
|
322 // Set the server Transaction |
|
323 iCommandCntx.iServerTx = aMsgBundle.iServTransaction; |
|
324 if (iSuspendRequest) |
|
325 { |
|
326 SetSuspendRequest(EFalse); |
|
327 } |
|
328 |
|
329 iServerStimulus = ETrue; |
|
330 iSipMsgBundle.Append(aMsgBundle); |
|
331 MakeActive(); |
|
332 MarkRequestComplete(KErrNone); |
|
333 } |
|
334 |
|
335 void CSipStateMachine::ErrorOccured(TSipMsgBundle aErrBundle) |
|
336 /** |
|
337 Handle the error from TE |
|
338 */ |
|
339 { |
|
340 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::ErrorOccurred()"),this); |
|
341 iActiveState->ResetRequestResponse(); |
|
342 if (iSuspendRequest) |
|
343 { |
|
344 SetSuspendRequest(EFalse); |
|
345 } |
|
346 |
|
347 iServerErrorStimulus = ETrue; |
|
348 iSipMsgBundle.Append(aErrBundle); |
|
349 MakeActive(); |
|
350 MarkRequestComplete(KErrNone); |
|
351 } |
|
352 |
|
353 void CSipStateMachine::InviteCompleted(CSIPClientTransaction& /*aTransaction*/) |
|
354 /** |
|
355 This callback is called to maek the completion of invite |
|
356 */ |
|
357 { |
|
358 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::InviteCompleted()"),this); |
|
359 // we will not match and delete the client transaction as it will be anyway |
|
360 // deleted when a BYE is being sent or received. |
|
361 } |
|
362 |
|
363 void CSipStateMachine::IncomingRequest(TSipMsgBundle aMsgBundle) |
|
364 /** |
|
365 New Incoming request Inside established dialog |
|
366 */ |
|
367 { |
|
368 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingRequest()"),this); |
|
369 iActiveState->ResetRequestResponse(); |
|
370 iActiveState->SetServerRequest(aMsgBundle.iRequest); |
|
371 iSipMsgBundle.Append(aMsgBundle); |
|
372 iServerStimulus = ETrue; |
|
373 if (iSuspendRequest) |
|
374 { |
|
375 SetSuspendRequest(EFalse); |
|
376 } |
|
377 |
|
378 MakeActive(); |
|
379 MarkRequestComplete(KErrNone); |
|
380 } |
|
381 |
|
382 void CSipStateMachine::IncomingRequestOutsideDialog(TSipMsgBundle & aMsgBundle) |
|
383 /** |
|
384 New Incoming request outside any established dialog |
|
385 */ |
|
386 { |
|
387 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingRequestOutsideDialog()"),this); |
|
388 // set the command context |
|
389 iCommandCntx.iDialogAssoc = (CSIPInviteDialogAssoc*)aMsgBundle.iDialog; |
|
390 iCommandCntx.iServerTx = aMsgBundle.iServTransaction; |
|
391 iActiveState->ResetRequestResponse(); |
|
392 iActiveState->SetServerRequest(aMsgBundle.iRequest); |
|
393 iSipMsgBundle.Append(aMsgBundle); |
|
394 iServerStimulus = ETrue; |
|
395 if (iSuspendRequest) |
|
396 { |
|
397 SetSuspendRequest(EFalse); |
|
398 } |
|
399 |
|
400 MakeActive(); |
|
401 MarkRequestComplete(KErrNone); |
|
402 } |
|
403 |
|
404 void CSipStateMachine::GenerateInviteResponseL( |
|
405 CSIPServerTransaction *& aTransaction, |
|
406 TSipHLConsts::SIP_RESPONSE_TYPE aType) |
|
407 /** |
|
408 */ |
|
409 { |
|
410 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL()"),this); |
|
411 switch(aType) |
|
412 { |
|
413 case TSipHLConsts::EResponseRinging: |
|
414 { |
|
415 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<180 Ringing>>"),this); |
|
416 CSIPResponseElements *ResElem = CSIPResponseElements::NewLC( |
|
417 180, SIPStrings::StringF(SipStrConsts::EPhraseRinging)); |
|
418 aTransaction->SendResponseL(ResElem); |
|
419 CleanupStack::Pop(ResElem); |
|
420 } |
|
421 break; |
|
422 case TSipHLConsts::EResponse200OK: |
|
423 { |
|
424 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<200 OK>>"),this); |
|
425 CSIPResponseElements *ResElem = CSIPResponseElements::NewLC( |
|
426 200, SIPStrings::StringF(SipStrConsts::EPhraseOk)); |
|
427 aTransaction->SendResponseL(ResElem); |
|
428 CleanupStack::Pop(ResElem); |
|
429 } |
|
430 break; |
|
431 case TSipHLConsts::EResponseReject: |
|
432 { |
|
433 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<488 Reject>>"),this); |
|
434 CSIPResponseElements *ResElem = CSIPResponseElements::NewLC( |
|
435 488, SIPStrings::StringF(SipStrConsts::EPhraseNotAcceptableHere)); |
|
436 aTransaction->SendResponseL(ResElem); |
|
437 CleanupStack::Pop(ResElem); |
|
438 } |
|
439 break; |
|
440 default: |
|
441 { |
|
442 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<No Response Generated>>"),this); |
|
443 } |
|
444 } |
|
445 |
|
446 } |
|
447 |
|
448 void CSipStateMachine::GenerateSubscribeResponseL |
|
449 (CSIPServerTransaction *& aTransaction, |
|
450 TSipHLConsts::SIP_RESPONSE_TYPE aType) |
|
451 /** |
|
452 */ |
|
453 { |
|
454 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL()"),this); |
|
455 switch(aType) |
|
456 { |
|
457 case TSipHLConsts::EResponse200OK: |
|
458 { |
|
459 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL() <<200 OK>>"),this); |
|
460 CSIPResponseElements *ResElem = CSIPResponseElements::NewLC( |
|
461 200, SIPStrings::StringF(SipStrConsts::EPhraseOk)); |
|
462 aTransaction->SendResponseL(ResElem); |
|
463 CleanupStack::Pop(ResElem); |
|
464 // We will not delete this here , this will be deleted after giving notification |
|
465 // to the client |
|
466 /* |
|
467 delete aTransaction; |
|
468 aTransaction = NULL; |
|
469 */ |
|
470 } |
|
471 break; |
|
472 default: |
|
473 { |
|
474 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL() <<No Response Generated>>"),this); |
|
475 } |
|
476 } |
|
477 } |
|
478 |
|
479 HBufC8 * CSipStateMachine::GenerateNotificationData() |
|
480 /** |
|
481 */ |
|
482 { |
|
483 // Generate the notification parameter from the incoming server Transaction |
|
484 CSIPServerTransaction *sTran = iCommandCntx.iServerTx; |
|
485 // get the request elements |
|
486 const CSIPRequestElements *reqElems = sTran->RequestElements(); |
|
487 // Get the contents of the request elements |
|
488 // Get the Message Elements |
|
489 const CSIPMessageElements & msgElems = reqElems->MessageElements(); |
|
490 // Get the content |
|
491 TPtrC8 content = msgElems.Content(); |
|
492 HBufC8 * notificationData = NULL; |
|
493 TRAPD(err,notificationData = content.AllocL()); |
|
494 if(err != KErrNone) |
|
495 { |
|
496 return NULL; |
|
497 } |
|
498 return notificationData; |
|
499 } |
|
500 |
|
501 void CSipStateMachine::RunL() |
|
502 /** |
|
503 * Called on completion of one active event |
|
504 */ |
|
505 { |
|
506 if (iStatus.Int() != KErrNone) |
|
507 { |
|
508 OnError(); |
|
509 } |
|
510 |
|
511 if (iActiveState) |
|
512 { |
|
513 if (iSuspendRequest) |
|
514 { |
|
515 // do nothing wait for somebody to enable the state machine |
|
516 return; |
|
517 } |
|
518 else if (iClientStimulus) |
|
519 { |
|
520 iClientStimulus = EFalse; |
|
521 MakeActive(); |
|
522 iActiveState = iActiveState->ProcessClientL(iStatus); |
|
523 } |
|
524 else if (iServerStimulus) |
|
525 { |
|
526 iServerStimulus = EFalse; |
|
527 MakeActive(); |
|
528 iActiveState = iActiveState->ProcessServerL(iStatus); |
|
529 } |
|
530 else if(iServerErrorStimulus) |
|
531 { |
|
532 iServerErrorStimulus = EFalse; |
|
533 MakeActive(); |
|
534 iActiveState = iActiveState->ProcessServerErrorL(iStatus); |
|
535 } |
|
536 else |
|
537 { |
|
538 iSuspendRequest = ETrue; |
|
539 MakeActive(); |
|
540 TRequestStatus *stat = &iStatus; |
|
541 User::RequestComplete(stat,KErrNone); |
|
542 } |
|
543 } |
|
544 else if (iActiveState == NULL && iDeleteMeNow ) |
|
545 { |
|
546 // Ask the state machine to delete itself |
|
547 OnCompletion(); |
|
548 } |
|
549 else |
|
550 { |
|
551 //do nothing |
|
552 } |
|
553 } |
|
554 |
|
555 void CSipStateMachine::OnError() |
|
556 /** |
|
557 * Called from ::RunL when an error occures |
|
558 */ |
|
559 { |
|
560 // Put the state machine in suspended mode , and return. |
|
561 SetSuspendRequest(ETrue); |
|
562 TRequestStatus *stat = &iStatus; |
|
563 User::RequestComplete(stat,KErrNone); |
|
564 } |
|
565 |
|
566 void CSipStateMachine::OnCompletion() |
|
567 /** |
|
568 * Called by RunL when it is needed to delete the state machine |
|
569 */ |
|
570 { |
|
571 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::OnCompletion() <<delete this>>"),this); |
|
572 delete this; |
|
573 } |
|
574 |
|
575 TInt CSipStateMachine::RunError(TInt aError) |
|
576 /** |
|
577 */ |
|
578 { |
|
579 TRequestStatus * Stat = &iStatus; |
|
580 User::RequestComplete( Stat , aError ); |
|
581 return KErrNone; |
|
582 } |
|
583 |
|
584 void CSipStateMachine::DoCancel() |
|
585 /** |
|
586 */ |
|
587 { |
|
588 OnCompletion(); |
|
589 } |
|
590 |
|
591 void CSipStateMachine::MakeActive() |
|
592 /** |
|
593 Function call to wake State Machine from Suspended |
|
594 state |
|
595 */ { |
|
596 if(!IsActive()) |
|
597 { |
|
598 SetActive(); |
|
599 } |
|
600 } |
|
601 |
|
602 void CSipStateMachine::MarkRequestComplete(TInt aErrCode) |
|
603 /** |
|
604 This function will mimic implicitly calling of the |
|
605 Runl function of the State Machine base |
|
606 */ |
|
607 { |
|
608 TRequestStatus * ThisStat = &iStatus; |
|
609 User::RequestComplete ( ThisStat, aErrCode); |
|
610 } |
|
611 |
|
612 CSIPTransitionEngine * CSipStateMachine::GetTe() |
|
613 /** |
|
614 returns the current instance of TE |
|
615 */ |
|
616 { |
|
617 return iTe; |
|
618 } |
|
619 |
|
620 CSipStateBase * CSipStateMachine::GetActiveState() |
|
621 /** |
|
622 Return the Currently active state |
|
623 */ |
|
624 { |
|
625 return iActiveState; |
|
626 } |
|
627 |
|
628 void CSipStateMachine::CallTerminateCallback() |
|
629 /** |
|
630 Varifies and call the terminate call back with appropriate values |
|
631 */ |
|
632 { |
|
633 __FLOG_2(_L("[SipStateMachine]: CSipStateMachine[%x]::CallTerminateCallback() <<Callback Flag = %d>>"),this,iCallTerminateCallback); |
|
634 if(iCallTerminateCallback) |
|
635 { |
|
636 iClient->CallTerminated(iCallTerminateCode.iErrorCode, iCallTerminateCode.iSipCode); |
|
637 } |
|
638 } |
|
639 |
|
640 void CSipStateMachine::CallIncomingCallback() |
|
641 /** |
|
642 Calls the client with incoming call parameters |
|
643 */ |
|
644 { |
|
645 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallIncomingCallback()"),this); |
|
646 TIncomingCallParameters inParam; |
|
647 GenerateIncomingCallParameters(inParam); |
|
648 iClient->IncomingCall(inParam); |
|
649 } |
|
650 |
|
651 void CSipStateMachine::CallEstablishedCallback() |
|
652 /** |
|
653 Notifies the client about the established call |
|
654 */ |
|
655 { |
|
656 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallEstablishedCallback()"),this); |
|
657 iClient->CallEstablished(); |
|
658 } |
|
659 |
|
660 void CSipStateMachine::CallNotificationCallback(TPtrC8 aNotifyData) |
|
661 /** |
|
662 Notifies the client about the incoming notification |
|
663 */ |
|
664 { |
|
665 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallNotificationCallback()"),this); |
|
666 iClient->ReceiveNotification(aNotifyData); |
|
667 } |
|
668 |
|
669 void CSipStateMachine::GenerateIncomingCallParameters(TIncomingCallParameters & aParam) |
|
670 /** |
|
671 Store the incoming call parameters |
|
672 */ |
|
673 { |
|
674 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateIncomingCallParameters()"),this); |
|
675 _LIT8(KAtTheRate,"@"); |
|
676 |
|
677 CSIPServerTransaction *sTran = iCommandCntx.iServerTx; |
|
678 const CSIPRequestElements *reqElems = sTran->RequestElements(); |
|
679 // Get Request Uri |
|
680 const CUri8 & uri = reqElems->RemoteUri(); |
|
681 TPtr8 ptrUri = iUriValues.iReqUri.Des(); |
|
682 |
|
683 ptrUri.Append(uri.Uri().Extract(EUriUserinfo)); |
|
684 ptrUri.Append(KAtTheRate); |
|
685 ptrUri.Append(uri.Uri().Extract(EUriHost)); |
|
686 // Set Request Uri |
|
687 aParam.iReqUri.Set(iUriValues.iReqUri); |
|
688 |
|
689 |
|
690 // Get from |
|
691 const CSIPFromHeader *fromHdr = reqElems->FromHeader(); |
|
692 const CUri8 & uriFrom = fromHdr->SIPAddress().Uri8(); |
|
693 |
|
694 TPtr8 ptrFrom = iUriValues.iFrom.Des(); |
|
695 ptrFrom.Append(uriFrom.Uri().Extract(EUriUserinfo)); |
|
696 ptrFrom.Append(KAtTheRate); |
|
697 ptrFrom.Append(uriFrom.Uri().Extract(EUriHost)); |
|
698 // Set from |
|
699 aParam.iFrom.Set(iUriValues.iFrom); |
|
700 |
|
701 // Get To |
|
702 const CSIPToHeader *toHdr = reqElems->ToHeader(); |
|
703 const CUri8 & uriTo = toHdr->SIPAddress().Uri8(); |
|
704 |
|
705 TPtr8 ptrTo = iUriValues.iTo.Des(); |
|
706 ptrTo.Append(uriTo.Uri().Extract(EUriUserinfo)); |
|
707 ptrTo.Append(KAtTheRate); |
|
708 ptrTo.Append(uriTo.Uri().Extract(EUriHost)); |
|
709 // Set To |
|
710 aParam.iTo.Set(iUriValues.iTo); |
|
711 |
|
712 // Get the Message Elements |
|
713 const CSIPMessageElements & msgElems = reqElems->MessageElements(); |
|
714 aParam.iContent.Set(msgElems.Content()); |
|
715 } |
|
716 |
|
717 TBool CSipStateMachine::GetIncomingStatus() |
|
718 /** |
|
719 Sets whether the state machine is for incoming call |
|
720 */ |
|
721 { |
|
722 return iIncomingStateMachine; |
|
723 } |
|
724 |
|
725 TBool CSipStateMachine::GetOutgoingStatus() |
|
726 /** |
|
727 sets whether an active outgoing is pending or not |
|
728 */ |
|
729 { |
|
730 return isActiveOutgoingSession; |
|
731 } |
|
732 |
|
733 void CSipStateMachine::SetOutgoingStatus(TBool aStatus) |
|
734 /** |
|
735 Resets the status of active outgoing pending |
|
736 */ |
|
737 { |
|
738 isActiveOutgoingSession = aStatus; |
|
739 } |
|
740 |
|
741 CSipStateBase * CSipStateMachine::GetNextState (TSipHLConsts::SIP_STATES aNextState) |
|
742 { |
|
743 switch (aNextState) |
|
744 { |
|
745 case TSipHLConsts::EStateSessionIdle: |
|
746 return iStateIdle; |
|
747 case TSipHLConsts::EStateSessionInitiation: |
|
748 return iStateSessionInit; |
|
749 case TSipHLConsts::EStateSessionEstablished: |
|
750 return iStateSessionEstablished; |
|
751 case TSipHLConsts::EStateSessionTerminated: |
|
752 return iStateSessionTerminate; |
|
753 case TSipHLConsts::EStateNone: |
|
754 default: |
|
755 return NULL; |
|
756 } |
|
757 |
|
758 } |
|
759 void CSipStateMachine::Cleanup() |
|
760 { |
|
761 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::Cleanup()"),this); |
|
762 // Cleanup everything in Command Context |
|
763 delete iCommandCntx.iClientTx; |
|
764 iCommandCntx.iClientTx = NULL; |
|
765 |
|
766 delete iCommandCntx.iCancelClientTx; |
|
767 iCommandCntx.iCancelClientTx = NULL; |
|
768 |
|
769 delete iCommandCntx.iRegBinding; |
|
770 iCommandCntx.iRegBinding = NULL; |
|
771 |
|
772 delete iCommandCntx.iClientTx; |
|
773 iCommandCntx.iClientTx = NULL; |
|
774 |
|
775 delete iCommandCntx.iServerTx; |
|
776 iCommandCntx.iServerTx = NULL; |
|
777 |
|
778 delete iCommandCntx.iDialogAssoc; |
|
779 iCommandCntx.iDialogAssoc = NULL; |
|
780 |
|
781 delete iCommandCntx.iSubsDialogAssoc; |
|
782 iCommandCntx.iSubsDialogAssoc = NULL; |
|
783 } |
|
784 |
|
785 |
|
786 void CSipStateMachine::SendRegisterMessageL() |
|
787 { |
|
788 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendRegisterMessageL()"),this); |
|
789 // create all the necessary ingredients to send Register Message |
|
790 CSIPRefresh * refresh = CSIPRefresh::NewLC(); |
|
791 CSIPToHeader * to = CreateToHeaderLC(iSipParams.iRegParams.iTo); |
|
792 CSIPFromHeader *from = CreateFromHeaderLC (iSipParams.iRegParams.iFrom); |
|
793 CSIPAddress * addr = CSIPAddress::DecodeL(iSipParams.iRegParams.iContact); |
|
794 CSIPContactHeader * contact = CSIPContactHeader::NewL(addr); |
|
795 CleanupStack::PushL(contact); |
|
796 TUriParser8 parser; |
|
797 User::LeaveIfError(parser.Parse(iSipParams.iRegParams.iRegistrar)); |
|
798 CUri8* remoteUri = CUri8::NewLC(parser); |
|
799 // Send Registration |
|
800 CSIPConnection * sipConn = GetTe()->GetSipConnection(); |
|
801 iCommandCntx.iRegBinding = CSIPRegistrationBinding::NewL( |
|
802 *sipConn, to, contact, |
|
803 refresh,0, remoteUri, from); |
|
804 CleanupStack::PushL(iCommandCntx.iRegBinding); |
|
805 iCommandCntx.iClientTx = iCommandCntx.iRegBinding->RegisterL(); |
|
806 CleanupStack::Pop(6, refresh); |
|
807 } |
|
808 |
|
809 void CSipStateMachine::SendUnRegisterMessageL() |
|
810 { |
|
811 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendUnRegisterMessageL()"),this); |
|
812 if (iCommandCntx.iClientTx != NULL) |
|
813 { |
|
814 delete iCommandCntx.iClientTx; |
|
815 iCommandCntx.iClientTx = NULL; |
|
816 } |
|
817 iCommandCntx.iClientTx = iCommandCntx.iRegBinding->DeregisterL(); |
|
818 } |
|
819 |
|
820 void CSipStateMachine::SendInviteMessageL() |
|
821 /** |
|
822 Send an invitation to remote phone |
|
823 */ |
|
824 { |
|
825 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendInviteMessageL()"),this); |
|
826 // set the active outgoing session |
|
827 isActiveOutgoingSession = ETrue; |
|
828 // Get Invite Parameters |
|
829 CSIPToHeader * to = CreateToHeaderLC(iSipParams.iInvParams.iTo); |
|
830 CSIPFromHeader * from = CreateFromHeaderLC(iSipParams.iInvParams.iFrom); |
|
831 CSIPAddress * addr = CSIPAddress::DecodeL(iSipParams.iInvParams.iContact); |
|
832 CSIPContactHeader * contact = CSIPContactHeader::NewLC(addr); |
|
833 TUriParser8 parser; |
|
834 User::LeaveIfError(parser.Parse(iSipParams.iInvParams.iReqUri)); |
|
835 CUri8 * remoteUri = CUri8::NewLC(parser); |
|
836 CSIPMessageElements* msgElements = NULL; |
|
837 |
|
838 // Check whether the content is provided or not, if not no SDP will be genrated |
|
839 if((iSipParams.iInvParams.iContentType.Length() != 0) && |
|
840 (iSipParams.iInvParams.iContentSubType.Length() != 0) && |
|
841 (iSipParams.iInvParams.iContent.Length() != 0)) |
|
842 { |
|
843 // Generate the SDP |
|
844 SdpCodecStringPool::OpenL(); |
|
845 |
|
846 msgElements = CSIPMessageElements::NewLC(); |
|
847 CSIPContentTypeHeader* ct = CSIPContentTypeHeader::NewLC( |
|
848 iSipParams.iInvParams.iContentType, iSipParams.iInvParams.iContentSubType ); |
|
849 CSdpDocument * sdp = CSdpDocument::DecodeLC(iSipParams.iInvParams.iContent); |
|
850 HBufC8* content = GetContentBodyL( sdp ); |
|
851 CleanupStack::PushL( content ); |
|
852 msgElements->SetContentL( content, ct ); |
|
853 CleanupStack::Pop(); |
|
854 CleanupStack::Check(sdp); |
|
855 CleanupStack::PopAndDestroy();// for the sdp document. |
|
856 SdpCodecStringPool::Close(); |
|
857 } |
|
858 // Create Invite Dialog Association |
|
859 CSIPConnection * sipConn = GetTe()->GetSipConnection(); |
|
860 iCommandCntx.iDialogAssoc = CSIPInviteDialogAssoc::NewLC( |
|
861 *sipConn, from, remoteUri, to, contact ); |
|
862 iCommandCntx.iClientTx = iCommandCntx.iDialogAssoc->SendInviteL(msgElements); |
|
863 |
|
864 if(msgElements) |
|
865 { |
|
866 CleanupStack::Pop(7, to); |
|
867 } |
|
868 else |
|
869 { |
|
870 CleanupStack::Pop(5, to); |
|
871 } |
|
872 } |
|
873 |
|
874 void CSipStateMachine::SendAckForInviteL() |
|
875 /** |
|
876 Send in response to the response of Initial invite request |
|
877 */ |
|
878 { |
|
879 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendAckForInvite()"),this); |
|
880 iCommandCntx.iDialogAssoc->SendAckL(*(iCommandCntx.iClientTx),NULL); |
|
881 } |
|
882 |
|
883 void CSipStateMachine::SendCancelL() |
|
884 /** |
|
885 Cancels the ongoing session |
|
886 */ |
|
887 { |
|
888 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendCancelL()"),this); |
|
889 iCommandCntx.iCancelClientTx = iCommandCntx.iClientTx->CancelL(); |
|
890 } |
|
891 |
|
892 void CSipStateMachine::SendByeL() |
|
893 /** |
|
894 Terminates the ongoing session associated with a dialog |
|
895 */ |
|
896 { |
|
897 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendByeL()"),this); |
|
898 if (iCommandCntx.iClientTx != NULL) |
|
899 { |
|
900 delete iCommandCntx.iClientTx; |
|
901 iCommandCntx.iClientTx = NULL; |
|
902 } |
|
903 iCommandCntx.iClientTx = iCommandCntx.iDialogAssoc->SendByeL(NULL); |
|
904 } |
|
905 |
|
906 void CSipStateMachine::SendByeResponseL() |
|
907 /** |
|
908 Acknoweldge the bye |
|
909 */ |
|
910 { |
|
911 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendByeResponseL() <<200 OK>>"),this); |
|
912 CSIPResponseElements* RespElem = CSIPResponseElements::NewLC( |
|
913 200, SIPStrings::StringF( SipStrConsts::EPhraseOk ) ); |
|
914 iCommandCntx.iServerTx->SendResponseL(RespElem); |
|
915 CleanupStack::Pop(RespElem); |
|
916 } |
|
917 |
|
918 HBufC8* CSipStateMachine::GetContentBodyL( CSdpDocument* aContent ) |
|
919 { |
|
920 HBufC8* contentBuf = NULL; |
|
921 if ( aContent->IsValid() ) |
|
922 { |
|
923 CBufFlat* enBuf = CBufFlat::NewL( 1000 ); |
|
924 CleanupStack::PushL( enBuf ); |
|
925 RBufWriteStream writeStream; |
|
926 writeStream.Open( *enBuf, 0 ); |
|
927 aContent->EncodeL( writeStream ); |
|
928 writeStream.Close(); |
|
929 TPtr8 ptr = enBuf->Ptr( 0 ); |
|
930 contentBuf = ptr.AllocL(); |
|
931 CleanupStack::PopAndDestroy( enBuf ); |
|
932 writeStream.Close(); |
|
933 } |
|
934 return contentBuf; |
|
935 } |
|
936 |
|
937 void CSipStateMachine::SendSubscribeMessageL() |
|
938 { |
|
939 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendSubscribeMessageL()"),this); |
|
940 // set the active outgoing session |
|
941 isActiveOutgoingSession = ETrue; |
|
942 // get Refresh |
|
943 CSIPRefresh* refresh = NULL; |
|
944 if (iSipParams.iSubsParams.iAutoRefresh) |
|
945 { |
|
946 refresh = CSIPRefresh::NewLC(); |
|
947 } |
|
948 |
|
949 // SIP Message Elements required for Subscribe |
|
950 CSIPMessageElements* message = CSIPMessageElements::NewLC(); |
|
951 RPointerArray<CSIPHeaderBase> headers; |
|
952 CSIPHeaderBase::PushLC(&headers); |
|
953 // Add Expires |
|
954 CSIPExpiresHeader* expires = new(ELeave)CSIPExpiresHeader(iSipParams.iSubsParams.iExpires); |
|
955 CleanupStack::PushL(expires); |
|
956 headers.AppendL(expires); |
|
957 CleanupStack::Pop(expires); |
|
958 // Add Accept |
|
959 CSIPAcceptHeader* accept = CSIPAcceptHeader::NewLC( |
|
960 iSipParams.iSubsParams.iAcceptType,iSipParams.iSubsParams.iAcceptSubType); |
|
961 headers.AppendL(accept); |
|
962 CleanupStack::Pop(accept); |
|
963 // add user headers |
|
964 message->SetUserHeadersL(headers); |
|
965 CleanupStack::Pop(1); // headers |
|
966 headers.Close(); |
|
967 |
|
968 |
|
969 CSIPToHeader * to = CreateToHeaderLC(iSipParams.iSubsParams.iTo); |
|
970 CSIPFromHeader * from = CreateFromHeaderLC(iSipParams.iSubsParams.iFrom); |
|
971 CSIPAddress * addr = CSIPAddress::DecodeL(iSipParams.iSubsParams.iContact); |
|
972 CSIPContactHeader * contact = CSIPContactHeader::NewLC(addr); |
|
973 TUriParser8 parser; |
|
974 User::LeaveIfError(parser.Parse(iSipParams.iSubsParams.iReqUri)); |
|
975 CUri8 * remoteUri = CUri8::NewLC(parser); |
|
976 CSIPEventHeader *evtHdr = CSIPEventHeader::DecodeL(iSipParams.iSubsParams.iEventType); |
|
977 CleanupStack::PushL(evtHdr); |
|
978 CSIPConnection * sipConn = GetTe()->GetSipConnection(); |
|
979 // Create subscription to send |
|
980 iCommandCntx.iSubsDialogAssoc = CSIPSubscribeDialogAssoc::NewLC( |
|
981 *sipConn,from,remoteUri,evtHdr,to,contact); |
|
982 iCommandCntx.iClientTx = iCommandCntx.iSubsDialogAssoc->SendSubscribeL(message,refresh); |
|
983 if (refresh) |
|
984 { |
|
985 CleanupStack::Pop(8, refresh); |
|
986 } |
|
987 else |
|
988 { |
|
989 CleanupStack::Pop(7, message); |
|
990 } |
|
991 |
|
992 } |
|
993 |
|
994 void CSipStateMachine::SendUnSubscribeMessageL() |
|
995 { |
|
996 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendUnSubscribeMessageL()"),this); |
|
997 if (iCommandCntx.iClientTx != NULL) |
|
998 { |
|
999 delete iCommandCntx.iClientTx; |
|
1000 iCommandCntx.iClientTx = NULL; |
|
1001 } |
|
1002 iCommandCntx.iClientTx = iCommandCntx.iSubsDialogAssoc->SendUnsubscribeL(NULL); |
|
1003 } |
|
1004 |
|
1005 CSIPToHeader* CSipStateMachine::CreateToHeaderLC( const TDesC8& aSipUri ) |
|
1006 { |
|
1007 CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri ); |
|
1008 CleanupStack::PushL( addr ); |
|
1009 |
|
1010 CSIPToHeader* to = CSIPToHeader::NewL( addr ); |
|
1011 CleanupStack::Pop( addr ); |
|
1012 CleanupStack::PushL( to ); |
|
1013 return to; |
|
1014 } |
|
1015 |
|
1016 CSIPFromHeader* CSipStateMachine::CreateFromHeaderLC( const TDesC8& aSipUri ) |
|
1017 { |
|
1018 CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri ); |
|
1019 CleanupStack::PushL( addr ); |
|
1020 |
|
1021 CSIPFromHeader* from = CSIPFromHeader::NewL( addr ); |
|
1022 CleanupStack::Pop( addr ); |
|
1023 CleanupStack::PushL( from ); |
|
1024 return from; |
|
1025 } |
|
1026 |
|
1027 |
|
1028 void CSipStateMachine::ChallengeIgnored(const TDesC8& aRealm) |
|
1029 { |
|
1030 __FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::ChallengeIgnored()"),this); |
|
1031 //Notify SIPSCPR that challenge has been ignored |
|
1032 //and credentials need to be set |
|
1033 iClient->CredentialsRequired(aRealm); |
|
1034 } |
|
1035 |