Skip to content

Commit

Permalink
[b2b_entities] Proper handling of overlaping transactions
Browse files Browse the repository at this point in the history
As per RFC3261, Section 14.2 :

   A UAS that receives a second INVITE before it sends the final
   response to a first INVITE with a lower CSeq sequence number on the
   same dialog MUST return a 500 (Server Internal Error) response to the
   second INVITE and MUST include a Retry-After header field with a
   randomly chosen value of between 0 and 10 seconds.

   A UAS that receives an INVITE on a dialog while an INVITE it had sent
   on that dialog is in progress MUST return a 491 (Request Pending)
   response to the received INVITE.

Changes:
* 491 is now generated when receiving a request while already having an outbound one - the old code was generating 491 upon receiving a request while having another INCOMING one :-/
* generate the 500 reply when receiving a new request while handing another incoming one.

(cherry picked from commit c4032f9)
  • Loading branch information
bogdan-iancu committed Sep 14, 2023
1 parent 193e65d commit e4236b5
Showing 1 changed file with 71 additions and 43 deletions.
114 changes: 71 additions & 43 deletions modules/b2b_entities/dlg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1169,57 +1169,85 @@ int b2b_prescript_f(struct sip_msg *msg, void *uparam)
tmb.t_setkr(REQ_FWDED);
}

if(dlg->uac_tran && dlg->uac_tran!=T_UNDEFINED)
{
/* We have an UAC ongoing transaction in the dialog
* -> reject with 491 Request Pending */
if (method_value != METHOD_BYE) {
/* send reply */
LM_DBG("Received a request while having an ongoing "
"outbound/UAC one\n");
str text = str_init("Request Pending");
if(tmb.t_reply_with_body( tm_tran, 491,
&text, 0, 0, &to_tag) < 0)
{
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [491] and unreffed the cell %p\n",
tm_tran);
} else {
LM_DBG("Received BYE while having an ongoing "
"outbound/UAC transaction\n");
str text_ok = str_init("OK");
if(tmb.t_reply_with_body( tm_tran, 200,
&text_ok, 0, 0, &to_tag) < 0)
{
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [200] and unreffed the cell %p\n",
tm_tran);
tmb.unref_cell(tm_tran);

str text_term = str_init("Request Terminated");
if(tmb.t_reply_with_body(dlg->uas_tran, 487,
&text_term, 0, 0, &to_tag) < 0)
{
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [487] and unreffed the cell %p\n",
dlg->uas_tran);

tmb.unref_cell(dlg->uas_tran);
dlg->uas_tran = NULL;

b2b_cb_flags |= B2B_NOTIFY_FL_TERM_BYE;
goto run_cb;
}
tmb.unref_cell(tm_tran); /* for t_newtran() */
B2BE_LOCK_RELEASE(table, hash_index);
return SCB_DROP_MSG;
} else
if(dlg->uas_tran && dlg->uas_tran!=T_UNDEFINED)
{
if(dlg->uas_tran->uas.request)
/* there is another transaction for which no reply
* was sent out */
/* We have another UAS ongoing transaction on the dialog
* -> reject with 500, "Overlapping Requests" */
#define RETRY_AFTER_HDR "Retry-After: "
#define RETRY_AFTER_HDR_LEN (sizeof("Retry-After: ")-1)
char ra_s[RETRY_AFTER_HDR_LEN + 3 + CRLF_LEN];
str ra = {ra_s, 0};
str text = str_init("Overlapping Requests");
LM_DBG("Received another request when the previous "
"one was in process\n");
memcpy( ra.s+ra.len, RETRY_AFTER_HDR, RETRY_AFTER_HDR_LEN);
ra.len += RETRY_AFTER_HDR_LEN;
/* the retry value is between 0 and 10 */
ra.len += btostr(ra.s+ra.len, (unsigned char)(rand()%10) );
memcpy( ra.s+ra.len, CRLF, CRLF_LEN);
ra.len += CRLF_LEN;
/* send reply */
if(tmb.t_reply_with_body( tm_tran, 500,
&text, 0, &ra, &to_tag) < 0)
{
if (method_value != METHOD_BYE) {
/* send reply */
LM_DBG("Received another request when the previous "
"one was in process\n");
str text = str_init("Request Pending");
if(tmb.t_reply_with_body( tm_tran, 491,
&text, 0, 0, &to_tag) < 0)
{
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [491] and unreffed the cell %p\n",
tm_tran);
} else {
LM_DBG("Received BYE while another request "
"was in process\n");
str text_ok = str_init("OK");
if(tmb.t_reply_with_body( tm_tran, 200,
&text_ok, 0, 0, &to_tag) < 0)
{
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [200] and unreffed the cell %p\n",
tm_tran);
tmb.unref_cell(tm_tran);

str text_term = str_init("Request Terminated");
if(tmb.t_reply_with_body(dlg->uas_tran, 487,
&text_term, 0, 0, &to_tag) < 0)
{
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [487] and unreffed the cell %p\n",
dlg->uas_tran);

tmb.unref_cell(dlg->uas_tran);
dlg->uas_tran = NULL;

b2b_cb_flags |= B2B_NOTIFY_FL_TERM_BYE;
goto run_cb;
}
LM_ERR("failed to send reply with tm\n");
}
LM_DBG("Sent reply [500] and unreffed the cell %p\n",
tm_tran);
tmb.unref_cell(tm_tran); /* for t_newtran() */
B2BE_LOCK_RELEASE(table, hash_index);
return SCB_DROP_MSG;
}

/* the new request is accepted for handling */
dlg->uas_tran = tm_tran;
LM_DBG("Saved uas_tran=[%p] for dlg[%p]\n", tm_tran, dlg);
}
Expand Down

0 comments on commit e4236b5

Please sign in to comment.