Skip to content

Commit 5fc57e9

Browse files
committed
cfgutils: Add support for large diffs in ts_usec_delta()
This patch reworks the 5th parameter as a string output variable, thus avoiding issues related to integer overflows when the time diffs get larger (e.g. differences of 35+ minutes, which are not uncommon). Note: NOT backwards-compatible
1 parent 422f815 commit 5fc57e9

File tree

2 files changed

+51
-18
lines changed

2 files changed

+51
-18
lines changed

modules/cfgutils/cfgutils.c

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ mi_response_t *mi_check_hash(const mi_params_t *params,
106106
static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
107107
pv_value_t *res);
108108

109-
static int ts_usec_delta(struct sip_msg *msg, int *t1s,
110-
int *t1u, int *t2s, int *t2u, pv_spec_t *_res);
109+
static int ts_usec_delta(struct sip_msg *msg, int *t1s, int *t1u,
110+
int *t2s, int *t2u, pv_spec_t *pv_delta_str, pv_spec_t *pv_delta_int);
111111
int check_time_rec(struct sip_msg *_, char *time_rec, unsigned int *ptime);
112112

113113
#ifdef HAVE_TIMER_FD
@@ -182,7 +182,8 @@ static const cmd_export_t cmds[]={
182182
{CMD_PARAM_INT, 0, 0},
183183
{CMD_PARAM_INT, 0, 0},
184184
{CMD_PARAM_INT, 0, 0},
185-
{CMD_PARAM_VAR, fixup_check_pv_setf, 0}, {0,0,0}},
185+
{CMD_PARAM_VAR|CMD_PARAM_OPT, fixup_check_pv_setf, 0},
186+
{CMD_PARAM_VAR|CMD_PARAM_OPT, fixup_check_pv_setf, 0}, {0,0,0}},
186187
REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE|
187188
STARTUP_ROUTE|TIMER_ROUTE|EVENT_ROUTE},
188189
{"get_static_lock",(cmd_function)get_static_lock, {
@@ -307,8 +308,8 @@ struct module_exports exports = {
307308

308309
static int fixup_check_pv_setf(void **param)
309310
{
310-
if (((pv_spec_t*)*param)->setf == 0) {
311-
LM_ERR("invalid pvar\n");
311+
if (!pv_is_w(((pv_spec_t*)*param))) {
312+
LM_ERR("invalid pvar: must be writable\n");
312313
return E_SCRIPT;
313314
}
314315

@@ -824,18 +825,44 @@ static int pv_sel_weight(struct sip_msg* msg, pv_spec_t *pv_name)
824825
return -1;
825826
}
826827

827-
static int ts_usec_delta(struct sip_msg *msg, int *t1s,
828-
int *t1u, int *t2s, int *t2u, pv_spec_t *_res)
828+
static int ts_usec_delta(struct sip_msg *msg, int *t1s, int *t1u,
829+
int *t2s, int *t2u, pv_spec_t *pv_delta_str, pv_spec_t *pv_delta_int)
829830
{
830-
pv_value_t res;
831+
pv_value_t val;
832+
long long diff;
831833

832-
res.ri = abs(1000000 * (*t1s - *t2s) + *t1u - *t2u);
833-
res.flags = PV_TYPE_INT;
834+
diff = llabs(1000000LL * (*t1s - *t2s) + *t1u - *t2u);
834835

835-
if (pv_set_value(msg, _res, 0, &res)) {
836-
LM_ERR("cannot store result value\n");
837-
return -1;
836+
if (pv_delta_str) {
837+
char diff_buf[20 + 1];
838+
839+
val.rs.s = diff_buf;
840+
val.rs.len = sprintf(diff_buf, "%lld", diff);
841+
val.flags = PV_VAL_STR;
842+
843+
if (pv_set_value(msg, pv_delta_str, 0, &val) != 0) {
844+
LM_ERR("failed to set the 'delta_str' output variable\n");
845+
return -1;
846+
}
847+
}
848+
849+
if (pv_delta_int) {
850+
if (diff > INT_MAX) {
851+
LM_ERR("diff is too large to store in 'delta_int' (%lld us), "
852+
"use the 'delta_str' output variable instead!\n", diff);
853+
return -1;
854+
}
855+
856+
val.rs = STR_NULL;
857+
val.ri = (int)diff;
858+
val.flags = PV_VAL_INT|PV_TYPE_INT;
859+
860+
if (pv_set_value(msg, pv_delta_int, 0, &val)) {
861+
LM_ERR("failed to set the 'delta_int' output variable\n");
862+
return -1;
863+
}
838864
}
865+
839866
return 1;
840867
}
841868

modules/cfgutils/doc/cfgutils_admin.xml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -473,12 +473,18 @@ $var(next_gw_idx) = set_select_weight($avp(gw_success_rates));
473473
</section>
474474
<section id="func_ts_usec_delta" xreflabel="ts_usec_delta()">
475475
<title>
476-
<function moreinfo="none">ts_usec_delta(t1_sec, t1_usec, t2_sec, t2_usec, delta)</function>
476+
<function moreinfo="none">ts_usec_delta(t1_sec, t1_usec, t2_sec, t2_usec, [delta_str], [delta_int])</function>
477477
</title>
478478
<para>
479-
This function returns the difference between two timestamps, specified
480-
in seconds and microseconds. The result is returned in the last
481-
parameter, expressed in microseconds.
479+
This function returns the absolute difference between the two given
480+
timestamps. The result is expressed as <emphasis>microseconds</emphasis>
481+
and can be returned as either string or integer.
482+
</para>
483+
<para>
484+
<emphasis role='bold'>WARNING:</emphasis> when using
485+
<emphasis>delta_int</emphasis>, the function will return error code
486+
<emphasis role='bold'>-1</emphasis> in case the difference overflows
487+
the signed integer holder! (i.e. a diff of ~35 minutes or more)
482488
</para>
483489
<para>
484490
This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
@@ -488,7 +494,7 @@ $var(next_gw_idx) = set_select_weight($avp(gw_success_rates));
488494
<title><function>ts_usec_delta</function> usage</title>
489495
<programlisting format="linespecific">
490496
...
491-
ts_usec_delta($var(t1s), 300, 10, $var(t2ms), $var(result));
497+
ts_usec_delta($var(t1s), 300, 10, $var(t2us), $var(diff_str));
492498
...
493499
</programlisting>
494500
</example>

0 commit comments

Comments
 (0)