|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 #include "mcestateacknowledgementrequired.h" |
|
22 #include "mcesipsession.h" |
|
23 #include "mceactionset.h" |
|
24 #include "mcefcactionset.h" |
|
25 #include "mcenatmacros.h" |
|
26 #include "mcereliablesender.h" |
|
27 |
|
28 // ----------------------------------------------------------------------------- |
|
29 // CMceStateAcknowledgementRequired::CMceStateAcknowledgementRequired |
|
30 // ----------------------------------------------------------------------------- |
|
31 // |
|
32 CMceStateAcknowledgementRequired::CMceStateAcknowledgementRequired() |
|
33 : CMceState( KMceStateAcknowledgementRequired ) |
|
34 { |
|
35 } |
|
36 |
|
37 |
|
38 // ----------------------------------------------------------------------------- |
|
39 // CMceStateAcknowledgementRequired::~CMceStateAcknowledgementRequired |
|
40 // ----------------------------------------------------------------------------- |
|
41 // |
|
42 CMceStateAcknowledgementRequired::~CMceStateAcknowledgementRequired() |
|
43 { |
|
44 } |
|
45 |
|
46 |
|
47 // ----------------------------------------------------------------------------- |
|
48 // CMceStateAcknowledgementRequired::DoAcceptL |
|
49 // ----------------------------------------------------------------------------- |
|
50 // |
|
51 TBool CMceStateAcknowledgementRequired::DoAcceptL( |
|
52 TMceStateTransitionEvent& aEvent ) |
|
53 { |
|
54 User::LeaveIfError( |
|
55 aEvent.Code() == EMcePrack || |
|
56 aEvent.Code() == EMceMediaUpdated || |
|
57 aEvent.Code() == EMceNoPrackReceived || |
|
58 aEvent.Code() == EMceReliableFailed || |
|
59 aEvent.Code() == EMceAck || |
|
60 aEvent.Code() == EMceItcEnable || |
|
61 aEvent.Code() == EMceItcDisable || |
|
62 aEvent.Code() == EMceItcAcceptSession || |
|
63 aEvent.Code() == EMceItcRejectSession || |
|
64 IsExtensionRequestEvent( aEvent ) |
|
65 |
|
66 ? KErrNone : KErrTotalLossOfPrecision ); |
|
67 |
|
68 return ETrue; |
|
69 } |
|
70 |
|
71 // ----------------------------------------------------------------------------- |
|
72 // CMceStateAcknowledgementRequired::EntryL |
|
73 // ----------------------------------------------------------------------------- |
|
74 // |
|
75 void CMceStateAcknowledgementRequired::EntryL( |
|
76 TMceStateTransitionEvent& aEvent ) |
|
77 { |
|
78 |
|
79 if ( IsExtensionRequestEvent( aEvent )) |
|
80 { |
|
81 HandleExtensionRequestEventL( aEvent ); |
|
82 } |
|
83 |
|
84 else |
|
85 { |
|
86 switch ( aEvent.Code() ) |
|
87 { |
|
88 case EMcePrack: |
|
89 { |
|
90 EntryPrackL( aEvent ); |
|
91 break; |
|
92 } |
|
93 case EMceMediaUpdated: |
|
94 { |
|
95 EntryMediaUpdatedL( aEvent ); |
|
96 break; |
|
97 } |
|
98 case EMceNoPrackReceived: |
|
99 { |
|
100 EntryNoPrackReceivedL( aEvent ); |
|
101 break; |
|
102 } |
|
103 case EMceReliableFailed: |
|
104 { |
|
105 EntryReliableFailedL ( aEvent ); |
|
106 break; |
|
107 } |
|
108 case EMceItcEnable: |
|
109 case EMceItcDisable: |
|
110 { |
|
111 aEvent.Session().Actions().ControlMediaL( aEvent.ParamIDs(), |
|
112 (TMceItcFunctions)aEvent.Code() ); |
|
113 break; |
|
114 } |
|
115 case EMceItcAcceptSession: |
|
116 { |
|
117 EntryEarlyAcceptL( aEvent ); |
|
118 break; |
|
119 } |
|
120 |
|
121 case EMceItcRejectSession: |
|
122 { |
|
123 CMceSipSession& session = aEvent.Session(); |
|
124 CSIPServerTransaction& request = session.Request(); |
|
125 |
|
126 aEvent.Session().Actions().SendDeclineL( request, |
|
127 aEvent.ParamClientMessage() ); |
|
128 |
|
129 aEvent.Session().Actions().StopMedia(); |
|
130 aEvent.Session().FCActions().ReleaseFC(); |
|
131 break; |
|
132 } |
|
133 |
|
134 |
|
135 default: |
|
136 { |
|
137 // NOP |
|
138 break; |
|
139 } |
|
140 } |
|
141 } |
|
142 } |
|
143 |
|
144 // ----------------------------------------------------------------------------- |
|
145 // CMceStateAcknowledgementRequired::ExitL |
|
146 // ----------------------------------------------------------------------------- |
|
147 // |
|
148 void CMceStateAcknowledgementRequired::ExitL( TMceStateTransitionEvent& aEvent ) |
|
149 { |
|
150 |
|
151 if ( IsExtensionRequestEvent( aEvent )) |
|
152 { |
|
153 //Do Nothing; |
|
154 } |
|
155 |
|
156 else |
|
157 { |
|
158 CMceSipSession& session = aEvent.Session(); |
|
159 TInt status = aEvent.ParamStatus(); |
|
160 switch ( aEvent.Code() ) |
|
161 { |
|
162 case EMcePrack: |
|
163 { |
|
164 if ( MCE_IS_ERROR( status ) ) |
|
165 { |
|
166 session.Actions().StateChanged( KMceStateTerminated ); |
|
167 session.Actions().ClientStateChangedL( CMceSession::ETerminated ); |
|
168 } |
|
169 else |
|
170 { |
|
171 //NOTE this is only for media reservation, not for resource |
|
172 //reservation |
|
173 if ( status == KMceAsync ) |
|
174 { |
|
175 //PRACK caused media to be ready asynchronously |
|
176 } |
|
177 else if ( status == KMceReady && |
|
178 MCE_NEED_TO_RECEIVE( session ) ) |
|
179 { |
|
180 //media is ready, but preconditions are not met |
|
181 session.Actions().StateChanged( KMceStateConfirmationRequired ); |
|
182 } |
|
183 |
|
184 else |
|
185 { |
|
186 // media is ready and preconditions are met |
|
187 ProceedToUpdatedL( aEvent ); |
|
188 } |
|
189 } |
|
190 break; |
|
191 } |
|
192 case EMceMediaUpdated: |
|
193 { |
|
194 if ( MCE_IS_ERROR( status ) ) |
|
195 { |
|
196 session.Actions().StateChanged( KMceStateTerminated ); |
|
197 session.Actions().ClientStateChangedL( CMceSession::ETerminated ); |
|
198 } |
|
199 else if ( status == KMceReady ) |
|
200 { |
|
201 // Other possible state changes handle in entry |
|
202 session.Actions().StateChanged( KMceStateConfirmationRequired ); |
|
203 } |
|
204 else // KMceAsync |
|
205 { |
|
206 session.Actions().StateChanged( KMceStateServerReserving ); |
|
207 } |
|
208 break; |
|
209 } |
|
210 |
|
211 case EMceNoPrackReceived: |
|
212 { |
|
213 session.Actions().StateChanged( KMceStateTerminated ); |
|
214 session.Actions().ClientStateChangedL( CMceSession::ETerminated, |
|
215 KErrTimedOut ); |
|
216 break; |
|
217 } |
|
218 |
|
219 case EMceReliableFailed: |
|
220 { |
|
221 session.Actions().StateChanged( KMceStateTerminated ); |
|
222 session.Actions().ClientStateChangedL( CMceSession::ETerminated, |
|
223 aEvent.ParamStatus()); |
|
224 break; |
|
225 } |
|
226 |
|
227 case EMceItcRejectSession: |
|
228 { |
|
229 session.Actions().StateChanged( KMceStateTerminated ); |
|
230 session.Actions().ClientStateChanged( aEvent.ParamIDs(), |
|
231 CMceSession::ETerminated ); |
|
232 break; |
|
233 } |
|
234 |
|
235 |
|
236 default: |
|
237 { |
|
238 // NOP |
|
239 break; |
|
240 } |
|
241 } |
|
242 } |
|
243 } |
|
244 |
|
245 // ----------------------------------------------------------------------------- |
|
246 // CMceStateAcknowledgementRequired::EntryPrackL |
|
247 // ----------------------------------------------------------------------------- |
|
248 // |
|
249 void CMceStateAcknowledgementRequired::EntryPrackL( |
|
250 TMceStateTransitionEvent& aEvent ) |
|
251 { |
|
252 CMceSipSession& session = aEvent.Session(); |
|
253 // validate PRACK |
|
254 TBool match = session.ReliableSender().PrackReceived( session.Request() ); |
|
255 TMceSipWarningCode warning = KErrNone; |
|
256 if ( match ) |
|
257 { |
|
258 if ( MceSip::HasContent( session.Request() ) ) |
|
259 { |
|
260 // PRACK carries SDP |
|
261 User::LeaveIfError( session.Actions().CreateSDP( session.Request() ) ); |
|
262 |
|
263 session.Actions().CreateBodyCandidateL( CMceComSession::EInSession ); |
|
264 |
|
265 warning = session.Actions().DecodeL(); |
|
266 |
|
267 session.ActiveBody().iCodecSelection = KMceCodecSelectionMerge; |
|
268 |
|
269 aEvent.ParamStatus() = !warning ? KErrNone : KErrAbort; |
|
270 if ( !warning ) |
|
271 { |
|
272 TMceReturnStatus status = session.Actions().UpdateL(); |
|
273 //Second update is needed. |
|
274 status = session.Actions().UpdateL(); |
|
275 aEvent.ParamStatus() = status; |
|
276 if ( status == KMceReady ) |
|
277 { |
|
278 aEvent.Code() = EMceMediaUpdated; |
|
279 EntryMediaUpdatedL( aEvent ); |
|
280 } |
|
281 } |
|
282 } |
|
283 else |
|
284 { |
|
285 // Empty PRACK |
|
286 // Send 200 OK |
|
287 session.Actions().Send200OKL( session.Request() ); |
|
288 TMceReturnStatus status = KMceReady; |
|
289 status = session.Actions().ReserveL(); |
|
290 |
|
291 aEvent.ParamStatus() = status; |
|
292 if ( status == KMceAsync ) |
|
293 { |
|
294 // reservation ongoind |
|
295 session.Actions().StateChanged( KMceStateServerReserving ); |
|
296 } |
|
297 } |
|
298 |
|
299 if ( aEvent.Code() != EMceMediaUpdated && |
|
300 MCE_IS_ERROR( aEvent.ParamStatus() ) ) |
|
301 { |
|
302 if ( warning ) //if error, reject offer (4XX out) |
|
303 { |
|
304 session.Actions().SendRejectOfferWithWarningL( warning, session.Request() ); |
|
305 } |
|
306 else |
|
307 { |
|
308 MceSip::DiscardRequest( session.Request() ); |
|
309 } |
|
310 |
|
311 //reject also invite |
|
312 session.DiscardInvite(); |
|
313 } |
|
314 } |
|
315 else // not match |
|
316 { |
|
317 // Reject the PRACK |
|
318 // Suitable Error code can be defined when PRACK is not mached |
|
319 // to handle state transition |
|
320 aEvent.ParamStatus() = KErrNotFound; |
|
321 MceSip::DiscardRequest( session.Request(), |
|
322 KMceSipCallOrTransactionDoesNotExist ); |
|
323 |
|
324 } |
|
325 } |
|
326 |
|
327 // ----------------------------------------------------------------------------- |
|
328 // CMceStateAcknowledgementRequired::EntryMediaUpdatedL |
|
329 // ----------------------------------------------------------------------------- |
|
330 // |
|
331 void CMceStateAcknowledgementRequired::EntryMediaUpdatedL( |
|
332 TMceStateTransitionEvent& aEvent ) |
|
333 { |
|
334 CMceSipSession& session = aEvent.Session(); |
|
335 CSIPServerTransaction& prack = session.Request(); |
|
336 // verify, that PRACK really is the previous request |
|
337 __ASSERT_ALWAYS( prack.Type() == SIPStrings::StringF( SipStrConsts::EPrack ), |
|
338 User::Leave( KErrTotalLossOfPrecision ) ); |
|
339 |
|
340 TMceReturnStatus status = session.Actions().ReserveL(); |
|
341 aEvent.ParamStatus() = status; |
|
342 if ( MCE_IS_ERROR( aEvent.ParamStatus() ) ) |
|
343 { |
|
344 MceSip::DiscardRequest( session.Request() ); |
|
345 |
|
346 //reject also invite |
|
347 session.DiscardInvite(); |
|
348 } |
|
349 else |
|
350 { |
|
351 // send 2xx to PRACK |
|
352 if ( session.ActiveBody().SecureSession() ) |
|
353 { |
|
354 session.ActiveBody().SecureSession()->iLSReadyToBind = ETrue; |
|
355 } |
|
356 |
|
357 // In KMceNatStateDecodeOffer state, answer is available. |
|
358 // Pull mode is not used with long signalling. |
|
359 if ( !( session.NatSession() && |
|
360 ( ( session.NatState() == KMceNatStateCreateOffer ) || |
|
361 ( session.NatState() == KMceNatStateCreateAnswer ) || |
|
362 ( session.NatState() == KMceNatStateWait ) || |
|
363 ( session.NatState() == KMceNatStateConnected ) ) ) ) |
|
364 { |
|
365 session.Actions().EncodeL(); |
|
366 } |
|
367 session.FCActions().UpdateFCAnswerL( *session.Offer() ); |
|
368 session.Actions().SendAnswerL( prack ); |
|
369 |
|
370 session.Actions().UpdateSucceed(); |
|
371 |
|
372 if ( !MCE_NEED_TO_RECEIVE( session ) && !MCE_FORCED_TO_RECEIVE( session ) ) |
|
373 { |
|
374 ProceedToUpdatedL( aEvent ); |
|
375 } |
|
376 } |
|
377 } |
|
378 |
|
379 // ----------------------------------------------------------------------------- |
|
380 // CMceStateAcknowledgementRequired::EntryNoPrackReveivedL |
|
381 // ----------------------------------------------------------------------------- |
|
382 // |
|
383 void CMceStateAcknowledgementRequired::EntryNoPrackReceivedL( |
|
384 TMceStateTransitionEvent& aEvent ) |
|
385 { |
|
386 CMceSipSession& session = aEvent.Session(); |
|
387 CSIPServerTransaction& serverTransaction = session.Request(); |
|
388 MceSip::DiscardRequest( serverTransaction, |
|
389 KMceSipServerTimeOut, |
|
390 KMceNoRetryAfter ); |
|
391 |
|
392 if ( session.SubState() == CMceSipSession::EOffering || |
|
393 session.SubState() == CMceSipSession::EAnswering ) |
|
394 { |
|
395 session.Actions().StopMedia(); |
|
396 session.FCActions().ReleaseFC(); |
|
397 } |
|
398 else if ( session.SubState() == CMceSipSession::EUpdating ) |
|
399 { |
|
400 session.Actions().UpdateFailed(); |
|
401 } |
|
402 else |
|
403 { |
|
404 // NOP |
|
405 } |
|
406 } |
|
407 |
|
408 // ----------------------------------------------------------------------------- |
|
409 // CMceStateAcknowledgementRequired::EntryReliableFailedL |
|
410 // ----------------------------------------------------------------------------- |
|
411 // |
|
412 void CMceStateAcknowledgementRequired::EntryReliableFailedL( |
|
413 TMceStateTransitionEvent& aEvent ) |
|
414 { |
|
415 |
|
416 CMceSipSession& session = aEvent.Session(); |
|
417 CSIPServerTransaction& serverTransaction = session.Request(); |
|
418 MceSip::DiscardRequest( serverTransaction, |
|
419 KMceSipServerInternalError, |
|
420 KMceNoRetryAfter ); |
|
421 |
|
422 if ( session.SubState() == CMceSipSession::EOffering || |
|
423 session.SubState() == CMceSipSession::EAnswering ) |
|
424 { |
|
425 session.Actions().StopMedia(); |
|
426 session.FCActions().ReleaseFC(); |
|
427 } |
|
428 else if ( session.SubState() == CMceSipSession::EUpdating ) |
|
429 { |
|
430 session.Actions().UpdateFailed(); |
|
431 } |
|
432 else |
|
433 { |
|
434 // NOP |
|
435 } |
|
436 } |
|
437 |
|
438 // ----------------------------------------------------------------------------- |
|
439 // CMceStateAcknowledgementRequired::EntryEarlyAcceptL |
|
440 // ----------------------------------------------------------------------------- |
|
441 // |
|
442 void CMceStateAcknowledgementRequired::EntryEarlyAcceptL( |
|
443 TMceStateTransitionEvent& aEvent ) |
|
444 { |
|
445 // Client accepted the session before prack was received, remember that |
|
446 // 200 OK for invite is sent when possible. |
|
447 CMceSipSession& session = aEvent.Session(); |
|
448 session.StoreAutoEventL( &aEvent, &session.InitialRequest() ); |
|
449 } |
|
450 |
|
451 // ----------------------------------------------------------------------------- |
|
452 // CMceStateAcknowledgementRequired::ProceedToUpdatedL |
|
453 // ----------------------------------------------------------------------------- |
|
454 // |
|
455 void CMceStateAcknowledgementRequired::ProceedToUpdatedL( |
|
456 TMceStateTransitionEvent& aEvent ) |
|
457 { |
|
458 CMceSipSession& session = aEvent.Session(); |
|
459 |
|
460 TMceStateTransitionEvent* acceptEvent = session.StoredAutoEvent(); |
|
461 if ( acceptEvent && acceptEvent->Code() == EMceItcAcceptSession ) |
|
462 { |
|
463 // Session was accepted before really possible and now accepting is |
|
464 // possible, enable automatic event generation to occur at state change |
|
465 session.SetAutoEvent( ETrue ); |
|
466 } |
|
467 |
|
468 session.Actions().StateChanged( KMceStateUpdated ); |
|
469 session.Actions().ClientStateChangedL( CMceSession::EProceeding, |
|
470 *session.Body(), |
|
471 KErrNone ); |
|
472 } |
|
473 |
|
474 // End of file |