[reSIProcate] Target refresh in the wrong invitesession state causes abort
Hi,
We have experienced a crash (abort) in our resiprocate-based B2BUA, in
this scenario:
we use rtpproxy, but when it turns out to be unnecessary, we drop it
using a pair of reinvites:
1, SDP-less invite to C
2, OK from C with SDP offer
3, pass on the SDP offer in invite to A,
4, OK from A with SDP answer
5, pass on the SDP answer in ACK to C,
6, ACK to A
we also have an upstream SBC, which have multiple instances with
fail-over capabilities. When one of the instances fail, the fail-over
sends "target refresh" INVITEs to our B2BUA. When these two happen
simultaneously (the reinvite being between step 2 and 5), the B2BUA will
crash in resiprocate:
3 0x00007f7880eb4e42 in __assert_fail () from
/lib/x86_64-linux-gnu/libc.so.6
#4 0x00000000007eb9e6 in resip::InviteSession::dispatchOthers
(this=0x7f784da84a50, msg=
...) at InviteSession.cxx:2039
#5 0x00000000007eaee8 in
resip::InviteSession::dispatchSentReinviteAnswered (
this=0x7f784da84a50, msg=...) at InviteSession.cxx:1892
#6 0x00000000007e7209 in resip::InviteSession::dispatch
(this=0x7f784da84a50, msg=...)
at InviteSession.cxx:1160
#7 0x000000000082fedd in resip::ClientInviteSession::dispatch
(this=0x7f784da84a50,
msg=...) at ClientInviteSession.cxx:450
#8 0x00000000007a5426 in resip::Dialog::dispatch (this=0x7f784cdf4520,
msg=...)
at Dialog.cxx:427
#9 0x00000000007b56e7 in resip::DialogSet::dispatch
(this=0x7f783f04e200, msg=...)
at DialogSet.cxx:895
#10 0x00000000007c7fe6 in resip::DialogUsageManager::processRequest (
this=0x7f7882f16fd8, request=...) at DialogUsageManager.cxx:1985
#11 0x00000000007c549f in resip::DialogUsageManager::incomingProcess (
this=0x7f7882f16fd8, msg=...) at DialogUsageManager.cxx:1622
#12 0x00000000007c4595 in resip::DialogUsageManager::internalProcess (
this=0x7f7882f16fd8, msg=...) at DialogUsageManager.cxx:1446
#13 0x00000000007c57cf in resip::DialogUsageManager::process
(this=0x7f7882f16fd8,
mutex=0x0) at DialogUsageManager.cxx:1656
(the line numbers may vary, this trace is from an older resiprocate, but
the crash is reproducible with the latest, too).
We have a proposed patch, but we'd like to have a discussion about it,
so I post it here instead of creating the pull request right away:
Index: InviteSession.cxx
===================================================================
--- InviteSession.cxx (revision 33950)
+++ InviteSession.cxx (working copy)
@@ -299,6 +299,29 @@
}
bool
+InviteSession::isUpdating() const
+{
+ switch (mState)
+ {
+ case SentUpdate:
+ case SentUpdateGlare:
+ case SentReinvite:
+ case SentReinviteGlare:
+ case SentReinviteNoOffer:
+ case SentReinviteAnswered:
+ case SentReinviteNoOfferGlare:
+ case ReceivedUpdate:
+ case ReceivedReinvite:
+ case ReceivedReinviteNoOffer:
+ case ReceivedReinviteSentOffer:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool
InviteSession::isEarly() const
{
switch (mState)
Index: InviteSession.hxx
===================================================================
--- InviteSession.hxx (revision 33950)
+++ InviteSession.hxx (working copy)
@@ -152,6 +152,7 @@
const SdpContents& getProposedRemoteSdp() const;
bool isConnected() const;
+ bool isUpdating() const;
bool isTerminated() const;
bool isEarly() const; // UAC Early states
bool isAccepted() const; // UAS States after accept is called
Index: Dialog.cxx
===================================================================
--- Dialog.cxx (revision 33950)
+++ Dialog.cxx (working copy)
@@ -426,6 +426,14 @@
}
}
+ if(msg.isRequest() && INVITE == msg.header(h_CSeq).method() &&
+ mInviteSession != 0 && mInviteSession->isUpdating())
+ {
+ SipMessage failure;
+ makeResponse(failure, msg, 491);
+ mDum.sendResponse(failure);
+ return;
+ }
handleTargetRefresh(msg);
if (msg.isRequest())
{
please comment
br
Szo