diff --git a/modules/dialog/dialog.c b/modules/dialog/dialog.c index ff2ecedcadc..0cb865bd3e5 100644 --- a/modules/dialog/dialog.c +++ b/modules/dialog/dialog.c @@ -159,6 +159,7 @@ static int dlg_on_answer(struct sip_msg* msg, void *route_id); static int dlg_on_hangup(struct sip_msg* msg, void *route_id); static int dlg_send_sequential(struct sip_msg* msg, str *method, int leg, str *body, str *ct, str *headers); +static int dlg_inc_cseq(struct sip_msg *msg, str *tag, int *_count); /* item/pseudo-variables functions */ @@ -282,6 +283,10 @@ static const cmd_export_t cmds[]={ {CMD_PARAM_STR|CMD_PARAM_OPT, 0, 0}, {CMD_PARAM_STR|CMD_PARAM_OPT, 0, 0}, {0,0,0}}, ALL_ROUTES}, + {"dlg_inc_cseq", (cmd_function)dlg_inc_cseq, { + {CMD_PARAM_STR|CMD_PARAM_OPT, 0, 0}, + {CMD_PARAM_INT|CMD_PARAM_OPT, 0, 0}, {0,0,0}}, + REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE}, {"load_dlg", (cmd_function)load_dlg, {{0,0,0}}, 0}, {0,0,{{0,0,0}},0} }; @@ -2566,3 +2571,55 @@ static int dlg_send_sequential(struct sip_msg* msg, str *method, int leg, body, ct, headers, NULL, NULL) == 0?1:-1; } + +static int dlg_inc_cseq(struct sip_msg *msg, str *tag, int *_count) +{ + struct dlg_cell *dlg; + int count = (_count?*_count:1); + int leg, ret = -1; + str cseq; + unsigned int loc_seq; + + if ( (dlg=get_current_dialog())==NULL ) { + LM_DBG("no current dialog found\n"); + return -2; + } + + if (!tag) { + if ((!msg->to && parse_headers(msg, HDR_TO_F, 0) < 0) || !msg->to) { + LM_ERR("inexisting or invalid to header!\n"); + return -1; + } + tag = &get_to(msg)->tag_value; + } + dlg_lock_dlg(dlg); + for (leg = DLG_FIRST_CALLEE_LEG ; leg < dlg->legs_no[DLG_LEGS_USED]; leg++) { + if (str_match(tag, &dlg->legs[leg].tag)) + break; + } + if (leg == dlg->legs_no[DLG_LEGS_USED]) { + LM_ERR("leg with tag <%.*s> not found\n", tag->len, tag->s); + goto end; + } + if (dlg->legs[leg].last_gen_cseq == 0) { + /*local sequence number*/ + cseq = dlg->legs[leg].r_cseq; + if (!cseq.s || !cseq.len || str2int(&cseq, &loc_seq) != 0){ + LM_ERR("invalid cseq\n"); + goto end; + } + + dlg->legs[leg].last_gen_cseq = loc_seq + count; + } else { + dlg->legs[leg].last_gen_cseq += count; + loc_seq = -1; + } + LM_DBG("increasing leg=%d cseq=%u count=%d gen=%d\n", + leg, loc_seq, count, dlg->legs[leg].last_gen_cseq); + ret = 1; + + dlg->flags |= DLG_FLAG_CSEQ_ENFORCE; +end: + dlg_unlock_dlg(dlg); + return ret; +} diff --git a/modules/dialog/doc/dialog_admin.xml b/modules/dialog/doc/dialog_admin.xml index 7569d2b8bb5..293e37d31e9 100644 --- a/modules/dialog/doc/dialog_admin.xml +++ b/modules/dialog/doc/dialog_admin.xml @@ -2602,6 +2602,45 @@ event_route[E_RTPPROXY_DTMF] { } } ... + + + +
+ + <function moreinfo="none">dlg_inc_cseq([tag, ][inc])</function> + + Increments the dialog's generated CSeq associated to the leg + identified by the dialog's tag. + + Parameters: + + tag (string, optional) - + the tag to increment the CSeq value for. If missing, the + message's To tag is used to identify + the leg to increment the CSeq for. + + inc (integer, optional) - the + value used to increment/decrement (if negative) the CSeq of + the identified leg. If not used, the value is incremented with + 1. + + + + This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, + ONREPLY_ROUTE, BRANCH_ROUTE and LOCAL_ROUTE routes. + + + <function>dlg_inc_cseq</function> usage + +... +route { + ... + if (has_totag()) { + if (loose_route()) + dlg_inc_cseq(); # increment upstream CSeq after each in-dialog request + } +} +...