< Previous by Date Date Index Next by Date >
< Previous in Thread Thread Index Next in Thread >

Re: [reSIProcate] Target refresh in the wrong invitesession state causes abort


Hi Robert,

It appears there are actually more states we don't handle this properly in.  I took a different approach and put in "catch all" like handling for inbound INVITEs and UPDATEs in dispatchOthers.  If an INVITE or UPDATE makes it here, we will respond with a 491.

Can you try out the following code and see if it works for you?

void
InviteSession::dispatchOthers(const SipMessage& msg)
{
   // handle OnGeneralFailure
   // handle OnRedirect

   switch (msg.header(h_CSeq).method())
   {
      case INVITE:
      case UPDATE:
         if (msg.isRequest())
         {
            SharedPtr<SipMessage> response(new SipMessage);
            mDialog.makeResponse(*response, msg, 491);
            send(response);
            break;
         }
      case PRACK:
         dispatchPrack(msg);
         break;
      case CANCEL:
         dispatchCancel(msg);
         break;
      case BYE:
         dispatchBye(msg);
         break;
      case INFO:
         dispatchInfo(msg);
         break;
      case MESSAGE:
         dispatchMessage(msg);
         break;
      case ACK:
         // Ignore duplicate ACKs from 2xx reTransmissions
         break;
      default:
         // handled in Dialog
         WarningLog (<< "DUM delivered a "
                     << msg.header(h_CSeq).unknownMethodName()
                     << " to the InviteSession in state: " << toData(mState)
                     << endl
                     << msg);
         resip_assert(0);
         break;
   }
}

Best Regards,
Scott

On Thu, Apr 14, 2016 at 9:18 AM, Szokovacs Robert <robert.szokovacs@xxxxxxxxxxx> wrote:
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
_______________________________________________
resiprocate-devel mailing list
resiprocate-devel@xxxxxxxxxxxxxxx
https://list.resiprocate.org/mailman/listinfo/resiprocate-devel