Skip to content

Commit b2e3270

Browse files
committed
dialog: fix multi-PRACK CSeq handling and uac-auth ACK CSeq regression
* fix CSeq regression on the outbound leg, prioritize .last_gen_cseq * manual PRACK: fix matching for current leg (multi-180 scenario) * manual PRACK: add logic for early leg creation during onreply_route. This allows the leg to be correctly matched and have its CSeq set. * small fix: avoid overwriting .last_gen_cseq with smaller values
1 parent 5d5fbed commit b2e3270

4 files changed

Lines changed: 66 additions & 10 deletions

File tree

modules/dialog/dialog.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,11 +2608,16 @@ static int dlg_send_sequential(struct sip_msg* msg, str *method, int leg,
26082608
return rc;
26092609
}
26102610

2611-
if (is_prack && msg && msg->first_line.type == SIP_REPLY)
2611+
if (is_prack && msg && msg->first_line.type == SIP_REPLY) {
2612+
if (leg != DLG_CALLER_LEG) {
2613+
rc = dlg_ensure_reply_leg(dlg, msg);
2614+
if (rc > 0)
2615+
leg = rc;
2616+
}
26122617
rc = send_prack_indialog_request(dlg, msg,
2613-
(leg == DLG_CALLER_LEG ? leg : callee_idx(dlg)), body, ct,
2618+
leg, body, ct,
26142619
(req_headers.s ? &req_headers : headers), NULL, NULL, NULL);
2615-
else
2620+
} else
26162621
rc = send_indialog_request(dlg, method,
26172622
(leg == DLG_CALLER_LEG ? leg : callee_idx(dlg)),
26182623
body, ct, (req_headers.s ? &req_headers : headers),

modules/dialog/dlg_handlers.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,15 @@ static inline void push_reply_in_dialog(struct sip_msg *req, struct sip_msg *rpl
700700
if (str2int( &(get_cseq(rpl)->number), &cseq_no) < 0) {
701701
LM_ERR("Failed to convert cseq to integer \n");
702702
} else {
703-
LM_DBG("last_gen_cseq = cseq_no [%d] for method id [%d]\n", cseq_no, get_cseq(rpl)->method_id);
704-
dlg->legs[dlg->legs_no[DLG_LEG_200OK]].last_gen_cseq = cseq_no;
703+
if (dlg->legs[dlg->legs_no[DLG_LEG_200OK]].last_gen_cseq < cseq_no) {
704+
LM_DBG("updating last_gen_cseq to reply cseq [%d] for method id [%d]\n",
705+
cseq_no, get_cseq(rpl)->method_id);
706+
dlg->legs[dlg->legs_no[DLG_LEG_200OK]].last_gen_cseq = cseq_no;
707+
} else {
708+
LM_DBG("keeping higher last_gen_cseq [%d] over reply cseq [%d] for method id [%d]\n",
709+
dlg->legs[dlg->legs_no[DLG_LEG_200OK]].last_gen_cseq,
710+
cseq_no, get_cseq(rpl)->method_id);
711+
}
705712
}
706713
}
707714

@@ -726,6 +733,21 @@ static inline void push_reply_in_dialog(struct sip_msg *req, struct sip_msg *rpl
726733
dlg_unlock_dlg(dlg);
727734
}
728735

736+
/* Manual PRACK may be generated from onreply_route before the dialog reply
737+
* callback has materialized the current early-dialog leg. Push the reply into
738+
* dialog state first, then return the matched/newly-created callee leg. */
739+
int dlg_ensure_reply_leg(struct dlg_cell *dlg, struct sip_msg *rpl)
740+
{
741+
long leg_idx = -1;
742+
str empty = {0, 0};
743+
744+
if (!dlg || !rpl || rpl == FAKED_REPLY)
745+
return -1;
746+
747+
push_reply_in_dialog(NULL, rpl, NULL, dlg, &empty, &empty, &leg_idx);
748+
return (int)leg_idx;
749+
}
750+
729751
static void _dlg_setup_reinvite_callbacks(struct cell *t, struct sip_msg *req,
730752
struct dlg_cell *dlg);
731753

@@ -2415,13 +2437,13 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
24152437
LM_DBG("dlg_leg_get_cseq(dlg, [%d], req)\n", src_leg);
24162438
update_val = dlg_leg_get_cseq(dlg, src_leg, req);
24172439
if (update_val == 0) {
2418-
if (str2int(&dlg->legs[src_leg].inv_cseq, &update_val) == 0) {
2440+
if (dlg->legs[dst_leg].last_gen_cseq) {
2441+
LM_DBG("using last generated cseq [%d] for ACK on leg [%d]\n",
2442+
dlg->legs[dst_leg].last_gen_cseq, dst_leg);
2443+
update_val = dlg->legs[dst_leg].last_gen_cseq;
2444+
} else if (str2int(&dlg->legs[src_leg].inv_cseq, &update_val) == 0) {
24192445
LM_DBG("using INVITE cseq [%d] for ACK on leg [%d]\n",
24202446
update_val, src_leg);
2421-
} else if (dlg->legs[dst_leg].last_gen_cseq) {
2422-
LM_DBG("dlg->legs[%d].last_gen_cseq=[%d]\n",
2423-
dst_leg, dlg->legs[dst_leg].last_gen_cseq);
2424-
update_val = dlg->legs[dst_leg].last_gen_cseq;
24252447
} else {
24262448
update_val = 0;
24272449
}

modules/dialog/dlg_handlers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ int send_prack_indialog_request(struct dlg_cell *dlg, struct sip_msg *rpl,
143143
void *param, indialog_release_f release);
144144
int dlg_prepare_prack_headers(struct sip_msg *msg, str *headers, str *out,
145145
int enforce_onreply_route);
146+
int dlg_ensure_reply_leg(struct dlg_cell *dlg, struct sip_msg *rpl);
146147

147148
void unreference_dialog(void *dialog);
148149

modules/dialog/dlg_req_within.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,32 @@ static struct dlg_auto_prack_ctx *dlg_build_auto_prack_ctx(struct sip_msg *rpl)
229229
return ctx;
230230
}
231231

232+
/* Resolve the PRACK leg by matching the reply To-tag,
233+
* use the current primary callee as a default. */
234+
static int dlg_get_prack_leg(struct dlg_cell *dlg, struct sip_msg *rpl, int dst_leg)
235+
{
236+
str *tag;
237+
int i;
238+
239+
if (!rpl)
240+
return dst_leg;
241+
if ((!rpl->to && parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)
242+
return dst_leg;
243+
244+
tag = &get_to(rpl)->tag_value;
245+
if (!tag->len)
246+
return dst_leg;
247+
248+
for (i = DLG_FIRST_CALLEE_LEG; i < dlg->legs_no[DLG_LEGS_USED]; i++) {
249+
if (dlg->legs[i].tag.len != tag->len)
250+
continue;
251+
if (strncmp(dlg->legs[i].tag.s, tag->s, tag->len) == 0)
252+
return i;
253+
}
254+
255+
return dst_leg;
256+
}
257+
232258
int free_tm_dlg(dlg_t *td)
233259
{
234260
if(td)
@@ -1406,6 +1432,8 @@ int send_prack_indialog_request(struct dlg_cell *dlg, struct sip_msg *rpl,
14061432
dlg_t *dialog_info = NULL;
14071433
int result;
14081434

1435+
dstleg = dlg_get_prack_leg(dlg, rpl, dstleg);
1436+
14091437
if (!dlg_get_leg_hdrs(dlg, other_leg(dlg, dstleg), dstleg, ct, hdrs,
14101438
&extra_headers)) {
14111439
LM_ERR("could not build extra headers!\n");

0 commit comments

Comments
 (0)