/[resiprocate]/main/resip/dum/ServerInviteSession.cxx
ViewVC logotype

Contents of /main/resip/dum/ServerInviteSession.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11167 - (show annotations) (download)
Thu May 1 19:31:20 2014 UTC (5 years, 6 months ago) by sgodin
File MIME type: text/plain
File size: 70093 byte(s)
-ensure we maintain the virtual override of InviteSession::provideOffer by moving the new 
 bool sendOfferAtAccept parameter (added in UAS PRACK changes) to two new methods
 -some apps relied on the virtualness of provideOffer to call the correct version
1 #include "resip/stack/MultipartMixedContents.hxx"
2 #include "resip/stack/MultipartAlternativeContents.hxx"
3 #include "resip/dum/Dialog.hxx"
4 #include "resip/dum/DialogEventStateManager.hxx"
5 #include "resip/dum/DialogUsageManager.hxx"
6 #include "resip/dum/DumTimeout.hxx"
7 #include "resip/dum/InviteSessionHandler.hxx"
8 #include "resip/dum/ServerInviteSession.hxx"
9 #include "resip/dum/MasterProfile.hxx"
10 #include "resip/dum/UsageUseException.hxx"
11 #include "resip/dum/DumHelper.hxx"
12 #include "resip/dum/DumCommand.hxx"
13 #include "rutil/Random.hxx"
14 #include "rutil/Logger.hxx"
15 #include "rutil/compat.hxx"
16 #include "rutil/WinLeakCheck.hxx"
17
18 using namespace resip;
19
20 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
21
22 ServerInviteSession::ServerInviteSession(DialogUsageManager& dum, Dialog& dialog, const SipMessage& request)
23 : InviteSession(dum, dialog),
24 mFirstRequest(request),
25 m1xx(new SipMessage),
26 mCurrentRetransmit1xxSeq(0),
27 mLocalRSeq(0),
28 mAnswerSentReliably(false)
29 {
30 assert(request.isRequest());
31 mState = UAS_Start;
32 }
33
34 ServerInviteSessionHandle
35 ServerInviteSession::getHandle()
36 {
37 return ServerInviteSessionHandle(mDum, getBaseHandle().getId());
38 }
39
40 void
41 ServerInviteSession::redirect(const NameAddrs& contacts, int code)
42 {
43 InfoLog (<< toData(mState) << ": redirect(" << code << ")"); // -> " << contacts);
44
45 switch (mState)
46 {
47 case UAS_EarlyNoOffer:
48 case UAS_EarlyOffer:
49 case UAS_EarlyProvidedAnswer:
50 case UAS_EarlyProvidedOffer:
51 case UAS_NegotiatedReliable:
52 case UAS_FirstSentAnswerReliable:
53 case UAS_FirstSentOfferReliable:
54 case UAS_NoOffer:
55 case UAS_NoOfferReliable:
56 case UAS_ProvidedOfferReliable:
57 case UAS_OfferReliableProvidedAnswer:
58 case UAS_NoAnswerReliableWaitingPrack:
59 case UAS_NoAnswerReliable:
60 case UAS_Offer:
61 case UAS_OfferProvidedAnswer:
62 case UAS_OfferReliable:
63 case UAS_ProvidedOffer:
64 case UAS_ReceivedUpdate:
65 case UAS_SentUpdate:
66 {
67 // !jf! the cleanup for 3xx may be a bit strange if we are in the middle of
68 // an offer/answer exchange with PRACK.
69 // e.g. we sent 183 reliably and then 302 before PRACK was received. Ideally,
70 // we should send 200PRACK
71 SharedPtr<SipMessage> response(new SipMessage);
72 mDialog.makeResponse(*response, mFirstRequest, code);
73 response->header(h_Contacts) = contacts;
74 send(response);
75
76 if (mDum.mDialogEventStateManager)
77 {
78 mDum.mDialogEventStateManager->onTerminated(mDialog, *response, InviteSessionHandler::Rejected);
79 }
80
81 transition(Terminated);
82
83 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Referred);
84 mDum.destroy(this);
85 break;
86 }
87
88 case UAS_Accepted:
89 case UAS_WaitingToOffer:
90 case UAS_WaitingToRequestOffer:
91 case UAS_WaitingToHangup:
92 case UAS_SentUpdateAccepted:
93 case UAS_ReceivedUpdateWaitingAnswer:
94 case UAS_Start:
95 default:
96 assert(0);
97 throw UsageUseException("Can't redirect after accepted", __FILE__, __LINE__);
98 break;
99 }
100 }
101
102 class ServerInviteSessionRedirectCommand : public DumCommandAdapter
103 {
104 public:
105 ServerInviteSessionRedirectCommand(const ServerInviteSessionHandle& serverInviteSessionHandle, const NameAddrs& contacts, int code)
106 : mServerInviteSessionHandle(serverInviteSessionHandle),
107 mContacts(contacts),
108 mCode(code)
109 {
110
111 }
112
113 virtual void executeCommand()
114 {
115 if(mServerInviteSessionHandle.isValid())
116 {
117 mServerInviteSessionHandle->redirect(mContacts, mCode);
118 }
119 }
120
121 virtual EncodeStream& encodeBrief(EncodeStream& strm) const
122 {
123 return strm << "ServerInviteSessionRedirectCommand";
124 }
125 private:
126 ServerInviteSessionHandle mServerInviteSessionHandle;
127 NameAddrs mContacts;
128 int mCode;
129 };
130
131 void
132 ServerInviteSession::redirectCommand(const NameAddrs& contacts, int code)
133 {
134 mDum.post(new ServerInviteSessionRedirectCommand(getHandle(), contacts, code));
135 }
136
137 void
138 ServerInviteSession::provisional(int code, bool earlyFlag)
139 {
140 InfoLog (<< toData(mState) << ": provisional(" << code << ")");
141
142 switch (mState)
143 {
144 case UAS_Offer:
145 transition(UAS_EarlyOffer);
146 sendProvisional(code, earlyFlag);
147 break;
148
149 case UAS_OfferProvidedAnswer:
150 case UAS_EarlyProvidedAnswer:
151 transition(UAS_EarlyProvidedAnswer);
152 sendProvisional(code, earlyFlag);
153 break;
154
155 case UAS_ProvidedOffer:
156 case UAS_EarlyProvidedOffer:
157 transition(UAS_EarlyProvidedOffer);
158 sendProvisional(code, earlyFlag);
159 break;
160
161 case UAS_EarlyOffer:
162 transition(UAS_EarlyOffer);
163 sendProvisional(code, earlyFlag);
164 break;
165
166 case UAS_NoOffer:
167 case UAS_EarlyNoOffer:
168 transition(UAS_EarlyNoOffer);
169 sendProvisional(code, earlyFlag);
170 break;
171
172 case UAS_NoOfferReliable:
173 case UAS_NegotiatedReliable:
174 case UAS_FirstSentAnswerReliable:
175 case UAS_NoAnswerReliableWaitingPrack:
176 case UAS_FirstSentOfferReliable:
177 if(mUnacknowledgedReliableProvisional.get())
178 {
179 InfoLog (<< "Waiting for PRACK. queued provisional, code=" << code << ", early=" << (earlyFlag ? "YES" : "NO") );
180 queueResponse(code, earlyFlag);
181 }
182 else
183 {
184 sendProvisional(code, earlyFlag);
185 }
186 break;
187
188 case UAS_NoAnswerReliable:
189 case UAS_OfferReliable:
190 if(sendProvisional(code, earlyFlag))
191 {
192 // If sent reliably then change state
193 transition(UAS_NoAnswerReliableWaitingPrack);
194 }
195 break;
196
197 case UAS_ProvidedOfferReliable:
198 if(sendProvisional(code, earlyFlag))
199 {
200 // If sent reliably then change state
201 transition(UAS_FirstSentOfferReliable);
202 }
203 break;
204
205 case UAS_OfferReliableProvidedAnswer:
206 if(mUnacknowledgedReliableProvisional.get()) // First 18x may not have containted answer and still be outstanding
207 {
208 InfoLog (<< "Waiting for PRACK. queued provisional, code=" << code << ", early=" << (earlyFlag ? "YES" : "NO") );
209 queueResponse(code, earlyFlag);
210 }
211 else if(sendProvisional(code, earlyFlag) && earlyFlag)
212 {
213 // If sent reliably and earlyFlag set (answer actually sent) then change state
214 transition(UAS_FirstSentAnswerReliable);
215 }
216 break;
217
218 case UAS_Accepted:
219 case UAS_WaitingToOffer:
220 case UAS_WaitingToRequestOffer:
221 case UAS_ReceivedUpdate:
222 case UAS_ReceivedUpdateWaitingAnswer:
223 case UAS_SentUpdate:
224 case UAS_SentUpdateAccepted:
225 case UAS_Start:
226 case UAS_WaitingToHangup:
227 default:
228 assert(0);
229 break;
230 }
231 }
232
233 class ServerInviteSessionProvisionalCommand : public DumCommandAdapter
234 {
235 public:
236 ServerInviteSessionProvisionalCommand(const ServerInviteSessionHandle& serverInviteSessionHandle, int statusCode)
237 : mServerInviteSessionHandle(serverInviteSessionHandle),
238 mStatusCode(statusCode)
239 {
240 }
241
242 virtual void executeCommand()
243 {
244 if(mServerInviteSessionHandle.isValid())
245 {
246 mServerInviteSessionHandle->provisional(mStatusCode);
247 }
248 }
249
250 virtual EncodeStream& encodeBrief(EncodeStream& strm) const
251 {
252 return strm << "ServerInviteSessionProvisionalCommand";
253 }
254 private:
255 ServerInviteSessionHandle mServerInviteSessionHandle;
256 int mStatusCode;
257 };
258
259 void
260 ServerInviteSession::provisionalCommand(int statusCode)
261 {
262 mDum.post(new ServerInviteSessionProvisionalCommand(getHandle(), statusCode));
263 }
264
265 void
266 ServerInviteSession::provideOffer(const Contents& offer,
267 DialogUsageManager::EncryptionLevel level,
268 const Contents* alternative,
269 bool sendOfferAtAccept)
270 {
271 InfoLog (<< toData(mState) << ": provideOffer");
272 switch (mState)
273 {
274 case UAS_NoOffer:
275 transition(UAS_ProvidedOffer);
276 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer, alternative);
277 mProposedEncryptionLevel = level;
278 break;
279
280 case UAS_EarlyNoOffer:
281 transition(UAS_EarlyProvidedOffer);
282 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer, alternative);
283 mProposedEncryptionLevel = level;
284 break;
285
286 case UAS_NoOfferReliable:
287 transition(UAS_ProvidedOfferReliable);
288 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer, alternative);
289 mProposedEncryptionLevel = level;
290 break;
291
292 case UAS_NegotiatedReliable:
293 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer, alternative);
294 mProposedEncryptionLevel = level;
295 if (sendOfferAtAccept)
296 {
297 transition(UAS_ProvidedOffer);
298 }
299 else
300 {
301 transition(UAS_SentUpdate);
302 sendUpdate(offer);
303 }
304 break;
305
306 case UAS_Accepted:
307 // queue the offer to be sent after the ACK is received
308 transition(UAS_WaitingToOffer);
309 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer);
310 mProposedEncryptionLevel = level;
311 break;
312
313 case UAS_WaitingToOffer:
314 InviteSession::provideOffer(offer, level, alternative);
315 break;
316
317 case UAS_FirstSentAnswerReliable:
318 // Queue up offer to be sent after PRACK arrives
319 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer);
320 mProposedEncryptionLevel = level;
321 break;
322
323 case UAS_EarlyProvidedAnswer:
324 case UAS_EarlyProvidedOffer:
325 case UAS_FirstSentOfferReliable:
326 case UAS_Offer:
327 case UAS_EarlyOffer:
328 case UAS_OfferReliable:
329 case UAS_OfferProvidedAnswer:
330 case UAS_ProvidedOffer:
331 case UAS_ProvidedOfferReliable:
332 case UAS_ReceivedUpdate:
333 case UAS_ReceivedUpdateWaitingAnswer:
334 case UAS_SentUpdate:
335 case UAS_SentUpdateAccepted:
336 case UAS_Start:
337 case UAS_WaitingToHangup:
338 case UAS_WaitingToRequestOffer:
339 case UAS_AcceptedWaitingAnswer:
340 assert(0);
341 break;
342 default:
343 InviteSession::provideOffer(offer, level, alternative);
344 break;
345 }
346 }
347
348 void
349 ServerInviteSession::provideOffer(const Contents& offer,
350 DialogUsageManager::EncryptionLevel level,
351 const Contents* alternative)
352 {
353 this->provideOffer(offer, level, alternative, false);
354 }
355
356 void
357 ServerInviteSession::provideOffer(const Contents& offer,
358 bool sendOfferAtAccept)
359 {
360 this->provideOffer(offer, mCurrentEncryptionLevel, 0, sendOfferAtAccept);
361 }
362
363 void
364 ServerInviteSession::provideOffer(const Contents& offer)
365 {
366 this->provideOffer(offer, mCurrentEncryptionLevel, 0, false);
367 }
368
369 void
370 ServerInviteSession::requestOffer()
371 {
372 InfoLog (<< toData(mState) << ": requestOffer");
373 switch (mState)
374 {
375 case UAS_Accepted:
376 // queue the request to be sent after the ACK is received
377 transition(UAS_WaitingToRequestOffer);
378 break;
379
380 case UAS_WaitingToRequestOffer:
381 InviteSession::requestOffer();
382 break;
383
384 default:
385 InviteSession::requestOffer();
386 break;
387 }
388 }
389
390 void
391 ServerInviteSession::provideAnswer(const Contents& answer)
392 {
393 InfoLog (<< toData(mState) << ": provideAnswer");
394 mAnswerSentReliably = false;
395 switch (mState)
396 {
397 case UAS_Offer:
398 transition(UAS_OfferProvidedAnswer);
399 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
400 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
401 break;
402
403 case UAS_EarlyOffer:
404 transition(UAS_EarlyProvidedAnswer);
405 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
406 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
407 break;
408
409 case UAS_OfferReliable:
410 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
411 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
412 transition(UAS_OfferReliableProvidedAnswer);
413 break;
414
415 case UAS_NoAnswerReliableWaitingPrack:
416 // Store answer and wait for PRACK
417 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
418 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
419 break;
420
421 case UAS_ReceivedUpdate:
422 {
423 transition(UAS_NegotiatedReliable);
424
425 // Send answer in 200/Update
426 SharedPtr<SipMessage> response(new SipMessage);
427 mDialog.makeResponse(*response, *mLastRemoteSessionModification, 200);
428 InviteSession::setOfferAnswer(*response, answer, 0);
429 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
430 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
431 InfoLog (<< "Sending " << response->brief());
432 DumHelper::setOutgoingEncryptionLevel(*response, mCurrentEncryptionLevel);
433 send(response);
434 }
435 break;
436
437 case UAS_ReceivedUpdateWaitingAnswer:
438 {
439 SharedPtr<SipMessage> response(new SipMessage);
440 mDialog.makeResponse(*response, *mLastRemoteSessionModification, 200);
441 InviteSession::setOfferAnswer(*response, answer, 0);
442 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
443 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
444 InfoLog (<< "Sending " << response->brief());
445 DumHelper::setOutgoingEncryptionLevel(*response, mCurrentEncryptionLevel);
446 send(response);
447
448 // send the queued 200/Invite
449 updateCheckQueue();
450 }
451 break;
452
453 case UAS_NoAnswerReliable:
454 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
455 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
456 transition(UAS_OfferReliableProvidedAnswer);
457 break;
458
459 // If we received an offer in a PRACK then we transition to NegotiateReliable and expect
460 // provideAnswer to be called to send the 200/Prack containing the answer.
461 case UAS_NegotiatedReliable:
462 if(mPrackWithOffer.get())
463 {
464 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer;
465 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer);
466 SharedPtr<SipMessage> p200(new SipMessage);
467 mDialog.makeResponse(*p200, *mPrackWithOffer, 200);
468 setOfferAnswer(*p200, mCurrentLocalOfferAnswer.get());
469 mAnswerSentReliably = true;
470 mPrackWithOffer.reset();
471 send(p200);
472 }
473 else
474 {
475 assert(0);
476 }
477 break;
478
479 case UAS_Accepted:
480 case UAS_WaitingToOffer:
481 case UAS_WaitingToRequestOffer:
482 case UAS_EarlyNoOffer:
483 case UAS_EarlyProvidedAnswer:
484 case UAS_EarlyProvidedOffer:
485 case UAS_FirstSentAnswerReliable:
486 case UAS_FirstSentOfferReliable:
487 case UAS_NoOffer:
488 case UAS_NoOfferReliable:
489 case UAS_OfferProvidedAnswer:
490 case UAS_ProvidedOffer:
491 case UAS_ProvidedOfferReliable:
492 case UAS_SentUpdate:
493 case UAS_SentUpdateAccepted:
494 case UAS_Start:
495 case UAS_WaitingToHangup:
496 case UAS_AcceptedWaitingAnswer:
497 assert(0);
498 break;
499 default:
500 InviteSession::provideAnswer(answer);
501 break;
502 }
503 }
504
505 void
506 ServerInviteSession::end()
507 {
508 end(NotSpecified);
509 }
510
511 void
512 ServerInviteSession::end(const Data& userReason)
513 {
514 mUserEndReason = userReason;
515 end(InviteSession::UserSpecified);
516 }
517
518 void
519 ServerInviteSession::end(EndReason reason)
520 {
521 InfoLog (<< toData(mState) << ": end");
522 if (mEndReason == NotSpecified)
523 {
524 mEndReason = reason;
525 }
526
527 switch (mState)
528 {
529 case UAS_EarlyNoOffer:
530 case UAS_EarlyOffer:
531 case UAS_EarlyProvidedAnswer:
532 case UAS_EarlyProvidedOffer:
533 case UAS_NoOffer:
534 case UAS_Offer:
535 case UAS_OfferProvidedAnswer:
536 case UAS_ProvidedOffer:
537 case UAS_ProvidedOfferReliable:
538 reject(480);
539 break;
540
541 case UAS_OfferReliable:
542 case UAS_OfferReliableProvidedAnswer:
543 case UAS_NegotiatedReliable:
544 case UAS_FirstSentOfferReliable:
545 case UAS_FirstSentAnswerReliable:
546 case UAS_NoAnswerReliableWaitingPrack:
547 case UAS_NoAnswerReliable:
548 case UAS_NoOfferReliable:
549 case UAS_ReceivedUpdate: // !slg! todo: send 488U
550 case UAS_ReceivedUpdateWaitingAnswer: // !slg! todo: send 488U
551 case UAS_SentUpdate:
552 case UAS_SentUpdateGlare:
553 case UAS_SentUpdateAccepted:
554 reject(480);
555 break;
556
557 case UAS_Start:
558 assert(0);
559 break;
560
561 case UAS_Accepted:
562 case UAS_WaitingToOffer:
563 case UAS_WaitingToRequestOffer:
564 case UAS_AcceptedWaitingAnswer:
565 if(mCurrentRetransmit200) // If retransmit200 timer is active then ACK is not received yet - wait for it
566 {
567 transition(UAS_WaitingToHangup);
568 }
569 else
570 {
571 // ACK has likely timed out - hangup immediately
572 SharedPtr<SipMessage> msg = sendBye();
573 transition(Terminated);
574 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalBye, msg.get());
575 }
576 break;
577
578 case UAS_WaitingToHangup: // This can happen if we are waiting for an ACK to hangup and the ACK timesout
579 break;
580
581 default:
582 InviteSession::end(reason);
583 break;
584 }
585 }
586
587 void
588 ServerInviteSession::reject(int code, WarningCategory *warning)
589 {
590 InfoLog (<< toData(mState) << ": reject(" << code << ")");
591
592 switch (mState)
593 {
594 case UAS_EarlyNoOffer:
595 case UAS_EarlyOffer:
596 case UAS_EarlyProvidedAnswer:
597 case UAS_EarlyProvidedOffer:
598 case UAS_NoOffer:
599 case UAS_Offer:
600 case UAS_OfferProvidedAnswer:
601 case UAS_ProvidedOffer:
602 case UAS_ProvidedOfferReliable:
603
604 case UAS_AcceptedWaitingAnswer:
605 case UAS_NegotiatedReliable:
606 case UAS_FirstSentAnswerReliable:
607 case UAS_NoAnswerReliableWaitingPrack:
608 case UAS_NoAnswerReliable:
609 case UAS_FirstSentOfferReliable:
610 case UAS_NoOfferReliable:
611 case UAS_OfferReliable:
612 case UAS_OfferReliableProvidedAnswer:
613 case UAS_ReceivedUpdate: // Note: This rejects the entire InviteSession - there is no way right now to reject only the Offer that was received via an Update
614 case UAS_ReceivedUpdateWaitingAnswer: // yes it's wrong to call reject after accept - however we can get here from end() as well. We haven't sent our 200/Inv on the wire yet, so we can just reject the Invite session to end it
615 case UAS_SentUpdate:
616 case UAS_SentUpdateGlare:
617 case UAS_SentUpdateAccepted: // yes it's wrong to call reject after accept - however we can get here from end() as well. We haven't sent our 200/Inv on the wire yet, so we can just reject the Invite session to end it
618 {
619 // !jf! the cleanup for 3xx may be a bit strange if we are in the middle of
620 // an offer/answer exchange with PRACK.
621 // e.g. we sent 183 reliably and then 302 before PRACK was received. Ideally,
622 // we should send 200PRACK
623 SharedPtr<SipMessage> response(new SipMessage);
624 mDialog.makeResponse(*response, mFirstRequest, code);
625 if(warning)
626 {
627 response->header(h_Warnings).push_back(*warning);
628 }
629 send(response);
630
631 transition(Terminated);
632 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Rejected);
633 mDum.destroy(this);
634 break;
635 }
636
637 case UAS_Accepted:
638 case UAS_WaitingToOffer:
639 case UAS_WaitingToRequestOffer:
640 case UAS_Start:
641 case UAS_WaitingToHangup:
642 assert(0);
643 break;
644
645 default:
646 InviteSession::reject(code);
647 break;
648 }
649 }
650
651 void
652 ServerInviteSession::accept(int code)
653 {
654 InfoLog (<< toData(mState) << ": accept(" << code << ")");
655 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
656 switch (mState)
657 {
658 case UAS_Offer:
659 case UAS_EarlyOffer:
660 case UAS_FirstSentOfferReliable:
661 assert(0);
662 break;
663
664 case UAS_OfferProvidedAnswer:
665 case UAS_EarlyProvidedAnswer:
666 transition(UAS_Accepted);
667 sendAccept(code, mCurrentLocalOfferAnswer.get());
668 handler->onConnected(getSessionHandle(), *mInvite200);
669 break;
670
671 case UAS_NoOffer:
672 case UAS_EarlyNoOffer:
673 assert(0);
674 break;
675
676 case UAS_ProvidedOffer:
677 case UAS_ProvidedOfferReliable:
678 case UAS_EarlyProvidedOffer:
679 transition(UAS_AcceptedWaitingAnswer);
680 sendAccept(code, mProposedLocalOfferAnswer.get());
681 break;
682
683 case UAS_Accepted:
684 case UAS_WaitingToOffer:
685 case UAS_WaitingToRequestOffer:
686 assert(0); // Already Accepted
687 break;
688
689 case UAS_FirstSentAnswerReliable:
690 case UAS_NoAnswerReliableWaitingPrack:
691 // queue 2xx
692 // waiting for PRACK
693 InfoLog (<< "Waiting for PRACK. queued 200 OK" );
694 queueResponse(code, false);
695 break;
696
697 case UAS_NegotiatedReliable:
698 if(mUnacknowledgedReliableProvisional.get())
699 {
700 InfoLog (<< "Waiting for PRACK. queued provisional" );
701 queueResponse(code, false);
702 }
703 else
704 {
705 transition(UAS_Accepted);
706 sendAccept(code, 0);
707 handler->onConnected(getSessionHandle(), *mInvite200);
708 }
709 break;
710
711 case UAS_OfferReliableProvidedAnswer:
712 transition(UAS_Accepted);
713 sendAccept(code, mCurrentLocalOfferAnswer.get());
714 handler->onConnected(getSessionHandle(), *mInvite200);
715 break;
716
717 case UAS_SentUpdate:
718 transition(UAS_SentUpdateAccepted);
719 queueResponse(code, false);
720 break;
721
722 case UAS_ReceivedUpdate:
723 transition(UAS_ReceivedUpdateWaitingAnswer);
724 queueResponse(code, false);
725 break;
726
727 case UAS_NoAnswerReliable:
728 case UAS_NoOfferReliable:
729 case UAS_OfferReliable:
730 case UAS_ReceivedUpdateWaitingAnswer:
731 case UAS_SentUpdateAccepted:
732 case UAS_Start:
733 case UAS_WaitingToHangup:
734 default:
735 assert(0);
736 break;
737 }
738 }
739
740 class ServerInviteSessionAcceptCommand : public DumCommandAdapter
741 {
742 public:
743 ServerInviteSessionAcceptCommand(const ServerInviteSessionHandle& serverInviteSessionHandle, int statusCode)
744 : mServerInviteSessionHandle(serverInviteSessionHandle),
745 mStatusCode(statusCode)
746 {
747 }
748
749 virtual void executeCommand()
750 {
751 if(mServerInviteSessionHandle.isValid())
752 {
753 mServerInviteSessionHandle->accept(mStatusCode);
754 }
755 }
756
757 virtual EncodeStream& encodeBrief(EncodeStream& strm) const
758 {
759 return strm << "ServerInviteSessionAcceptCommand";
760 }
761 private:
762 ServerInviteSessionHandle mServerInviteSessionHandle;
763 int mStatusCode;
764 };
765
766 void
767 ServerInviteSession::acceptCommand(int statusCode)
768 {
769 mDum.post(new ServerInviteSessionAcceptCommand(getHandle(), statusCode));
770 }
771
772 void
773 ServerInviteSession::dispatch(const SipMessage& msg)
774 {
775 if (msg.isRequest())
776 {
777 if (msg.header(h_RequestLine).method() == INFO)
778 {
779 InviteSession::dispatchInfo(msg);
780 return;
781 }
782 if (msg.header(h_RequestLine).method() == MESSAGE)
783 {
784 InviteSession::dispatchMessage(msg);
785 return;
786 }
787 }
788
789 switch (mState)
790 {
791 case UAS_Start:
792 dispatchStart(msg);
793 break;
794
795 case UAS_Offer:
796 case UAS_EarlyOffer:
797 case UAS_EarlyProvidedAnswer:
798 case UAS_NoOffer:
799 case UAS_ProvidedOffer:
800 case UAS_ProvidedOfferReliable:
801 case UAS_EarlyNoOffer:
802 case UAS_EarlyProvidedOffer:
803 case UAS_OfferProvidedAnswer:
804 case UAS_NoOfferReliable:
805 case UAS_OfferReliable:
806 case UAS_NoAnswerReliable:
807 dispatchOfferOrEarly(msg);
808 break;
809 case UAS_OfferReliableProvidedAnswer:
810 dispatchOfferReliableProvidedAnswer(msg);
811 break;
812 case UAS_Accepted:
813 dispatchAccepted(msg);
814 break;
815 case UAS_WaitingToOffer:
816 dispatchWaitingToOffer(msg);
817 break;
818 case UAS_WaitingToRequestOffer:
819 dispatchWaitingToRequestOffer(msg);
820 break;
821 case UAS_AcceptedWaitingAnswer:
822 dispatchAcceptedWaitingAnswer(msg);
823 break;
824 case UAS_FirstSentAnswerReliable:
825 dispatchFirstSentAnswerReliable(msg);
826 break;
827 case UAS_NoAnswerReliableWaitingPrack:
828 dispatchNoAnswerReliableWaitingPrack(msg);
829 break;
830 case UAS_FirstSentOfferReliable:
831 dispatchFirstSentOfferReliable(msg);
832 break;
833 case UAS_ReceivedUpdate:
834 dispatchReceivedUpdate(msg);
835 break;
836 case UAS_ReceivedUpdateWaitingAnswer:
837 dispatchReceivedUpdateWaitingAnswer(msg);
838 break;
839 case UAS_SentUpdate:
840 dispatchSentUpdate(msg);
841 break;
842 case UAS_SentUpdateGlare:
843 dispatchSentUpdateGlare(msg);
844 break;
845 case UAS_WaitingToHangup:
846 dispatchWaitingToHangup(msg);
847 break;
848 case UAS_SentUpdateAccepted:
849 dispatchSentUpdateAccepted(msg);
850 break;
851 case UAS_NegotiatedReliable:
852 dispatchNegotiatedReliable(msg);
853 break;
854 default:
855 InviteSession::dispatch(msg);
856 break;
857 }
858 }
859
860 void
861 ServerInviteSession::dispatch(const DumTimeout& timeout)
862 {
863 if (timeout.type() == DumTimeout::Retransmit1xx)
864 {
865 if (timeout.seq() == mCurrentRetransmit1xxSeq) // If timer isn't stopped and this timer is for last 1xx sent, then resend
866 {
867 send(m1xx);
868 startRetransmit1xxTimer();
869 }
870 }
871 else if (timeout.type() == DumTimeout::Resubmit1xxRel)
872 {
873 if (timeout.seq() == mCurrentRetransmit1xxSeq) // If timer isn't stopped and this timer is for last 1xx sent, then resend
874 {
875 // This is not a retransmission, it is a resubmission - ensure the RSeq number is incremented
876 if(m1xx->exists(h_RSeq))
877 {
878 // increment RSeq
879 m1xx->header(h_RSeq).value()++;
880
881 // Remove any body/sdp
882 m1xx->setContents(0);
883
884 mUnacknowledgedReliableProvisional = m1xx;
885 send(m1xx);
886 startResubmit1xxRelTimer();
887 }
888 }
889 }
890 else if (timeout.type() == DumTimeout::Retransmit1xxRel)
891 {
892 if (mUnacknowledgedReliableProvisional.get() &&
893 mUnacknowledgedReliableProvisional->header(h_RSeq).value() == timeout.seq())
894 {
895 unsigned int duration = 2*timeout.secondarySeq();
896 if(duration>=64*Timer::T1)
897 {
898 InfoLog (<< "Reliable provisional timeout" );
899 SharedPtr<SipMessage> i504(new SipMessage);
900 mDialog.makeResponse(*i504, mFirstRequest, 504);
901 send(i504);
902
903 transition(Terminated);
904
905 if (mDum.mDialogEventStateManager)
906 {
907 SipMessage msg; // should onTerminated require this msg?
908 mDum.mDialogEventStateManager->onTerminated(mDialog, msg, InviteSessionHandler::Timeout);
909 }
910
911 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Timeout);
912 mDum.destroy(this);
913 return;
914 }
915 else
916 {
917 InfoLog (<< "Reliable provisional retransmit" );
918 send(mUnacknowledgedReliableProvisional);
919 mDum.addTimerMs(DumTimeout::Retransmit1xxRel, duration, getBaseHandle(), timeout.seq(), duration);
920 }
921 }
922 }
923 else if (timeout.type() == DumTimeout::Glare)
924 {
925 if (mState == UAS_SentUpdateGlare)
926 {
927 transition(UAS_SentUpdate);
928 InfoLog (<< "Retransmitting the UPDATE (glare condition timer)");
929 mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); // increments CSeq
930 send(mLastLocalSessionModification);
931 }
932 }
933 else
934 {
935 InviteSession::dispatch(timeout);
936 }
937 }
938
939 void
940 ServerInviteSession::dispatchStart(const SipMessage& msg)
941 {
942 assert(msg.isRequest());
943 assert(msg.header(h_CSeq).method() == INVITE);
944
945 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
946 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
947 storePeerCapabilities(msg);
948
949 if (mDum.mDialogEventStateManager)
950 {
951 mDum.mDialogEventStateManager->onTryingUas(mDialog, msg);
952 }
953
954 switch (toEvent(msg, offerAnswer.get()))
955 {
956 case OnInviteOffer:
957 *mLastRemoteSessionModification = msg;
958 transition(UAS_Offer);
959 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
960 mCurrentEncryptionLevel = getEncryptionLevel(msg);
961 handler->onNewSession(getHandle(), InviteSession::Offer, msg);
962 if(!isTerminated())
963 {
964 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
965 }
966 break;
967 case OnInvite:
968 *mLastRemoteSessionModification = msg;
969 transition(UAS_NoOffer);
970 handler->onNewSession(getHandle(), InviteSession::None, msg);
971 if(!isTerminated())
972 {
973 handler->onOfferRequired(getSessionHandle(), msg);
974 }
975 break;
976 case OnInviteReliableOffer:
977 *mLastRemoteSessionModification = msg;
978 transition(UAS_OfferReliable);
979 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
980 mCurrentEncryptionLevel = getEncryptionLevel(msg);
981 handler->onNewSession(getHandle(), InviteSession::Offer, msg);
982 if(!isTerminated())
983 {
984 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
985 }
986 break;
987 case OnInviteReliable:
988 *mLastRemoteSessionModification = msg;
989 transition(UAS_NoOfferReliable);
990 handler->onNewSession(getHandle(), InviteSession::None, msg);
991 if(!isTerminated())
992 {
993 handler->onOfferRequired(getSessionHandle(), msg);
994 }
995 break;
996 default:
997 assert(0);
998 break;
999 }
1000 }
1001
1002 // Offer, Early, EarlyNoOffer, NoOffer
1003 void
1004 ServerInviteSession::dispatchOfferOrEarly(const SipMessage& msg)
1005 {
1006 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1007 switch (toEvent(msg, offerAnswer.get()))
1008 {
1009 case OnCancel:
1010 dispatchCancel(msg);
1011 break;
1012 case OnBye:
1013 dispatchBye(msg);
1014 break;
1015 default:
1016 if(msg.isRequest())
1017 {
1018 dispatchUnknown(msg);
1019 }
1020 break;
1021 }
1022 }
1023
1024 void
1025 ServerInviteSession::dispatchAccepted(const SipMessage& msg)
1026 {
1027 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1028 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1029 InfoLog (<< "dispatchAccepted: " << msg.brief());
1030
1031 switch (toEvent(msg, offerAnswer.get()))
1032 {
1033 case OnInvite:
1034 case OnInviteReliable:
1035 case OnInviteOffer:
1036 case OnInviteReliableOffer:
1037 case OnUpdate:
1038 case OnUpdateOffer:
1039 {
1040 SharedPtr<SipMessage> response(new SipMessage);
1041 mDialog.makeResponse(*response, msg, 491);
1042 send(response);
1043 break;
1044 }
1045
1046 case OnAck:
1047 case OnAckAnswer: // .bwc. unsolicited body in ACK; it would probably make sense to just ignore.
1048 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1049 transition(Connected);
1050 handler->onConnectedConfirmed(getSessionHandle(), msg);
1051 break;
1052
1053 case OnCancel:
1054 {
1055 // Cancel and 200 crossed
1056 SharedPtr<SipMessage> c200(new SipMessage);
1057 mDialog.makeResponse(*c200, msg, 200);
1058 send(c200);
1059 break;
1060 }
1061
1062 case OnBye:
1063 {
1064 SharedPtr<SipMessage> b200(new SipMessage);
1065 mDialog.makeResponse(*b200, msg, 200);
1066 send(b200);
1067
1068 transition(Terminated);
1069 handler->onTerminated(getSessionHandle(), InviteSessionHandler::RemoteBye, &msg);
1070 mDum.destroy(this);
1071 break;
1072 }
1073
1074 case OnPrack:
1075 {
1076 // should never get a prack here - we always queue up our 200/Inv response
1077 InfoLog (<< "spurious PRACK in state=" << toData(mState));
1078 SharedPtr<SipMessage> p481(new SipMessage);
1079 mDialog.makeResponse(*p481, msg, 481);
1080 send(p481);
1081 break;
1082 }
1083
1084 default:
1085 if(msg.isRequest())
1086 {
1087 dispatchUnknown(msg);
1088 }
1089 break;
1090 }
1091 }
1092
1093 void
1094 ServerInviteSession::dispatchWaitingToOffer(const SipMessage& msg)
1095 {
1096 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1097 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1098 InfoLog (<< "dispatchWaitingToOffer: " << msg.brief());
1099
1100 switch (toEvent(msg, offerAnswer.get()))
1101 {
1102 case OnInvite:
1103 case OnInviteReliable:
1104 case OnInviteOffer:
1105 case OnInviteReliableOffer:
1106 case OnUpdate:
1107 case OnUpdateOffer:
1108 {
1109 SharedPtr<SipMessage> response(new SipMessage);
1110 mDialog.makeResponse(*response, msg, 491);
1111 send(response);
1112 break;
1113 }
1114
1115 case OnAck:
1116 assert(mProposedLocalOfferAnswer.get());
1117 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1118 provideProposedOffer();
1119 break;
1120
1121 case OnAckAnswer:
1122 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1123 sendBye();
1124 transition(Terminated);
1125 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1126 break;
1127
1128 case OnCancel:
1129 {
1130 // Cancel and 200 crossed
1131 SharedPtr<SipMessage> c200(new SipMessage);
1132 mDialog.makeResponse(*c200, msg, 200);
1133 send(c200);
1134 break;
1135 }
1136
1137 case OnBye:
1138 {
1139 SharedPtr<SipMessage> b200(new SipMessage);
1140 mDialog.makeResponse(*b200, msg, 200);
1141 send(b200);
1142
1143 transition(Terminated);
1144 handler->onTerminated(getSessionHandle(), InviteSessionHandler::RemoteBye, &msg);
1145 mDum.destroy(this);
1146 break;
1147 }
1148
1149 default:
1150 if(msg.isRequest())
1151 {
1152 dispatchUnknown(msg);
1153 }
1154 break;
1155 }
1156 }
1157
1158 void
1159 ServerInviteSession::dispatchWaitingToRequestOffer(const SipMessage& msg)
1160 {
1161 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1162 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1163 InfoLog (<< "dispatchWaitingToRequestOffer: " << msg.brief());
1164
1165 switch (toEvent(msg, offerAnswer.get()))
1166 {
1167 case OnInvite:
1168 case OnInviteReliable:
1169 case OnInviteOffer:
1170 case OnInviteReliableOffer:
1171 case OnUpdate:
1172 case OnUpdateOffer:
1173 {
1174 SharedPtr<SipMessage> response(new SipMessage);
1175 mDialog.makeResponse(*response, msg, 491);
1176 send(response);
1177 break;
1178 }
1179
1180 case OnAck:
1181 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1182 requestOffer();
1183 break;
1184
1185 case OnAckAnswer:
1186 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1187 sendBye();
1188 transition(Terminated);
1189 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1190 break;
1191
1192 case OnCancel:
1193 {
1194 // Cancel and 200 crossed
1195 SharedPtr<SipMessage> c200(new SipMessage);
1196 mDialog.makeResponse(*c200, msg, 200);
1197 send(c200);
1198 break;
1199 }
1200
1201 case OnBye:
1202 {
1203 SharedPtr<SipMessage> b200(new SipMessage);
1204 mDialog.makeResponse(*b200, msg, 200);
1205 send(b200);
1206
1207 transition(Terminated);
1208 handler->onTerminated(getSessionHandle(), InviteSessionHandler::RemoteBye, &msg);
1209 mDum.destroy(this);
1210 break;
1211 }
1212
1213 default:
1214 if(msg.isRequest())
1215 {
1216 dispatchUnknown(msg);
1217 }
1218 break;
1219 }
1220 }
1221
1222 void
1223 ServerInviteSession::dispatchAcceptedWaitingAnswer(const SipMessage& msg)
1224 {
1225 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1226 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1227
1228 switch (toEvent(msg, offerAnswer.get()))
1229 {
1230 case OnInvite:
1231 case OnInviteReliable:
1232 case OnInviteOffer:
1233 case OnInviteReliableOffer:
1234 case OnUpdate:
1235 case OnUpdateOffer:
1236 {
1237 SharedPtr<SipMessage> response(new SipMessage);
1238 mDialog.makeResponse(*response, msg, 491);
1239 send(response);
1240 break;
1241 }
1242
1243 case OnAckAnswer:
1244 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1245 transition(Connected);
1246 setCurrentLocalOfferAnswer(msg);
1247 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1248 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1249 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
1250 if(!isTerminated()) // onAnswer callback may call end() or reject()
1251 {
1252 handler->onConnected(getSessionHandle(), msg);
1253 }
1254 break;
1255
1256 case OnAck:
1257 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1258 mEndReason = IllegalNegotiation;
1259 sendBye();
1260 transition(Terminated);
1261 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1262 break;
1263
1264 case OnCancel:
1265 {
1266 // no transition
1267 SharedPtr<SipMessage> c200(new SipMessage);
1268 mDialog.makeResponse(*c200, msg, 200);
1269 send(c200);
1270 break;
1271 }
1272
1273 case OnPrack:
1274 {
1275 // should never get a prack here - we always queue up our 200/Inv response
1276 InfoLog (<< "spurious PRACK in state=" << toData(mState));
1277 SharedPtr<SipMessage> p481(new SipMessage);
1278 mDialog.makeResponse(*p481, msg, 481);
1279 send(p481);
1280 break;
1281 }
1282
1283 default:
1284 if(msg.isRequest())
1285 {
1286 dispatchUnknown(msg);
1287 }
1288 break;
1289 }
1290 }
1291
1292 void
1293 ServerInviteSession::dispatchFirstSentOfferReliable(const SipMessage& msg)
1294 {
1295 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1296 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1297
1298 switch (toEvent(msg, offerAnswer.get()))
1299 {
1300 case OnCancel:
1301 dispatchCancel(msg);
1302 break;
1303
1304 case OnBye:
1305 dispatchBye(msg);
1306 break;
1307
1308 case OnPrack:
1309 if(handlePrack(msg))
1310 {
1311 if(offerAnswer.get()) // Answer
1312 {
1313 transition(UAS_NegotiatedReliable);
1314 SharedPtr<SipMessage> p200(new SipMessage);
1315 mDialog.makeResponse(*p200, msg, 200);
1316 send(p200);
1317
1318 setCurrentLocalOfferAnswer(msg);
1319 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1320 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1321 handler->onPrack(getHandle(), msg);
1322 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
1323 }
1324 else
1325 {
1326 mEndReason = IllegalNegotiation;
1327 transition(Terminated);
1328 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1329
1330 // 406 the Prack
1331 SharedPtr<SipMessage> p406(new SipMessage);
1332 mDialog.makeResponse(*p406, msg, 406);
1333 send(p406);
1334
1335 // 406 the Invite
1336 SharedPtr<SipMessage> i406(new SipMessage);
1337 mDialog.makeResponse(*i406, mFirstRequest, 406);
1338 send(i406);
1339
1340 mDum.destroy(this);
1341 }
1342 }
1343 break;
1344
1345 default:
1346 if(msg.isRequest())
1347 {
1348 dispatchUnknown(msg);
1349 }
1350 break;
1351 }
1352 }
1353
1354 bool
1355 ServerInviteSession::handlePrack(const SipMessage& msg)
1356 {
1357 InfoLog (<< "handlePrack");
1358
1359 if(mUnacknowledgedReliableProvisional.get() &&
1360 mUnacknowledgedReliableProvisional->header(h_RSeq).value() == msg.header(h_RAck).rSequence() &&
1361 mUnacknowledgedReliableProvisional->header(h_CSeq).sequence() == msg.header(h_RAck).cSequence() &&
1362 mUnacknowledgedReliableProvisional->header(h_CSeq).method() == msg.header(h_RAck).method())
1363 {
1364 mUnacknowledgedReliableProvisional.reset(); // Clear storage we have received our PRACK
1365
1366 InfoLog (<< "Found matching provisional for PRACK.");
1367 return true;
1368 }
1369
1370 InfoLog (<< "spurious PRACK in state=" << toData(mState));
1371 SharedPtr<SipMessage> p481(new SipMessage);
1372 mDialog.makeResponse(*p481, msg, 481);
1373 send(p481);
1374 return false;
1375 }
1376
1377 void
1378 ServerInviteSession::prackCheckQueue()
1379 {
1380 InfoLog (<< "prackCheckQueue: " << mQueuedResponses.size() );
1381 if(mQueuedResponses.size() > 0 && mQueuedResponses.front().first < 200)
1382 {
1383 InfoLog (<< "Sending queued provisional" );
1384 sendProvisional(mQueuedResponses.front().first, mQueuedResponses.front().second);
1385 mQueuedResponses.pop_front();
1386 }
1387 else if(mQueuedResponses.size() > 0 && mQueuedResponses.front().first < 300)
1388 {
1389 InfoLog (<< "Sending queued 200 OK" );
1390 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1391 transition(UAS_Accepted);
1392 Contents* sdp = 0;
1393 if( !mAnswerSentReliably && mCurrentLocalOfferAnswer.get())
1394 {
1395 sdp = mCurrentLocalOfferAnswer.get();
1396 }
1397 sendAccept(mQueuedResponses.front().first, sdp);
1398 handler->onConnected(getSessionHandle(), *mInvite200);
1399 mQueuedResponses.clear(); // shouldn't be any provisionals or 200's behind us in queue - just clear the entire queue
1400 }
1401 }
1402
1403 void
1404 ServerInviteSession::updateCheckQueue()
1405 {
1406 // TODO - should we be skipping over or ignoring any provisionals in the queue?
1407 InfoLog (<< "updateCheckQueue: " << mQueuedResponses.size() );
1408 if(mQueuedResponses.size() > 0 &&
1409 mQueuedResponses.front().first >= 200 &&
1410 mQueuedResponses.front().first < 300)
1411 {
1412 InfoLog (<< "Sending queued 200 OK" );
1413 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1414 transition(UAS_Accepted);
1415 sendAccept(mQueuedResponses.front().first, 0);
1416 handler->onConnected(getSessionHandle(), *mInvite200);
1417 mQueuedResponses.pop_front();
1418 }
1419 }
1420
1421 void
1422 ServerInviteSession::dispatchOfferReliableProvidedAnswer(const SipMessage& msg)
1423 {
1424 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1425 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1426
1427 switch (toEvent(msg, offerAnswer.get()))
1428 {
1429 case OnCancel:
1430 dispatchCancel(msg);
1431 break;
1432
1433 case OnBye:
1434 dispatchBye(msg);
1435 break;
1436
1437 case OnPrack:
1438 if(handlePrack(msg))
1439 {
1440 if(offerAnswer.get())
1441 {
1442 // 2nd offer, we haven't answered the first one - log error an proceed by igoring body
1443 ErrLog (<< "PRACK with new offer when in state=" << toData(mState));
1444
1445 mEndReason = IllegalNegotiation;
1446 transition(Terminated);
1447 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1448
1449 // 406 the Prack
1450 SharedPtr<SipMessage> p406(new SipMessage);
1451 mDialog.makeResponse(*p406, msg, 406);
1452 send(p406);
1453
1454 // 406 the Invite
1455 SharedPtr<SipMessage> i406(new SipMessage);
1456 mDialog.makeResponse(*i406, mFirstRequest, 406);
1457 send(i406);
1458
1459 mDum.destroy(this);
1460 }
1461 else
1462 {
1463 // Send 200/PRACK
1464 SharedPtr<SipMessage> p200(new SipMessage);
1465 mDialog.makeResponse(*p200, msg, 200);
1466 send(p200);
1467
1468 // If we have a provisional to send with answer then transition to UAS_FirstSentAnswerReliable
1469 if(mQueuedResponses.size() > 0 &&
1470 mQueuedResponses.front().first < 200 &&
1471 mQueuedResponses.front().second) // Early flag is on
1472 {
1473 transition(UAS_FirstSentAnswerReliable);
1474 }
1475 handler->onPrack(getHandle(), msg);
1476 prackCheckQueue();
1477 }
1478 }
1479 break;
1480
1481 default:
1482 if(msg.isRequest())
1483 {
1484 dispatchUnknown(msg);
1485 }
1486 break;
1487 }
1488 }
1489
1490 void
1491 ServerInviteSession::dispatchFirstSentAnswerReliable(const SipMessage& msg)
1492 {
1493 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1494 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1495
1496 switch (toEvent(msg, offerAnswer.get()))
1497 {
1498 case OnCancel:
1499 dispatchCancel(msg);
1500 break;
1501
1502 case OnBye:
1503 dispatchBye(msg);
1504 break;
1505
1506 case OnPrack:
1507 if(handlePrack(msg))
1508 {
1509 if(offerAnswer.get()) // New offer
1510 {
1511 // If we have an offer in the prack and the dum user also tried to provide a new offer, then
1512 // reject the dum api offer and pass the one from the wire to the application
1513 if(mProposedLocalOfferAnswer.get())
1514 {
1515 //!slg! -- should this be onIllegalNegotiation?
1516 handler->onOfferRejected(getSessionHandle(), 0);
1517 }
1518 // dispatch offer here and respond with 200OK in provideAnswer
1519 transition(UAS_NegotiatedReliable);
1520 mPrackWithOffer = resip::SharedPtr<SipMessage>(new SipMessage(msg));
1521 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1522 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1523 handler->onPrack(getHandle(), msg);
1524 if(!isTerminated())
1525 {
1526 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
1527 }
1528 }
1529 else
1530 {
1531 SharedPtr<SipMessage> p200(new SipMessage);
1532 mDialog.makeResponse(*p200, msg, 200);
1533 send(p200);
1534 // check if we have a queued up offer then sent it - if not check prack queue
1535 if(mProposedLocalOfferAnswer.get())
1536 {
1537 transition(UAS_SentUpdate);
1538 handler->onPrack(getHandle(), msg);
1539 sendUpdate(*mProposedLocalOfferAnswer.get());
1540 }
1541 else
1542 {
1543 transition(UAS_NegotiatedReliable);
1544 handler->onPrack(getHandle(), msg);
1545 prackCheckQueue();
1546 }
1547 }
1548 }
1549 break;
1550
1551 default:
1552 if(msg.isRequest())
1553 {
1554 dispatchUnknown(msg);
1555 }
1556 break;
1557 }
1558 }
1559
1560 void
1561 ServerInviteSession::dispatchNoAnswerReliableWaitingPrack(const SipMessage& msg)
1562 {
1563 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1564 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1565
1566 switch (toEvent(msg, offerAnswer.get()))
1567 {
1568 case OnCancel:
1569 dispatchCancel(msg);
1570 break;
1571
1572 case OnBye:
1573 dispatchBye(msg);
1574 break;
1575
1576 case OnPrack:
1577 if(handlePrack(msg))
1578 {
1579 if(offerAnswer.get())
1580 {
1581 // 2nd offer, we haven't answered the first one - log error an proceed by igoring body
1582 ErrLog (<< "PRACK with new offer when in state=" << toData(mState));
1583
1584 mEndReason = IllegalNegotiation;
1585 transition(Terminated);
1586 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1587
1588 // 406 the Prack
1589 SharedPtr<SipMessage> p406(new SipMessage);
1590 mDialog.makeResponse(*p406, msg, 406);
1591 send(p406);
1592
1593 // 406 the Invite
1594 SharedPtr<SipMessage> i406(new SipMessage);
1595 mDialog.makeResponse(*i406, mFirstRequest, 406);
1596 send(i406);
1597
1598 mDum.destroy(this);
1599 }
1600 else
1601 {
1602 // Send 200/PRACK
1603 SharedPtr<SipMessage> p200(new SipMessage);
1604 mDialog.makeResponse(*p200, msg, 200);
1605 send(p200);
1606
1607 transition(UAS_NoAnswerReliable);
1608 handler->onPrack(getHandle(), msg);
1609 prackCheckQueue();
1610 }
1611 }
1612 break;
1613
1614 default:
1615 if(msg.isRequest())
1616 {
1617 dispatchUnknown(msg);
1618 }
1619 break;
1620 }
1621 }
1622
1623 void
1624 ServerInviteSession::dispatchSentUpdate(const SipMessage& msg)
1625 {
1626 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1627 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1628
1629 switch (toEvent(msg, offerAnswer.get()))
1630 {
1631 case OnCancel:
1632 dispatchCancel(msg);
1633 break;
1634
1635 case OnBye:
1636 dispatchBye(msg);
1637 break;
1638
1639 case OnUpdate:
1640 case OnUpdateOffer:
1641 {
1642 // Glare
1643 SharedPtr<SipMessage> response(new SipMessage);
1644 mDialog.makeResponse(*response, msg, 491);
1645 send(response);
1646 break;
1647 }
1648
1649 case On200Update:
1650 transition(UAS_NegotiatedReliable);
1651 if (offerAnswer.get())
1652 {
1653 setCurrentLocalOfferAnswer(msg);
1654 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1655 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1656 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
1657 }
1658 prackCheckQueue(); // needed for when provideOffer then accept are both called in FirstSentAnswerReliable
1659 break;
1660
1661 case OnUpdateRejected:
1662 case OnGeneralFailure: // handle 481 or 408 responses
1663 transition(UAS_NegotiatedReliable);
1664 mProposedLocalOfferAnswer.reset();
1665 handler->onOfferRejected(getSessionHandle(), &msg);
1666 prackCheckQueue(); // needed for when provideOffer then accept are both called in FirstSentAnswerReliable
1667 break;
1668
1669 case On491Update:
1670 transition(UAS_SentUpdateGlare);
1671 start491Timer();
1672 break;
1673
1674 default:
1675 if(msg.isRequest())
1676 {
1677 dispatchUnknown(msg);
1678 }
1679 break;
1680 }
1681 }
1682
1683 void
1684 ServerInviteSession::dispatchSentUpdateGlare(const SipMessage& msg)
1685 {
1686 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1687 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1688
1689 switch (toEvent(msg, offerAnswer.get()))
1690 {
1691 case OnCancel:
1692 dispatchCancel(msg);
1693 break;
1694
1695 case OnBye:
1696 dispatchBye(msg);
1697 break;
1698
1699 case OnUpdate:
1700 case OnUpdateOffer:
1701 handler->onOfferRejected(getSessionHandle(), &msg);
1702 // handle as if we received in NegotiatedReliable
1703 dispatchNegotiatedReliable(msg);
1704 break;
1705
1706 default:
1707 if(msg.isRequest())
1708 {
1709 dispatchUnknown(msg);
1710 }
1711 break;
1712 }
1713 }
1714
1715 void
1716 ServerInviteSession::dispatchSentUpdateAccepted(const SipMessage& msg)
1717 {
1718 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1719 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1720
1721 switch (toEvent(msg, offerAnswer.get()))
1722 {
1723 case OnCancel:
1724 dispatchCancel(msg);
1725 break;
1726
1727 case OnBye:
1728 dispatchBye(msg);
1729 break;
1730
1731 case On200Update:
1732 transition(UAS_Accepted);
1733 if (offerAnswer.get())
1734 {
1735 setCurrentLocalOfferAnswer(msg);
1736 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1737 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1738 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
1739 }
1740 updateCheckQueue();
1741 break;
1742
1743 case OnUpdateRejected:
1744 case OnGeneralFailure: // handle 481 or 408 responses
1745 transition(UAS_Accepted);
1746 mProposedLocalOfferAnswer.reset();
1747 handler->onOfferRejected(getSessionHandle(), &msg);
1748 updateCheckQueue();
1749 break;
1750
1751 case On491Update:
1752 // strange case - we send an offer then called accept and the offer/update got 491'd - treating the same as any offer error
1753 transition(UAS_Accepted);
1754 mProposedLocalOfferAnswer.reset();
1755 handler->onOfferRejected(getSessionHandle(), &msg);
1756 updateCheckQueue();
1757 break;
1758
1759 default:
1760 if(msg.isRequest())
1761 {
1762 dispatchUnknown(msg);
1763 }
1764 break;
1765 }
1766 }
1767
1768 void
1769 ServerInviteSession::dispatchReceivedUpdate(const SipMessage& msg)
1770 {
1771 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1772
1773 switch (toEvent(msg, offerAnswer.get()))
1774 {
1775 case OnCancel:
1776 dispatchCancel(msg);
1777 break;
1778
1779 case OnBye:
1780 dispatchBye(msg);
1781 break;
1782
1783 case OnUpdate:
1784 case OnUpdateOffer:
1785 // If we receive an UPDATE before we have generated a final response to a previous UPDATE on the
1786 // same dialog, then we MUST return a 500 response with a Retry-After header (random duration 0-10 seconds)
1787 {
1788 SharedPtr<SipMessage> u500(new SipMessage);
1789 mDialog.makeResponse(*u500, msg, 500);
1790 u500->header(h_RetryAfter).value() = Random::getRandom() % 10;
1791 send(u500);
1792 }
1793 break;
1794
1795 default:
1796 if(msg.isRequest())
1797 {
1798 dispatchUnknown(msg);
1799 }
1800 break;
1801 }
1802 }
1803
1804 void
1805 ServerInviteSession::dispatchReceivedUpdateWaitingAnswer(const SipMessage& msg)
1806 {
1807 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1808
1809 switch (toEvent(msg, offerAnswer.get()))
1810 {
1811 case OnCancel:
1812 dispatchCancel(msg);
1813 break;
1814
1815 case OnBye:
1816 dispatchBye(msg);
1817 break;
1818
1819 case OnUpdate:
1820 case OnUpdateOffer:
1821 // A UAS that receives an UPDATE before it has generated a final response to a previous UPDATE on the
1822 // same dialog MUST return a 500 response
1823 {
1824 SharedPtr<SipMessage> u500(new SipMessage);
1825 mDialog.makeResponse(*u500, msg, 500);
1826 send(u500);
1827 }
1828 break;
1829
1830 default:
1831 if(msg.isRequest())
1832 {
1833 dispatchUnknown(msg);
1834 }
1835 break;
1836 }
1837 }
1838
1839 void
1840 ServerInviteSession::dispatchNegotiatedReliable(const SipMessage& msg)
1841 {
1842 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1843 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1844
1845 switch (toEvent(msg, offerAnswer.get()))
1846 {
1847 case OnCancel:
1848 dispatchCancel(msg);
1849 break;
1850
1851 case OnBye:
1852 dispatchBye(msg);
1853 break;
1854
1855 case OnPrack:
1856 if(handlePrack(msg))
1857 {
1858 if(offerAnswer.get()) // New offer
1859 {
1860 // dispatch offer here and respond with 200OK in provideAnswer
1861 mPrackWithOffer = resip::SharedPtr<SipMessage>(new SipMessage(msg));
1862 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1863 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1864 handler->onPrack(getHandle(), msg);
1865 if(!isTerminated())
1866 {
1867 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
1868 }
1869 }
1870 else
1871 {
1872 SharedPtr<SipMessage> p200(new SipMessage);
1873 mDialog.makeResponse(*p200, msg, 200);
1874 send(p200);
1875 handler->onPrack(getHandle(), msg);
1876 prackCheckQueue();
1877 }
1878 }
1879 break;
1880
1881 case OnUpdateOffer:
1882 *mLastRemoteSessionModification = msg;
1883 transition(UAS_ReceivedUpdate);
1884 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer);
1885 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1886 if(!isTerminated())
1887 {
1888 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
1889 }
1890 break;
1891
1892 case OnUpdate:
1893 {
1894 // UPDATE with no offer just respond with 200
1895 SharedPtr<SipMessage> u200(new SipMessage);
1896 mDialog.makeResponse(*u200, msg, 200);
1897 send(u200);
1898 }
1899 break;
1900
1901 default:
1902 if(msg.isRequest())
1903 {
1904 dispatchUnknown(msg);
1905 }
1906 break;
1907 }
1908 }
1909
1910 void
1911 ServerInviteSession::dispatchWaitingToHangup(const SipMessage& msg)
1912 {
1913 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1914
1915 switch (toEvent(msg, offerAnswer.get()))
1916 {
1917 case OnAck:
1918 case OnAckAnswer:
1919 {
1920 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1921
1922 SharedPtr<SipMessage> msg = sendBye();
1923 transition(Terminated);
1924 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalBye, msg.get());
1925 break;
1926 }
1927
1928 default:
1929 break;
1930 }
1931 }
1932
1933 void
1934 ServerInviteSession::dispatchCancel(const SipMessage& msg)
1935 {
1936 SharedPtr<SipMessage> c200(new SipMessage);
1937 mDialog.makeResponse(*c200, msg, 200);
1938 send(c200);
1939
1940 SharedPtr<SipMessage> i487(new SipMessage);
1941 mDialog.makeResponse(*i487, mFirstRequest, 487);
1942 send(i487);
1943
1944 transition(Terminated);
1945
1946 if (mDum.mDialogEventStateManager)
1947 {
1948 mDum.mDialogEventStateManager->onTerminated(mDialog, msg, InviteSessionHandler::RemoteCancel);
1949 }
1950
1951 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::RemoteCancel, &msg);
1952 mDum.destroy(this);
1953 }
1954
1955 void
1956 ServerInviteSession::dispatchBye(const SipMessage& msg)
1957 {
1958 SharedPtr<SipMessage> b200(new SipMessage);
1959 mDialog.makeResponse(*b200, msg, 200);
1960 send(b200);
1961 // !dcm! -- pretty sure we shouldn't 487 after the BYE/200
1962 SharedPtr<SipMessage> i487(new SipMessage);
1963 mDialog.makeResponse(*i487, mFirstRequest, 487);
1964 send(i487);
1965
1966 transition(Terminated);
1967
1968 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::RemoteBye, &msg);
1969 mDum.destroy(this);
1970 }
1971
1972 void
1973 ServerInviteSession::dispatchUnknown(const SipMessage& msg)
1974 {
1975 InfoLog (<< "Unknown request (" << msg.brief() << ") received in state=" << toData(mState) << ", rejecting request and terminating call.");
1976
1977 SharedPtr<SipMessage> r500(new SipMessage);
1978 mDialog.makeResponse(*r500, msg, 500);
1979 send(r500);
1980
1981 SharedPtr<SipMessage> i400(new SipMessage);
1982 mDialog.makeResponse(*i400, mFirstRequest, 400);
1983 send(i400);
1984
1985 transition(Terminated);
1986 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg);
1987 mDum.destroy(this);
1988 }
1989
1990 void
1991 ServerInviteSession::startRetransmit1xxTimer()
1992 {
1993 // RFC3261 13.3.1 says the UAS must send a non-100 provisional response every minute, to handle the possiblity of lost provisional responses
1994 int retransmissionTime = mDialog.mDialogSet.getUserProfile()->get1xxRetransmissionTime();
1995 if(retransmissionTime > 0 && m1xx->header(resip::h_StatusLine).statusCode() > 100)
1996 {
1997 mDum.addTimer(DumTimeout::Retransmit1xx, retransmissionTime, getBaseHandle(), ++mCurrentRetransmit1xxSeq);
1998 }
1999 }
2000
2001 void
2002 ServerInviteSession::startResubmit1xxRelTimer()
2003 {
2004 // RFC3262 section says the UAS SHOULD send reliable provisional responses once every two and half minutes
2005 int resubmitTime = mDialog.mDialogSet.getUserProfile()->get1xxRelResubmitTime();
2006 if(resubmitTime > 0 && m1xx->header(resip::h_StatusLine).statusCode() > 100)
2007 {
2008 mDum.addTimer(DumTimeout::Resubmit1xxRel, resubmitTime, getBaseHandle(), ++mCurrentRetransmit1xxSeq); // This timer serves the same purpose at the unreliable retransmit timer - use the same sequence number
2009 }
2010 }
2011
2012 void
2013 ServerInviteSession::startRetransmit1xxRelTimer()
2014 {
2015 unsigned int seq = m1xx->header(h_RSeq).value();
2016 mDum.addTimerMs(DumTimeout::Retransmit1xxRel, Timer::T1, getBaseHandle(), seq, Timer::T1);
2017 }
2018
2019 bool
2020 ServerInviteSession::sendProvisional(int code, bool earlyFlag)
2021 {
2022 m1xx->setContents(0);
2023 mDialog.makeResponse(*m1xx, mFirstRequest, code);
2024
2025 bool sendReliably = code > 100 && // Must be a non-100 response
2026 ((mFirstRequest.exists(h_Requires) && mFirstRequest.header(h_Requires).find(Token(Symbols::C100rel))) || // Far end requires it (note: we must at least support it or the invite would have been rejected already)
2027 mDum.getMasterProfile()->getUasReliableProvisionalMode() == MasterProfile::Required || // OR we require it (note: far end must at least support it or the invite would have been rejected)
2028 (mFirstRequest.exists(h_Supporteds) && mFirstRequest.header(h_Supporteds).find(Token(Symbols::C100rel)) && // OR far ends supports it and we support it
2029 mDum.getMasterProfile()->getUasReliableProvisionalMode() == MasterProfile::Supported)); // (note: SupportedEssential is not trapped here, cases for it are added below)
2030
2031 switch (mState)
2032 {
2033 case UAS_OfferProvidedAnswer:
2034 case UAS_EarlyProvidedAnswer:
2035 if (code > 100 && earlyFlag && mCurrentLocalOfferAnswer.get()) // early media
2036 {
2037 setOfferAnswer(*m1xx, mCurrentLocalOfferAnswer.get());
2038 }
2039 break;
2040
2041 case UAS_FirstSentAnswerReliable: // This is possible if someone called provisional() from the onPrack callback (since we change states after we call onPrack)
2042 case UAS_OfferReliableProvidedAnswer: // MAY send answer in reliable response - send only if earlyFlag is set
2043 if (code > 100 && earlyFlag && !mAnswerSentReliably && mCurrentLocalOfferAnswer.get()) // early media
2044 {
2045 setOfferAnswer(*m1xx, mCurrentLocalOfferAnswer.get());
2046 mAnswerSentReliably = true;
2047 sendReliably = true; // If UasReliableProvisionalMode is SupportEssential this may flip sendReliably to true
2048 }
2049 break;
2050
2051 case UAS_NoOfferReliable:
2052 if(sendReliably)
2053 {
2054 // Invite requires reliable responses - since there was no offer in the INVITE we MUST
2055 // provide an offer in the first reliable response. We would be in the ProvidedOfferReliable
2056 // state if that was the case. Looks like provisional was called too early!
2057 DebugLog( << "Sending a reliable provisional after receiving an INVITE with no offer, requires provideOffer to be called first (RFC3262-Section 5).");
2058 assert(false);
2059 return false;
2060 }
2061 break;
2062
2063 case UAS_ProvidedOfferReliable:
2064 // ignore early flag if we must sendReliably, since first reliable 1xx MUST contain Offer
2065 if (code > 100 && (earlyFlag || sendReliably) && mProposedLocalOfferAnswer.get())
2066 {
2067 setOfferAnswer(*m1xx, mProposedLocalOfferAnswer.get());
2068 sendReliably = true; // If UasReliableProvisionalMode is SupportEssential this may flip sendReliably to true
2069 }
2070 break;
2071
2072 case UAS_ProvidedOffer:
2073 case UAS_EarlyProvidedOffer:
2074 if (code > 100 && earlyFlag && mProposedLocalOfferAnswer.get())
2075 {
2076 setOfferAnswer(*m1xx, mProposedLocalOfferAnswer.get());
2077 }
2078 break;
2079
2080 default:
2081 break;
2082 }
2083 DumHelper::setOutgoingEncryptionLevel(*m1xx, mProposedEncryptionLevel);
2084
2085 if(sendReliably)
2086 {
2087 DebugLog ( << "Sending provisional reliably" );
2088 if (!m1xx->exists(h_Requires) ||
2089 !m1xx->header(h_Requires).find(Token(Symbols::C100rel)))
2090 {
2091 m1xx->header(h_Requires).push_back(Token(Symbols::C100rel));
2092 }
2093 m1xx->header(h_RSeq).value() = ++mLocalRSeq;
2094
2095 // We are supposed to advertised our Allow header in reliable provisionals - Add Advertised
2096 // Capabilities - allows UAC to detect UPDATE support before 200 response
2097 mDum.setAdvertisedCapabilities(*m1xx.get(), mDialog.mDialogSet.getUserProfile());
2098
2099 assert(!mUnacknowledgedReliableProvisional.get());
2100 mUnacknowledgedReliableProvisional = m1xx;
2101 startRetransmit1xxRelTimer(); // handles retransmissions until PRACK arrives
2102 startResubmit1xxRelTimer(); // handles - RFC3262 section says the UAS SHOULD send provisional reliable responses once every two and half minutes
2103 }
2104 else
2105 {
2106 // Make sure there is no RSeq or Requires 100rel
2107 if(m1xx->exists(h_RSeq))
2108 {
2109 m1xx->remove(h_RSeq);
2110 }
2111 if(m1xx->exists(h_Requires))
2112 {
2113 ParserContainer<Token>::iterator it = m1xx->header(h_Requires).begin();
2114 for(; it != m1xx->header(h_Requires).end(); it++)
2115 {
2116 if((*it) == Token(Symbols::C100rel))
2117 {
2118 m1xx->header(h_Requires).erase(it);
2119 break;
2120 }
2121 }
2122 }
2123 startRetransmit1xxTimer();
2124 }
2125
2126 if (mDum.mDialogEventStateManager)
2127 {
2128 mDum.mDialogEventStateManager->onEarly(mDialog, getSessionHandle());
2129 }
2130
2131 send(m1xx);
2132 return sendReliably;
2133 }
2134
2135 void
2136 ServerInviteSession::queueResponse(int code, bool earlyFlag)
2137 {
2138 InfoLog (<< "Response " << code << " queued." );
2139 mQueuedResponses.push_back( std::make_pair(code, earlyFlag) );
2140 }
2141
2142 void
2143 ServerInviteSession::sendAccept(int code, Contents* offerAnswer)
2144 {
2145 mDialog.makeResponse(*mInvite200, mFirstRequest, code);
2146 handleSessionTimerRequest(*mInvite200, mFirstRequest);
2147 if (offerAnswer && !mAnswerSentReliably )
2148 {
2149 setOfferAnswer(*mInvite200, offerAnswer);
2150 mAnswerSentReliably = true;
2151 }
2152 mCurrentRetransmit1xxSeq++; // Stop the 1xx timer - causes timer to be ignored on expirey
2153 startRetransmit200Timer(); // 2xx timer
2154 DumHelper::setOutgoingEncryptionLevel(*mInvite200, mCurrentEncryptionLevel);
2155
2156 if (mDum.mDialogEventStateManager)
2157 {
2158 mDum.mDialogEventStateManager->onConfirmed(mDialog, getSessionHandle());
2159 }
2160
2161 send(mInvite200);
2162 }
2163
2164 void
2165 ServerInviteSession::sendUpdate(const Contents& offerAnswer)
2166 {
2167 if (updateMethodSupported())
2168 {
2169 mDialog.makeRequest(*mLastLocalSessionModification, UPDATE);
2170 InviteSession::setOfferAnswer(*mLastLocalSessionModification, offerAnswer);
2171 DumHelper::setOutgoingEncryptionLevel(*mLastLocalSessionModification, mProposedEncryptionLevel);
2172 send(mLastLocalSessionModification);
2173 }
2174 else
2175 {
2176 throw UsageUseException("Can't send UPDATE to peer", __FILE__, __LINE__);
2177 }
2178 }
2179
2180 /* ====================================================================
2181 * The Vovida Software License, Version 1.0
2182 *
2183 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
2184 *
2185 * Redistribution and use in source and binary forms, with or without
2186 * modification, are permitted provided that the following conditions
2187 * are met:
2188 *
2189 * 1. Redistributions of source code must retain the above copyright
2190 * notice, this list of conditions and the following disclaimer.
2191 *
2192 * 2. Redistributions in binary form must reproduce the above copyright
2193 * notice, this list of conditions and the following disclaimer in
2194 * the documentation and/or other materials provided with the
2195
2196 * distribution.
2197 *
2198 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2199 * and "Vovida Open Communication Application Library (VOCAL)" must
2200 * not be used to endorse or promote products derived from this
2201 * software without prior written permission. For written
2202 * permission, please contact vocal@vovida.org.
2203 *
2204 * 4. Products derived from this software may not be called "VOCAL", nor
2205 * may "VOCAL" appear in their name, without prior written
2206 * permission of Vovida Networks, Inc.
2207 *
2208 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2209 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2210 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2211 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
2212 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2213 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2214 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2215 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2216 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2217 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2218 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2219 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2220 * DAMAGE.
2221 *
2222 * ====================================================================
2223 *
2224 * This software consists of voluntary contributions made by Vovida
2225 * Networks, Inc. and many individuals on behalf of Vovida Networks,
2226 * Inc. For more information on Vovida Networks, Inc., please see
2227 * <http://www.vovida.org/>.
2228 *
2229 */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27