reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ClientInviteSession.cxx
Go to the documentation of this file.
1
16#include "rutil/Logger.hxx"
17#include "rutil/Random.hxx"
18#include "rutil/compat.hxx"
20
21#include <utility>
22
23#define RESIPROCATE_SUBSYSTEM Subsystem::DUM
24
25using namespace resip;
26using namespace std;
27
29 Dialog& dialog,
30 std::shared_ptr<SipMessage> request,
31 const Contents* initialOffer,
33 ServerSubscriptionHandle serverSub) :
34 InviteSession(dum, dialog),
35 mStaleCallTimerSeq(1),
36 mCancelledTimerSeq(1),
37 mServerSub(serverSub),
38 mAllowOfferInPrack(false)
39{
40 resip_assert(request->isRequest());
41 if(initialOffer)
42 {
43 mProposedLocalOfferAnswer = unique_ptr<Contents>(initialOffer->clone());
45 }
46 *mLastLocalSessionModification = *request; // Copy message, so that modifications to mLastLocalSessionModification don't effect creator->getLastRequest
47
49}
50
56
57const Contents&
59{
60 return *mEarlyMedia;
61}
62
63void
65{
66 InfoLog (<< toData(mState) << ": provideOffer");
67
68 switch(mState)
69 {
71 if(mAllowOfferInPrack)
72 {
73 // This flag is enabled when we are about to send our first PRACK. We are
74 // allowed to send an offer in our first PRACK request, so don't use UPDATE in
75 // this case.
76 // Remember proposed local offerAnswer.
79 }
80 else
81 {
83
84 // Creates an UPDATE request with application supplied offer.
87
88 // Remember proposed local offerAnswer.
91
92 // Send the req and do state transition.
95 }
96 break;
97
98 case UAC_SentAnswer:
99 // just queue it for later
103 break;
104
105 case UAC_Start:
106 case UAC_Early:
108 case UAC_Answered:
111 case UAC_Cancelled:
112 case UAC_QueuedUpdate:
113 case Terminated:
114 WarningLog (<< "Incorrect state to provideOffer: " << toData(mState));
115 throw DialogUsage::Exception("Can't provide an offer", __FILE__,__LINE__);
116 break;
117
118 default:
119 InviteSession::provideOffer(offer, level, alternative);
120 break;
121 }
122}
123
124void
129
130void
132{
133 InfoLog (<< toData(mState) << ": provideAnswer");
134
135 switch(mState)
136 {
138 {
140
141 // Remember proposed local offerAnswer.
144
145 // Creates a PRACK request with application supplied answer
146 sendPrack(answer, mCurrentEncryptionLevel);
147 break;
148 }
149
150 case UAC_Answered:
151 {
153 std::shared_ptr<SipMessage> ack = sendAck(&answer);
154
157 break;
158 }
160 {
161 transition(UAC_EarlyWithAnswer); //.dcm. earlyWithAnswer is a strange
162 //name...maybe earlyEstablished?
163 //this sequence is repeated in many places...due for refactoring.
164 //see ReceivedUpdate handling in InviteSession.
165 //?dcm? are session timers allowed in the early dialog?
166
167 auto response = std::make_shared<SipMessage>();
169 InviteSession::setOfferAnswer(*response, answer, 0);
172 InfoLog (<< "Sending " << response->brief());
174 send(response);
175 break;
176 }
177
178 case UAC_Start:
179 case UAC_Early:
182 case UAC_SentAnswer:
183 case UAC_Cancelled:
184 case UAC_QueuedUpdate:
185 case Terminated:
186 WarningLog (<< "Incorrect state to provideAnswer: " << toData(mState));
187 throw DialogUsage::Exception("Can't provide an answer", __FILE__,__LINE__);
188 break;
189
190 default:
192 break;
193 }
194}
195
196void
201
202void
204{
205 mUserEndReason = userReason;
207}
208
209void
215
216void
218{
219 InfoLog (<< toData(mState) << ": end");
221 {
222 mEndReason = reason;
223 }
224
225 switch(mState)
226 {
227 case UAC_Early:
230 case UAC_Answered:
233 case UAC_SentAnswer:
234 case UAC_QueuedUpdate:
235 case UAC_Cancelled: // !jf! possibly incorrect to always BYE in UAC_Cancelled
236 {
237 const auto msg = sendBye();
239 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalBye, msg.get());
240 break;
241 }
242
243 case UAC_Start:
244 WarningLog (<< "Try to end when in state=" << toData(mState));
245 resip_assert(0);
246 break;
247
248 case Terminated:
249 // no-op
250 break;
251
252 default:
253 InviteSession::end(reason);
254 break;
255 }
256}
257
258void
260{
261 reject(statusCode, nullptr, warning);
262}
263
264void
265ClientInviteSession::reject (int statusCode, const Contents* contents, WarningCategory *warning)
266{
267 InfoLog (<< toData(mState) << ": reject(" << statusCode << ")");
268
269 switch(mState)
270 {
272 {
273 auto response = std::make_shared<SipMessage>();
274 mDialog.makeResponse(*response, *mLastRemoteSessionModification, statusCode);
275 // In case we wanted to reject the request by including content
276 if (contents)
277 {
278 response->setContents(contents);
279 }
280 if(warning)
281 {
282 response->header(h_Warnings).push_back(*warning);
283 }
284
285 // Send the req and do state transition.
286 send(response);
288 break;
289 }
290
291 case UAC_Answered:
292 {
293 // We received an offer in a 2xx response, and we want to reject it
294 // ACK with no body, then send bye
295 sendAck();
296 const auto msg = sendBye();
298 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalBye, msg.get());
299 break;
300 }
301
302 case UAC_Start:
303 case UAC_Early:
307 case UAC_SentAnswer:
308 case UAC_Cancelled:
309 WarningLog (<< "Try to reject when in state=" << toData(mState));
310 resip_assert(0);
311 break;
312
313 default:
314 InviteSession::reject(statusCode, contents, warning);
315 break;
316 }
317}
318
319void
320ClientInviteSession::cancel()
321{
322 switch(mState)
323 {
324 case UAC_Early:
329 case UAC_SentAnswer:
330 InfoLog (<< toData(mState) << ": cancel");
331 startCancelTimer();
333 break;
334
335 case UAC_Cancelled:
336 case Terminated:
337 // no-op already cancelled or ended
338 break;
339
340 default:
341 resip_assert(0);
342 break;
343 }
344}
345
346void
347ClientInviteSession::onForkAccepted()
348{
349 switch(mState)
350 {
351 case UAC_Early:
356 InfoLog (<< toData(mState) << ": onForkAccepted");
357 // !jf! should we avoid creating another timer here? I don't think it
358 // matters. Default timer is for 32secs. This is here to handle the
359 // cleanup on forked INVITEs that have sent a provisional response but
360 // don't ever receive a final response.
362 break;
363 default:
364 // If the dialog is already set up (or cancelled) we disregard.
365 break;
366 }
367}
368
369void
370ClientInviteSession::startCancelTimer()
371{
372 InfoLog (<< toData(mState) << ": startCancelTimer");
373 mDum.addTimerMs(DumTimeout::Cancelled, Timer::TH, getBaseHandle(), ++mCancelledTimerSeq);
374}
375
376void
377ClientInviteSession::startStaleCallTimer()
378{
379 InfoLog (<< toData(mState) << ": startStaleCallTimer");
380 unsigned long when = mDialog.mDialogSet.getUserProfile()->getDefaultStaleCallTime();
381
382 mDum.addTimer(DumTimeout::StaleCall,
383 when,
384 getBaseHandle(),
385 ++mStaleCallTimerSeq);
386}
387
388void
389ClientInviteSession::sendSipFrag(const SipMessage& msg)
390{
391 if (mServerSub.isValid())
392 {
393 if (msg.isResponse() && mState >= UAC_Start && mState <= UAC_Cancelled)
394 {
395 int code = msg.header(h_StatusLine).statusCode();
396 if (code > 100)
397 {
398 SipFrag contents;
399 contents.message().header(h_StatusLine) = msg.header(h_StatusLine);
400 if(mDialog.mDialogSet.getUserProfile()->getExtraHeadersInReferNotifySipFragEnabled())
401 {
402 contents.message().header(h_Vias) = msg.header(h_Vias);
403 contents.message().header(h_From) = msg.header(h_From);
404 contents.message().header(h_To) = msg.header(h_To);
405 contents.message().header(h_CallId) = msg.header(h_CallId);
406 contents.message().header(h_CSeq) = msg.header(h_CSeq);
407 contents.message().header(h_Contacts) = msg.header(h_Contacts);
408 }
409 if (code < 200)
410 {
411 mServerSub->send(mServerSub->update(&contents));
412 }
413 else
414 {
415 mServerSub->end(NoResource, &contents);
416 }
417 }
418 }
419 }
420}
421
422void
423ClientInviteSession::dispatch(const SipMessage& msg)
424{
425 try
426 {
427 if (msg.isRequest())
428 {
429 if (msg.header(h_RequestLine).method() == INFO)
430 {
432 return;
433 }
434 if (msg.header(h_RequestLine).method() == MESSAGE)
435 {
437 return;
438 }
439 }
440
441 if (isBadRseq(msg))
442 {
443 return;
444 }
445
446 sendSipFrag(msg);
447 switch(mState)
448 {
449 case UAC_Start:
450 dispatchStart(msg);
451 break;
452 case UAC_Early:
453 dispatchEarly(msg);
454 break;
456 dispatchEarlyWithOffer(msg);
457 break;
459 dispatchEarlyWithAnswer(msg);
460 break;
461 case UAC_Answered:
462 dispatchAnswered(msg);
463 break;
465 dispatchSentUpdateEarly(msg);
466 break;
468 dispatchSentUpdateEarlyGlare(msg);
469 break;
471 dispatchReceivedUpdateEarly(msg);
472 break;
473 case UAC_SentAnswer:
474 dispatchSentAnswer(msg);
475 break;
476 case UAC_QueuedUpdate:
477 dispatchQueuedUpdate(msg);
478 break;
479 case UAC_Cancelled:
480 dispatchCancelled(msg);
481 break;
482 default:
484 break;
485 }
486 }
487 catch (BaseException& e)
488 {
489 WarningLog (<< "Caught: " << e);
490 onFailureAspect(getHandle(), msg);
492 }
493}
494
495void
496ClientInviteSession::dispatch(const DumTimeout& timer)
497{
498 if (timer.type() == DumTimeout::Cancelled)
499 {
500 if(timer.seq() == mCancelledTimerSeq)
501 {
502 if (mServerSub.isValid())
503 {
504 SipMessage response;
506 sendSipFrag(response);
507 }
510 mDum.destroy(this);
511 }
512 }
513 else if (timer.type() == DumTimeout::StaleCall)
514 {
515 if(timer.seq() == mStaleCallTimerSeq)
516 {
517 mDum.mInviteSessionHandler->onStaleCallTimeout(getHandle());
518 mDum.mInviteSessionHandler->terminate(getHandle());
519 }
520 }
521 else if (timer.type() == DumTimeout::WaitingForForked2xx)
522 {
524 mDum.mInviteSessionHandler->onForkDestroyed(getHandle());
525 mDum.destroy(this);
526 }
527 else if (timer.type() == DumTimeout::Glare)
528 {
530 {
532 InfoLog (<< "Retransmitting the UPDATE (glare condition timer)");
533 mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); // increments CSeq
535 }
536 else
537 {
539 }
540 }
541 else
542 {
544 }
545}
546
547void
548ClientInviteSession::handleRedirect (const SipMessage& msg)
549{
550 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
552
553 if (mDum.mDialogEventStateManager)
554 {
555 mDum.mDialogEventStateManager->onTerminated(mDialog, msg, InviteSessionHandler::Rejected);
556 }
557
558 handler->onRedirected(getHandle(), msg);
559 mDum.destroy(this);
560}
561
562void
563ClientInviteSession::handleProvisional(const SipMessage& msg)
564{
566 resip_assert(msg.header(h_StatusLine).statusCode() < 200);
567 resip_assert(msg.header(h_StatusLine).statusCode() > 100);
568
569 //.dcm. Kept the following checks here rather than discardMessage as the
570 // state machine can be affected(termination).
571
572 // !dcm! should we really end the InviteSession or should be discard the 1xx instead?
573 // Check CSeq in 1xx against original INVITE request
574 if (msg.header(h_CSeq).sequence() != mDialog.mDialogSet.getCreator()->getLastRequest()->header(h_CSeq).sequence())
575 {
576 InfoLog (<< "Failure: CSeq doesn't match invite: " << msg.brief());
577 onFailureAspect(getHandle(), msg);
579 return;
580 }
581 else if (isReliable(msg))
582 {
583 if (!msg.exists(h_RSeq))
584 {
585 InfoLog (<< "Failure: No RSeq in 1xx: " << msg.brief());
586 onFailureAspect(getHandle(), msg);
588 return;
589 }
590 }
591
592 startStaleCallTimer();
593 onProvisionalAspect(getHandle(), msg);
594}
595
596void
597ClientInviteSession::handleFinalResponse(const SipMessage& msg)
598{
600 resip_assert(msg.header(h_StatusLine).statusCode() >= 200);
601 resip_assert(msg.header(h_StatusLine).statusCode() < 300);
602
605 ++mStaleCallTimerSeq; // disable stale call timer
606}
607
608void
609ClientInviteSession::handle1xxOffer(const SipMessage& msg, const Contents& offer)
610{
611 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
612
613 handleProvisional(msg);
616 handler->onOffer(getSessionHandle(), msg, offer);
617}
618
619void
620ClientInviteSession::handle1xxAnswer(const SipMessage& msg, const Contents& answer)
621{
625
626 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
627 handleProvisional(msg);
628
629 // flag to let handle1xxAnswer know that it is OK to send an offer in the
630 // first PRACK (for a provisional with SDP answer) and to let providerOffer know
631 // that the offer will be going in an PRACK and not in an update. Flag is not
632 // needed after handle1xxAnswer is called so it is reset.
633 mAllowOfferInPrack = true;
634
635 handler->onAnswer(getSessionHandle(), msg, answer);
636
637 // Reset flag - no longer needed
638 mAllowOfferInPrack = false;
639
640 // If offer is provided in onAnswer callback then send offer in PRACK
642 {
644 }
645 else
646 {
647 sendPrackIfNeeded(msg);
648 }
649}
650
651// will not include SDP (this is a subsequent 1xx)
652void
653ClientInviteSession::sendPrackIfNeeded(const SipMessage& msg)
654{
656 resip_assert(msg.header(h_StatusLine).statusCode() < 200);
657 resip_assert(msg.header(h_StatusLine).statusCode() > 100);
658
659 if (isReliable(msg))
660 {
661 auto prack = std::make_shared<SipMessage>();
662 mDialog.makeRequest(*prack, PRACK);
663 prack->header(h_RAck) = mRelRespInfo;
664 send(prack);
665 }
666}
667
668// This version is used to send an answer to the UAS in PRACK from EarlyWithOffer
669// state. Assumes that it is the first PRACK. Subsequent PRACK will not have SDP
670// Also used to send an offer in the first PRACK if the 18x included an
671// answer.
672void
673ClientInviteSession::sendPrack(const Contents& offerAnswer, DialogUsageManager::EncryptionLevel encryptionLevel)
674{
675 auto prack = std::make_shared<SipMessage>();
676 mDialog.makeRequest(*prack, PRACK);
677 prack->header(h_RAck)= mRelRespInfo;
678
679 InviteSession::setOfferAnswer(*prack, offerAnswer);
680
681 DumHelper::setOutgoingEncryptionLevel(*prack, encryptionLevel);
682 send(prack);
683}
684
685void
686ClientInviteSession::dispatchStart (const SipMessage& msg)
687{
689 resip_assert(msg.header(h_StatusLine).statusCode() > 100);
690 resip_assert(msg.header(h_CSeq).method() == INVITE);
691
692 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
693 std::unique_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
694
695 InviteSession::Event event = toEvent(msg, offerAnswer.get());
696
697 switch (event)
698 {
699 case On1xx:
702 if(!isTerminated())
703 {
704 handleProvisional(msg);
705 sendPrackIfNeeded(msg); // may wish to move empty PRACK handling
706 // outside the state machine
707 }
708 break;
709
710 case On1xxEarly: // only unreliable
712 // reliable 1xx followed by a reliable 1xx. Also, the initial 1xx
713 // doesn't have to have an offer. However, DUM will only generate
714 // reliable 1xx responses when 100rel is available.
715
717 mEarlyMedia = InviteSession::makeOfferAnswer(*offerAnswer);
719 if(!isTerminated())
720 {
721 handleProvisional(msg);
722 if(!isTerminated())
723 {
724 handler->onEarlyMedia(getHandle(), msg, *offerAnswer);
725 }
726 }
727 break;
728
729 case On1xxOffer:
732 if(!isTerminated())
733 {
734 handle1xxOffer(msg, *offerAnswer);
735 }
736 break;
737
738 case On1xxAnswer:
741 if(!isTerminated())
742 {
743 handle1xxAnswer(msg, *offerAnswer);
744 }
745 break;
746
747 case On2xxOffer:
749 handleFinalResponse(msg);
754 if(!isTerminated())
755 {
756 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
757 if(!isTerminated()) // application can call end() in onOffer callback
758 {
759 onConnectedAspect(getHandle(), msg);
760 }
761 }
762 break;
763
764 case On2xxAnswer:
766 sendAck();
767 handleFinalResponse(msg);
772 if(!isTerminated()) // onNewSession callback may call end() or reject()
773 {
774 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
775 if(!isTerminated()) // onAnswer callback may call end() or reject()
776 {
777 onConnectedAspect(getHandle(), msg);
778 }
779 }
780 break;
781
782 case On2xx:
783 {
784 sendAck();
785 InfoLog(<< "Failure: 2xx with no answer: " << msg.brief());
786 sendBye();
788 onFailureAspect(getHandle(), msg);
790 break;
791 }
792
793 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionally not handled and should be treated as an INVITE failure
794 case OnInviteFailure:
795 case OnGeneralFailure:
796 case On422Invite:
797 case On487Invite:
798 case On491Invite:
799 InfoLog (<< "Failure: error response: " << msg.brief());
801 onFailureAspect(getHandle(), msg);
803 mDum.destroy(this);
804 break;
805
806 case OnBye:
807 dispatchBye(msg);
808 break;
809
810 default:
811 // !kh!
812 // should not assert here for peer sent us garbage.
813 WarningLog (<< "Don't know what this is : " << msg);
814 break;
815 }
816}
817
818void
819ClientInviteSession::dispatchEarly (const SipMessage& msg)
820{
821 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
822 std::unique_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
823
824 switch (toEvent(msg, offerAnswer.get()))
825 {
826 case On1xx:
828 handleProvisional(msg);
829 sendPrackIfNeeded(msg);
830 break;
831
832 case On1xxEarly: // only unreliable
834 handleProvisional(msg);
835 if(!isTerminated())
836 {
837 mEarlyMedia = InviteSession::makeOfferAnswer(*offerAnswer);
838 handler->onEarlyMedia(getHandle(), msg, *offerAnswer);
839 }
840 break;
841
842 case On1xxOffer:
844 handle1xxOffer(msg, *offerAnswer);
845 break;
846
847 case On1xxAnswer:
849 handle1xxAnswer(msg, *offerAnswer);
850 break;
851
852 case On2xxOffer:
854 handleFinalResponse(msg);
855
859
860 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
861 if(!isTerminated())
862 {
863 onConnectedAspect(getHandle(), msg);
864 }
865 break;
866
867 case On2xxAnswer:
869 sendAck();
870 handleFinalResponse(msg);
874 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
875 if(!isTerminated()) // onNewSession callback may call end() or reject()
876 {
877 onConnectedAspect(getHandle(), msg);
878 }
879 break;
880
881 case On2xx:
882 {
883 sendAck();
884 InfoLog (<< "Failure: 2xx with no answer: " << msg.brief());
885 sendBye();
887 onFailureAspect(getHandle(), msg);
889 break;
890 }
891
892 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionally not handled and should be treated as an INVITE failure
893 case OnInviteFailure:
894 case OnGeneralFailure:
895 case On422Invite:
896 case On487Invite:
897 InfoLog (<< "Failure: error response: " << msg.brief());
899 onFailureAspect(getHandle(), msg);
901 mDum.destroy(this);
902 break;
903
904 case OnBye:
905 dispatchBye(msg);
906 break;
907
908 case OnUpdateOffer:
910 {
911 WarningLog (<< "Invalid UPDATE with offer received in early state with pending offer: " << msg.brief());
912 auto response = std::make_shared<SipMessage>();
913 mDialog.makeResponse(*response, msg, 500); // RFC3311 - section 5.2
914 InfoLog (<< "Sending " << response->brief());
915 send(response);
916 }
917 else
918 {
923 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
924 }
925 break;
926
927 case OnUpdate:
928 {
929 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback?
930 auto response = std::make_shared<SipMessage>();
931 mDialog.makeResponse(*response, msg, 200);
932 send(response);
933 break;
934 }
935
936 case On200Prack:
937 break;
938
939 default:
940 // !kh!
941 // should not assert here for peer sent us garbage.
942 WarningLog (<< "Don't know what this is : " << msg);
943 break;
944 }
945}
946
947void
948ClientInviteSession::dispatchAnswered (const SipMessage& msg)
949{
950 //InviteSessionHandler* handler = mDum.mInviteSessionHandler;
951 const auto offerAnswer = InviteSession::getOfferAnswer(msg);
952
953 switch (toEvent(msg, offerAnswer.get()))
954 {
955 case On1xx:
956 case On1xxEarly:
957 case On1xxOffer:
958 // late, so ignore
959 break;
960
961 case On2xxOffer:
962 case On2xx:
963 case On2xxAnswer:
964 // retransmission
965 break;
966
967 case OnRedirect:
968 // too late
969 break;
970
971 // .slg. This doesn't really make sense (after a 2xx)
972 case OnGeneralFailure:
973 case On422Invite:
974 break;
975#if 0 // !jf! don't think this is right
976 {
977 InfoLog (<< "Failure: error response: " << msg.brief());
978 sendBye();
980 onFailureAspect(getHandle(), msg);
982 mDum.destroy(this);
983 break;
984 }
985#endif
986 case OnBye:
987 dispatchBye(msg);
988 break;
989
990 default:
991 // !kh!
992 // should not assert here for peer sent us garbage.
993 WarningLog (<< "Don't know what this is : " << msg);
994 break;
995 }
996
997}
998
999void
1000ClientInviteSession::dispatchEarlyWithOffer (const SipMessage& msg)
1001{
1002 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1003 std::unique_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1004
1005 switch (toEvent(msg, offerAnswer.get()))
1006 {
1007 case On1xx: // must be reliable
1008 handleProvisional(msg);
1009 sendPrackIfNeeded(msg);
1010 break;
1011
1012 case On2xx:
1013 case On2xxAnswer:
1014 sendAck();
1015 InfoLog (<< "Failure: no answer sent: " << msg.brief());
1016 sendBye();
1018 onFailureAspect(getHandle(), msg);
1020 break;
1021
1022 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionally not handled and should be treated as an INVITE failure
1023 case OnInviteFailure:
1024 case OnGeneralFailure:
1025 case On422Invite:
1026 case On487Invite:
1027 case On491Invite:
1028 InfoLog (<< "Failure: error response: " << msg.brief());
1030 onFailureAspect(getHandle(), msg);
1032 mDum.destroy(this);
1033 break;
1034
1035 case OnBye:
1036 dispatchBye(msg);
1037 break;
1038
1039 case OnUpdateOffer:
1040 {
1041 WarningLog (<< "Invalid UPDATE with offer received in early state with pending offer: " << msg.brief());
1042 auto response = std::make_shared<SipMessage>();
1043 mDialog.makeResponse(*response, msg, 500); // RFC3311 - section 5.2
1044 InfoLog (<< "Sending " << response->brief());
1045 send(response);
1046 break;
1047 }
1048
1049 case OnUpdate:
1050 {
1051 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback?
1052 auto response = std::make_shared<SipMessage>();
1053 mDialog.makeResponse(*response, msg, 200);
1054 send(response);
1055 break;
1056 }
1057
1058 default:
1059 // !kh!
1060 // should not assert here for peer sent us garbage.
1061 WarningLog (<< "Don't know what this is : " << msg);
1062 break;
1063 }
1064}
1065
1066void
1067ClientInviteSession::dispatchSentAnswer (const SipMessage& msg)
1068{
1069 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1070 std::unique_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1071
1072 switch (toEvent(msg, offerAnswer.get()))
1073 {
1074 case On200Prack:
1076 break;
1077
1078 case On2xx:
1080 sendAck();
1081 handleFinalResponse(msg);
1082 onConnectedAspect(getHandle(), msg);
1083 break;
1084
1085 case On2xxOffer:
1086 // RFC6337 section 3.1.2 recommends we ignore any illegal SDP here to be more interoperable
1087 WarningLog(<< "Ignoring illegal SDP offer in 2xx: " << msg.brief());
1089 sendAck();
1090 handleFinalResponse(msg);
1091 onConnectedAspect(getHandle(), msg);
1092 break;
1093
1094 case On2xxAnswer:
1095 case On1xxAnswer:
1096 sendAck();
1097 WarningLog(<< "Failure: illegal offer/answer: " << msg.brief());
1098 sendBye();
1100 onFailureAspect(getHandle(), msg);
1102 break;
1103
1104 case On1xxOffer:
1105 // RFC6337 section 3.1.2 recommends we ignore any illegal SDP here to be more interoperable
1106 WarningLog(<< "Ignoring illegal SDP offer in 1xx: " << msg.brief());
1107 // No break is intentional
1108 case On1xx:
1109 handleProvisional(msg);
1110 sendPrackIfNeeded(msg);
1111 break;
1112
1113 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionally not handled and should be treated as an INVITE failure
1114 case OnInviteFailure:
1115 case OnGeneralFailure:
1116 case On422Invite:
1117 case On487Invite:
1118 case On491Invite:
1119 InfoLog (<< "Failure: error response: " << msg.brief());
1121 onFailureAspect(getHandle(), msg);
1123 mDum.destroy(this);
1124 break;
1125
1126 case OnBye:
1127 dispatchBye(msg);
1128 break;
1129
1130 default:
1131 // !kh!
1132 // should not assert here for peer sent us garbage.
1133 WarningLog (<< "Don't know what this is : " << msg);
1134 break;
1135 }
1136}
1137
1138void
1139ClientInviteSession::dispatchQueuedUpdate (const SipMessage& msg)
1140{
1141 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1142 std::unique_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1143
1144 switch (toEvent(msg, offerAnswer.get()))
1145 {
1146 case On200Prack:
1148 {
1151
1154 }
1155 break;
1156
1157 case On2xx:
1159 {
1160 sendAck();
1161
1162 auto update = std::make_shared<SipMessage>();
1163 mDialog.makeRequest(*update, UPDATE);
1166 send(update);
1167 }
1168 handleFinalResponse(msg);
1169 onConnectedAspect(getHandle(), msg);
1170 break;
1171
1172 case On2xxOffer:
1173 // RFC6337 section 3.1.2 recommends we ignore any illegal SDP here to be more interoperable
1174 WarningLog(<< "Ignoring illegal SDP offer in 2xx: " << msg.brief());
1176 sendAck();
1177 handleFinalResponse(msg);
1178 onConnectedAspect(getHandle(), msg);
1179 break;
1180
1181 case On2xxAnswer:
1182 case On1xxAnswer:
1183 sendAck();
1184 WarningLog(<< "Failure: illegal offer/answer: " << msg.brief());
1185 sendBye();
1187 onFailureAspect(getHandle(), msg);
1189 break;
1190
1191 case On1xxOffer:
1192 // RFC6337 section 3.1.2 recommends we ignore any illegal SDP here to be more interoperable
1193 WarningLog(<< "Ignoring illegal SDP offer in 1xx: " << msg.brief());
1194 // No break is intentional
1195 case On1xx:
1196 handleProvisional(msg);
1197 sendPrackIfNeeded(msg);
1198 break;
1199
1200 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionally not handled and should be treated as an INVITE failure
1201 case OnInviteFailure:
1202 case OnGeneralFailure:
1203 case On422Invite:
1204 case On487Invite:
1205 case On491Invite:
1206 InfoLog (<< "Failure: error response: " << msg.brief());
1208 onFailureAspect(getHandle(), msg);
1210 mDum.destroy(this);
1211 break;
1212
1213 case OnBye:
1214 dispatchBye(msg);
1215 break;
1216
1217 default:
1218 // !kh!
1219 // should not assert here for peer sent us garbage.
1220 WarningLog (<< "Don't know what this is : " << msg);
1221 break;
1222 }
1223}
1224
1225
1226
1227void
1228ClientInviteSession::dispatchEarlyWithAnswer (const SipMessage& msg)
1229{
1230 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1231 std::unique_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg);
1232
1233 switch (toEvent(msg, offerAnswer.get()))
1234 {
1235 case On1xxOffer:
1236 // RFC6337 section 3.1.1 recommends we ignore any illegal SDP here to be more interoperable
1237 WarningLog(<< "Ignoring illegal SDP offer in 1xx: " << msg.brief());
1238 // No break is intentional
1239 case On1xx:
1240 handleProvisional(msg);
1241 sendPrackIfNeeded(msg);
1242 break;
1243
1244 case On2xx:
1246 sendAck();
1247 handleFinalResponse(msg);
1248 onConnectedAspect(getHandle(), msg);
1249 break;
1250
1251 case On2xxOffer:
1252 // RFC6337 section 3.1.1 recommends we ignore any illegal SDP here to be more interoperable
1253 WarningLog(<< "Ignoring illegal SDP offer in 2xx: " << msg.brief());
1255 sendAck();
1256 handleFinalResponse(msg);
1257 onConnectedAspect(getHandle(), msg);
1258 break;
1259
1260 case On2xxAnswer:
1261 sendAck();
1262 WarningLog(<< "Failure: illegal offer/answer: " << msg.brief());
1263 sendBye();
1265 onFailureAspect(getHandle(), msg);
1267 break;
1268
1269 case OnUpdateOffer:
1274 handler->onOffer(getSessionHandle(), msg, *offerAnswer);
1275 break;
1276
1277 case OnUpdate:
1278 {
1279 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback?
1280 auto response = std::make_shared<SipMessage>();
1281 mDialog.makeResponse(*response, msg, 200);
1282 send(response);
1283 break;
1284 }
1285
1286 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
1287 case OnInviteFailure:
1288 case OnGeneralFailure:
1289 case On422Invite:
1290 case On487Invite:
1291 case On491Invite:
1292 InfoLog (<< "Failure: error response: " << msg.brief());
1294 onFailureAspect(getHandle(), msg);
1296 mDum.destroy(this);
1297 break;
1298
1299 case OnBye:
1300 dispatchBye(msg);
1301 break;
1302
1303 case On200Prack:
1304 // We may have sent a PRACK with an offer (if provideOffer was called from onAnswer
1305 // from the first reliable provisional) - if so this will have SDP we need to call onAnswer
1306 if (offerAnswer && mProposedLocalOfferAnswer)
1307 {
1311 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
1312 }
1313 break;
1314
1315 default:
1316 // !kh!
1317 // should not assert here for peer sent us garbage.
1318 WarningLog (<< "Don't know what this is : " << msg);
1319 break;
1320 }
1321}
1322
1323void
1324ClientInviteSession::dispatchSentUpdateEarly (const SipMessage& msg)
1325{
1326 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1327 const auto offerAnswer = InviteSession::getOfferAnswer(msg);
1328
1329 switch (toEvent(msg, offerAnswer.get()))
1330 {
1331 case On200Update:
1336 handler->onAnswer(getSessionHandle(), msg, *offerAnswer);
1337 break;
1338
1339 case OnUpdateOffer:
1340 {
1341 auto response = std::make_shared<SipMessage>();
1342 mDialog.makeResponse(*response, msg, 491);
1343 send(response);
1344 }
1345 break;
1346
1347 case OnUpdate:
1348 {
1349 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback?
1350 auto response = std::make_shared<SipMessage>();
1351 mDialog.makeResponse(*response, msg, 200);
1352 send(response);
1353 break;
1354 }
1355
1356 case On491Update:
1358 start491Timer();
1359 break;
1360
1361 case On2xx:
1363 sendAck();
1364 break;
1365
1366 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets
1367 // here then it's because the redirect was intentionally
1368 // not handled and should be treated as an INVITE failure
1369 case OnInviteFailure:
1370 case OnGeneralFailure:
1371 case On422Invite:
1372 case On487Invite:
1373 InfoLog (<< "Failure: error response: " << msg.brief());
1375 onFailureAspect(getHandle(), msg);
1377 mDum.destroy(this);
1378 break;
1379
1380 case On200Prack:
1381 break;
1382
1383 default:
1384 WarningLog (<< "Don't know what this is : " << msg);
1385 break;
1386 }
1387}
1388
1389void
1390ClientInviteSession::dispatchSentUpdateEarlyGlare (const SipMessage& msg)
1391{
1392 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1393 const auto offerAnswer = InviteSession::getOfferAnswer(msg);
1394
1395 switch (toEvent(msg, offerAnswer.get()))
1396 {
1397 case OnUpdateOffer:
1398 handler->onOfferRejected(getSessionHandle(), &msg);
1399 //will cause transition to UAC_ReceivedUpdateEarly
1400 dispatchEarlyWithAnswer(msg);
1401 break;
1402
1403 case On2xx:
1404 //transition to connected state machine
1406 sendAck();
1407 break;
1410 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets
1411 // here then it's because the redirect was intentionally
1412 // not handled and should be treated as an INVITE failure
1413 case OnInviteFailure:
1414 case OnGeneralFailure:
1415 case On422Invite:
1416 case On487Invite:
1417 InfoLog (<< "Failure: error response: " << msg.brief());
1419 onFailureAspect(getHandle(), msg);
1421 mDum.destroy(this);
1422 break;
1423
1424 default:
1425 WarningLog (<< "Don't know what this is : " << msg);
1426 break;
1427 }
1428}
1429
1430void
1431ClientInviteSession::dispatchReceivedUpdateEarly(const SipMessage& msg)
1432{
1433 const auto offerAnswer = InviteSession::getOfferAnswer(msg);
1434
1435 switch (toEvent(msg, offerAnswer.get()))
1436 {
1437 case OnUpdate:
1438 case OnUpdateOffer:
1439 // If we receive an UPDATE before we have generated a final response to a previous UPDATE on the
1440 // same dialog, then we MUST return a 500 response with a Retry-After header (random duration 0-10 seconds)
1441 {
1442 auto u500 = std::make_shared<SipMessage>();
1443 mDialog.makeResponse(*u500, msg, 500);
1444 u500->header(h_RetryAfter).value() = Random::getRandom() % 10;
1445 send(u500);
1446 }
1447 break;
1448
1449 default:
1450 WarningLog (<< "Don't know what this is : " << msg);
1451 break;
1452 }
1453 WarningLog (<< "Ignoring message received in ReceivedUpdateEarly: " << msg);
1454}
1455
1456void
1457ClientInviteSession::dispatchCancelled (const SipMessage& msg)
1458{
1459 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1460 const auto offerAnswer = InviteSession::getOfferAnswer(msg);
1461
1462 switch (toEvent(msg, offerAnswer.get()))
1463 {
1464 case OnGeneralFailure:
1465 case OnCancelFailure:
1466 case On487Invite:
1467 case OnRedirect:
1468 case On422Invite:
1469 case On491Invite:
1470 case OnInviteFailure:
1473 mDum.destroy(this);
1474 break;
1475
1476 case On2xx:
1477 case On2xxOffer:
1478 case On2xxAnswer:
1479 {
1480 // this is the 2xx crossing the CANCEL case
1481 sendAck();
1482 sendBye();
1485 mCancelledTimerSeq++;
1486 break;
1487 }
1488
1489 case OnBye:
1490 dispatchBye(msg);
1491 break;
1492
1493 default:
1494 if(msg.isRequest())
1495 {
1496 // We have canceled - reject any new requests
1497 std::shared_ptr<SipMessage> rsp(new SipMessage);
1498 mDialog.makeResponse(*rsp, msg, 481);
1499 send(rsp);
1500 }
1501 break;
1502 }
1503}
1504
1505//true if 180rel should be ignored. Saves rseq as a side effect.
1506bool
1507ClientInviteSession::isBadRseq(const SipMessage& msg)
1508{
1509 int code = msg.isResponse() ? msg.header(h_StatusLine).statusCode() : 0;
1510 if (msg.method() == INVITE && code > 100 && code < 200)
1511 {
1512 if (msg.exists(h_RSeq))
1513 {
1514 // store state about the provisional if reliable, so we can detect retransmissions
1515 unsigned int rseq = (unsigned int) msg.header(h_RSeq).value();
1516 unsigned int lastRseq = (unsigned int) mRelRespInfo.rSequence();
1517
1518 if (rseq == lastRseq)
1519 {
1520 DebugLog(<< "Discarding reliable 1xx retranmission with rseq " << rseq);
1521 return true;
1522 }
1523 else if (lastRseq != 0 && rseq > lastRseq + 1)
1524 {
1525 DebugLog(<< "Discarding out of order reliable 1xx with rseq " << rseq);
1526 return true;
1527 }
1528 mRelRespInfo.rSequence() = rseq;
1529 mRelRespInfo.cSequence() = msg.header(h_CSeq).sequence();
1530 mRelRespInfo.method() = msg.header(h_CSeq).method();
1531 }
1532 }
1533 return false;
1534}
1535
1536void
1537ClientInviteSession::onConnectedAspect(ClientInviteSessionHandle c, const SipMessage& msg)
1538{
1539 if (mDum.mDialogEventStateManager)
1540 {
1541 mDum.mDialogEventStateManager->onConfirmed(mDialog, getSessionHandle());
1542 }
1543 mDum.mInviteSessionHandler->onConnected(c, msg);
1544}
1545
1546void
1547ClientInviteSession::onProvisionalAspect(ClientInviteSessionHandle c, const SipMessage& msg)
1548{
1549 if (mDum.mDialogEventStateManager)
1550 {
1551 mDum.mDialogEventStateManager->onEarly(mDialog, getSessionHandle());
1552 }
1553 mDum.mInviteSessionHandler->onProvisional(c, msg);
1554}
1555
1556void
1557ClientInviteSession::onFailureAspect(ClientInviteSessionHandle c, const SipMessage& msg)
1558{
1559 if (mDum.mDialogEventStateManager)
1560 {
1562 if (msg.isResponse())
1563 {
1564 if (msg.header(h_StatusLine).responseCode() == 408)
1565 {
1567 }
1568 else if (msg.header(h_StatusLine).responseCode() / 100 == 5)
1569 {
1571 }
1572 }
1573 mDum.mDialogEventStateManager->onTerminated(mDialog, msg, reason);
1574 }
1575 mDum.mInviteSessionHandler->onFailure(c, msg);
1576}
1577
1578/* ====================================================================
1579 * The Vovida Software License, Version 1.0
1580 *
1581 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1582 *
1583 * Redistribution and use in source and binary forms, with or without
1584 * modification, are permitted provided that the following conditions
1585 * are met:
1586 *
1587 * 1. Redistributions of source code must retain the above copyright
1588 * notice, this list of conditions and the following disclaimer.
1589 *
1590 * 2. Redistributions in binary form must reproduce the above copyright
1591 * notice, this list of conditions and the following disclaimer in
1592 * the documentation and/or other materials provided with the
1593
1594 * distribution.
1595 *
1596 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1597 * and "Vovida Open Communication Application Library (VOCAL)" must
1598 * not be used to endorse or promote products derived from this
1599 * software without prior written permission. For written
1600 * permission, please contact vocal@vovida.org.
1601 *
1602 * 4. Products derived from this software may not be called "VOCAL", nor
1603 * may "VOCAL" appear in their name, without prior written
1604 * permission of Vovida Networks, Inc.
1605 *
1606 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1607 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1608 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1609 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1610 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1611 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1612 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1613 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1614 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1615 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1616 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1617 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1618 * DAMAGE.
1619 *
1620 * ====================================================================
1621 *
1622 * This software consists of voluntary contributions made by Vovida
1623 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1624 * Inc. For more information on Vovida Networks, Inc., please see
1625 * <http://www.vovida.org/>.
1626 *
1627 */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define resip_assert(x)
This file needs to work for both C and C++ code.
std::shared_ptr< SipMessage > getLastRequest() const noexcept
The abstract base-class for all exceptions thrown by resip code.
BaseUsageHandle getBaseHandle() const
Definition BaseUsage.cxx:36
DialogUsageManager & mDum
Definition BaseUsage.hxx:43
ClientInviteSession(DialogUsageManager &dum, Dialog &dialog, std::shared_ptr< SipMessage > request, const Contents *initialOffer, DialogUsageManager::EncryptionLevel level, ServerSubscriptionHandle serverSub=ServerSubscriptionHandle::NotValid())
ClientInviteSessionHandle getHandle()
const Contents & getEarlyMedia() const
void reject(int statusCode, WarningCategory *warning=nullptr) override
Rejects an offer at the SIP level.
void provideAnswer(const Contents &answer) override
Similar to provideOffer - called to set the answer to be signaled to the peer.
void provideOffer(const Contents &offer) override
Called to set the offer that will be used in the next message that sends an offer.
Base class for all SIP body types.
Definition Contents.hxx:51
virtual Contents * clone() const =0
returns a copy of a Contents object
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
BaseCreator * getCreator() const noexcept
std::shared_ptr< UserProfile > getUserProfile() const
virtual void send(std::shared_ptr< SipMessage > msg)
dcm! – kill typedef std::list<DialogId> DialogIdSet;
Definition Dialog.hxx:29
void makeRequest(SipMessage &request, MethodTypes method, bool incrementCSeq=true)
Definition Dialog.cxx:1033
void makeResponse(SipMessage &response, const SipMessage &request, int responseCode)
Definition Dialog.cxx:1108
static void setOutgoingEncryptionLevel(SipMessage &message, DialogUsageManager::EncryptionLevel level)
Definition DumHelper.cxx:11
Type type() const
unsigned int seq() const
bool isValid() const
Definition Handle.hxx:25
virtual void onOfferRejected(InviteSessionHandle, const SipMessage *msg)=0
called if an offer in a UPDATE or re-INVITE was rejected - not real useful.
virtual void terminate(ClientInviteSessionHandle h)
called when an early dialog decides it wants to terminate the dialog.
virtual void onForkDestroyed(ClientInviteSessionHandle)=0
called when a fork that was created through a 1xx never receives a 2xx because another fork answered ...
virtual void onAnswer(InviteSessionHandle, const SipMessage &msg, const SdpContents &)=0
called when an answer is received - has nothing to do with user answering the call
virtual void onEarlyMedia(ClientInviteSessionHandle, const SipMessage &, const SdpContents &)=0
called when an in-dialog provisional response is received that contains a body
virtual void onProvisional(ClientInviteSessionHandle, const SipMessage &)=0
called when dialog enters the Early state - typically after getting 18x
virtual void onRedirected(ClientInviteSessionHandle, const SipMessage &msg)=0
called when a 3xx with valid targets is encountered in an early dialog This is different then getti...
virtual void onStaleCallTimeout(ClientInviteSessionHandle h)
UAC gets no final response within the stale call timeout (default is 3 minutes).
virtual void onTerminated(InviteSessionHandle, InviteSessionHandler::TerminatedReason reason, const SipMessage *related=0)=0
virtual void onOffer(InviteSessionHandle, const SipMessage &msg, const SdpContents &)=0
called when an offer is received - must send an answer soon after this
virtual void onNewSession(ClientInviteSessionHandle, InviteSession::OfferAnswerType oat, const SipMessage &msg)=0
called when an initial INVITE or the intial response to an outoing invite
TerminatedReason
called when an dialog enters the terminated state - this can happen after getting a BYE,...
virtual void onFailure(ClientInviteSessionHandle, const SipMessage &msg)=0
Received a failure response from UAS.
virtual void onConnected(ClientInviteSessionHandle, const SipMessage &msg)=0
called when a dialog initiated as a UAC enters the connected state
Base class for class ClientInviteSession and class ServerInviteSession.
std::unique_ptr< Contents > getOfferAnswer(const SipMessage &msg)
void transition(State target)
void setCurrentLocalOfferAnswer(const SipMessage &msg)
std::shared_ptr< SipMessage > sendBye()
virtual void reject(int statusCode, WarningCategory *warning=0)
Rejects an offer at the SIP level.
std::unique_ptr< Contents > mProposedRemoteOfferAnswer
std::unique_ptr< Contents > mProposedLocalOfferAnswer
std::unique_ptr< Contents > mCurrentLocalOfferAnswer
std::shared_ptr< SipMessage > mLastRemoteSessionModification
std::shared_ptr< SipMessage > mLastLocalSessionModification
virtual void end() override
static std::unique_ptr< Contents > makeOfferAnswer(const Contents &offerAnswer)
DialogUsageManager::EncryptionLevel mProposedEncryptionLevel
void storePeerCapabilities(const SipMessage &msg)
InviteSessionHandle getSessionHandle()
virtual void provideAnswer(const Contents &answer)
Similar to provideOffer - called to set the answer to be signaled to the peer.
void handleSessionTimerResponse(const SipMessage &msg)
void dispatchMessage(const SipMessage &msg)
static void setOfferAnswer(SipMessage &msg, const Contents &offerAnswer, const Contents *alternative=0)
std::unique_ptr< Contents > mCurrentRemoteOfferAnswer
void dispatchInfo(const SipMessage &msg)
void dispatch(const SipMessage &msg) override
Event toEvent(const SipMessage &msg, const Contents *offeranswer)
void dispatchBye(const SipMessage &msg)
DialogUsageManager::EncryptionLevel getEncryptionLevel(const SipMessage &msg)
bool isReliable(const SipMessage &msg) const
virtual void provideOffer(const Contents &offer)
Called to set the offer that will be used in the next message that sends an offer.
static Data toData(State state)
std::shared_ptr< SipMessage > sendAck(const Contents *answer=0)
ParserContainer< Token > mUserEndReasons
DialogUsageManager::EncryptionLevel mCurrentEncryptionLevel
virtual Brief brief() const
return a facet for brief encoding of message
Definition Message.cxx:16
Container class for ParserCategory, used by SipMessage to represent multi-valued headers (Contact,...
unsigned int & rSequence()
unsigned int & cSequence()
MethodTypes & method()
static int getRandom()
Returns a postive integer (31 bits) of randomness.
Definition Random.cxx:261
MethodTypes & method()
void end(TerminateReason reason, const Contents *document=0, int retryAfter=0)
std::shared_ptr< SipMessage > update(const Contents *document)
void send(std::shared_ptr< SipMessage > msg) override
SIP body type for holding SipFrag contents (MIME content-type message/sipfrag).
Definition SipFrag.hxx:22
SipMessage & message()
Definition SipFrag.cxx:82
Represents a SIP message.
bool isRequest() const
Returns true if message is a request, false otherwise.
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
bool isResponse() const
Returns true if message is a response, false otherwise.
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
resip::MethodTypes method() const
returns the method type of the message
static unsigned long TH
Definition Timer.hxx:122
Represents the "warning-value" element in the RFC 3261 grammar.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
Definition Headers.cxx:348
Handle< ClientInviteSession > ClientInviteSessionHandle
Definition Handles.hxx:36
RequestLineType h_RequestLine
Definition Headers.cxx:347
H_CallId h_CallId
Definition Headers.cxx:266