Skip to content

Commit 717e8a3

Browse files
committed
callops: add headers params to call_hold/call_unhold MI cmds
1 parent 033eafa commit 717e8a3

2 files changed

Lines changed: 108 additions & 51 deletions

File tree

modules/callops/callops.c

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,13 @@ static const mi_export_t mi_cmds[] = {
222222
{ "call_hold", 0, 0, 0, {
223223
{mi_call_hold, {"callid", 0}},
224224
{mi_call_hold, {"callid", "leg", 0}},
225+
{mi_call_hold, {"callid", "leg", "headers", 0}},
225226
{EMPTY_MI_RECIPE}}
226227
},
227228
{ "call_unhold", 0, 0, 0, {
228229
{mi_call_unhold, {"callid", 0}},
229230
{mi_call_unhold, {"callid", "leg", 0}},
231+
{mi_call_unhold, {"callid", "leg", "headers", 0}},
230232
{EMPTY_MI_RECIPE}}
231233
},
232234
{EMPTY_MI_EXPORT}
@@ -1171,7 +1173,7 @@ static int call_get_hold_body(struct dlg_cell *dlg, int leg, unsigned mode, str
11711173
return 1;
11721174
}
11731175

1174-
static int call_put_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode)
1176+
static int call_put_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode, str *hdrs)
11751177
{
11761178
int ret;
11771179
unsigned int param;
@@ -1214,7 +1216,7 @@ static int call_put_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode)
12141216

12151217
/* send it out */
12161218
ret = call_dlg_api.send_indialog_request(dlg, &invite, leg, &body, &ct,
1217-
NULL, mi_call_hold_reply, (void *)(long)param, NULL);
1219+
hdrs, mi_call_hold_reply, (void *)(long)param, NULL);
12181220
pkg_free(body.s);
12191221
if (ret < 0) {
12201222
init_str(&state, "fail");
@@ -1225,7 +1227,7 @@ static int call_put_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode)
12251227
return 1;
12261228
}
12271229

1228-
static int call_resume_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode)
1230+
static int call_resume_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode, str *hdrs)
12291231
{
12301232
str body;
12311233
str invite = str_init("INVITE");
@@ -1275,7 +1277,7 @@ static int call_resume_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode)
12751277

12761278
RAISE_CALL_EVENT(HOLD, &dlg->callid, &sleg, &action, &state, NULL);
12771279
if (call_dlg_api.send_indialog_request(dlg, &invite, leg, &body, &ct,
1278-
NULL, mi_call_hold_reply, (void *)(long)param, NULL) < 0) {
1280+
hdrs, mi_call_hold_reply, (void *)(long)param, NULL) < 0) {
12791281
init_str(&state, "fail");
12801282
RAISE_CALL_EVENT(HOLD, &dlg->callid, &sleg, &action, &state, NULL);
12811283
LM_ERR("could not resume leg %d\n", leg);
@@ -1284,40 +1286,93 @@ static int call_resume_leg_onhold(struct dlg_cell *dlg, int leg, unsigned mode)
12841286
return 1;
12851287
}
12861288

1287-
1288-
static mi_response_t *mi_call_hold(const mi_params_t *params,
1289-
struct mi_handler *async_hdl)
1289+
static mi_response_t *mi_parse_call_hold(const mi_params_t *params, str *callid,
1290+
str *leg, unsigned *caller_mode, unsigned *callee_mode,
1291+
str *caller_hdrs, str *callee_hdrs)
12901292
{
1291-
str callid;
1292-
str leg, action, state;
1293-
struct dlg_cell *dlg;
1294-
mi_response_t *ret = NULL;
1295-
int ret_callee;
1296-
int ret_caller;
1297-
unsigned caller_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1298-
unsigned callee_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1293+
int hdrs_no;
1294+
str tmp;
1295+
mi_item_t *hdrs_arr;
1296+
caller_hdrs->len = callee_hdrs->len = 0;
1297+
caller_hdrs->s = callee_hdrs->s = NULL;
1298+
1299+
*caller_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1300+
*callee_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
12991301

13001302
if (get_mi_string_param(params, "callid",
1301-
&callid.s, &callid.len) < 0)
1303+
&callid->s, &callid->len) < 0)
13021304
return init_mi_param_error();
13031305

1304-
switch (try_get_mi_string_param(params, "leg", &leg.s, &leg.len)) {
1306+
switch (try_get_mi_string_param(params, "leg", &leg->s, &leg->len)) {
13051307
case -2:
13061308
return init_mi_param_error();
13071309
case -1:
13081310
break;
13091311
default:
1310-
if (str_match_nt(&leg, "caller")) {
1311-
caller_mode = CALLOPS_RECV_OFF;
1312-
callee_mode = CALLOPS_SEND_OFF;
1313-
} else if (str_match_nt(&leg, "callee")) {
1314-
caller_mode = CALLOPS_SEND_OFF;
1315-
callee_mode = CALLOPS_RECV_OFF;
1316-
} else if (!str_match_nt(&leg, "both")) {
1312+
if (str_match_nt(leg, "caller")) {
1313+
*caller_mode = CALLOPS_RECV_OFF;
1314+
*callee_mode = CALLOPS_SEND_OFF;
1315+
} else if (str_match_nt(leg, "callee")) {
1316+
*caller_mode = CALLOPS_SEND_OFF;
1317+
*callee_mode = CALLOPS_RECV_OFF;
1318+
} else if (!str_match_nt(leg, "both")) {
13171319
return init_mi_error(420, MI_SSTR("Bad leg"));
13181320
}
13191321
}
13201322

1323+
/* we try to parse it as string, and if it does not work, as array of two
1324+
* elements - first is the caller's headers, second is the callee's
1325+
* headers */
1326+
switch (try_get_mi_string_param(params, "headers", &tmp.s, &tmp.len)) {
1327+
case -2:
1328+
/* bad type - could be an array ? */
1329+
switch (try_get_mi_array_param(params, "headers", &hdrs_arr, &hdrs_no)) {
1330+
case -1:
1331+
case -3:
1332+
break;
1333+
case -2:
1334+
return init_mi_param_error();
1335+
default:
1336+
if (hdrs_no > 0 && get_mi_arr_param_string(hdrs_arr, 0,
1337+
&caller_hdrs->s, &caller_hdrs->len) < 0)
1338+
return init_mi_param_error();
1339+
unescape_crlf(caller_hdrs);
1340+
if (hdrs_no > 1 && get_mi_arr_param_string(hdrs_arr, 1,
1341+
&callee_hdrs->s, &callee_hdrs->len) < 0)
1342+
return init_mi_param_error();
1343+
unescape_crlf(callee_hdrs);
1344+
break;
1345+
}
1346+
break;
1347+
case -1:
1348+
break;
1349+
default:
1350+
unescape_crlf(&tmp);
1351+
*caller_hdrs = tmp;
1352+
*callee_hdrs = tmp;
1353+
break;
1354+
}
1355+
1356+
return NULL;
1357+
}
1358+
1359+
static mi_response_t *mi_call_hold(const mi_params_t *params,
1360+
struct mi_handler *async_hdl)
1361+
{
1362+
str callid;
1363+
str leg, action, state;
1364+
str caller_hdrs, callee_hdrs;
1365+
struct dlg_cell *dlg;
1366+
mi_response_t *ret = NULL;
1367+
int ret_callee;
1368+
int ret_caller;
1369+
unsigned caller_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1370+
unsigned callee_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1371+
1372+
if ((ret = mi_parse_call_hold(params, &callid, &leg,
1373+
&caller_mode, &callee_mode, &caller_hdrs, &callee_hdrs)) != NULL)
1374+
return ret;
1375+
13211376
dlg = call_dlg_api.get_dlg_by_callid(&callid, 1);
13221377
if (!dlg)
13231378
return init_mi_error(404, MI_SSTR("Dialog not found"));
@@ -1326,17 +1381,17 @@ static mi_response_t *mi_call_hold(const mi_params_t *params,
13261381
ret = init_mi_error(410, MI_SSTR("Dialog not ready"));
13271382
goto unref;
13281383
}
1329-
ret_caller = call_put_leg_onhold(dlg, DLG_CALLER_LEG, caller_mode);
1384+
ret_caller = call_put_leg_onhold(dlg, DLG_CALLER_LEG, caller_mode, &caller_hdrs);
13301385
if (ret_caller < 0)
13311386
goto unref;
1332-
ret_callee = call_put_leg_onhold(dlg, callee_idx(dlg), callee_mode);
1387+
ret_callee = call_put_leg_onhold(dlg, callee_idx(dlg), callee_mode, &callee_hdrs);
13331388
if (ret_callee < 0) {
13341389
if (ret_caller != 0) {
13351390
init_str(&leg, "caller");
13361391
init_str(&state, "state");
13371392
init_str(&action, "action");
13381393
RAISE_CALL_EVENT(HOLD, &dlg->callid, &leg, &action, &state, NULL);
1339-
call_resume_leg_onhold(dlg, DLG_CALLER_LEG, caller_mode);
1394+
call_resume_leg_onhold(dlg, DLG_CALLER_LEG, caller_mode, &caller_hdrs);
13401395
}
13411396
goto unref;
13421397
}
@@ -1357,29 +1412,13 @@ static mi_response_t *mi_call_unhold(const mi_params_t *params,
13571412
struct dlg_cell *dlg;
13581413
mi_response_t *ret = NULL;
13591414
int ret_caller, ret_callee;
1360-
unsigned caller_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1361-
unsigned callee_mode = CALLOPS_SEND_OFF | CALLOPS_RECV_OFF;
1362-
1363-
if (get_mi_string_param(params, "callid",
1364-
&callid.s, &callid.len) < 0)
1365-
return init_mi_param_error();
1415+
str caller_hdrs, callee_hdrs;
1416+
unsigned caller_mode;
1417+
unsigned callee_mode;
13661418

1367-
switch (try_get_mi_string_param(params, "leg", &leg.s, &leg.len)) {
1368-
case -2:
1369-
return init_mi_param_error();
1370-
case -1:
1371-
break;
1372-
default:
1373-
if (str_match_nt(&leg, "caller")) {
1374-
caller_mode = CALLOPS_RECV_OFF;
1375-
callee_mode = CALLOPS_SEND_OFF;
1376-
} else if (str_match_nt(&leg, "callee")) {
1377-
caller_mode = CALLOPS_SEND_OFF;
1378-
callee_mode = CALLOPS_RECV_OFF;
1379-
} else if (!str_match_nt(&leg, "both")) {
1380-
return init_mi_error(420, MI_SSTR("Bad leg"));
1381-
}
1382-
}
1419+
if ((ret = mi_parse_call_hold(params, &callid, &leg,
1420+
&caller_mode, &callee_mode, &caller_hdrs, &callee_hdrs)) != NULL)
1421+
return ret;
13831422

13841423
dlg = call_dlg_api.get_dlg_by_callid(&callid, 1);
13851424
if (!dlg)
@@ -1389,8 +1428,8 @@ static mi_response_t *mi_call_unhold(const mi_params_t *params,
13891428
ret = init_mi_error(410, MI_SSTR("Dialog not ready"));
13901429
goto unref;
13911430
}
1392-
ret_callee = call_resume_leg_onhold(dlg, callee_idx(dlg), callee_mode);
1393-
ret_caller = call_resume_leg_onhold(dlg, DLG_CALLER_LEG, caller_mode);
1431+
ret_callee = call_resume_leg_onhold(dlg, callee_idx(dlg), callee_mode, &callee_hdrs);
1432+
ret_caller = call_resume_leg_onhold(dlg, DLG_CALLER_LEG, caller_mode, &caller_hdrs);
13941433
if (ret_caller == 0 && ret_callee == 0)
13951434
ret = init_mi_error(480, MI_SSTR("No dialog legs on hold"));
13961435
else if (ret_caller > 0 || ret_callee > 0)

modules/callops/doc/callops_admin.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,15 @@ opensips-cli -x mi call_transfer \
459459
is being put on hold. If not used, both legs are being
460460
put on hold.
461461
</para></listitem>
462+
<listitem><para>
463+
<emphasis>headers</emphasis> (string or array, optional) -
464+
extra headers to be added to the outgoing re-INVITE.
465+
If a string is provided, the headers go to both caller
466+
and callee. If a two string elements array is provided,
467+
the first element represents the headers that go to the
468+
caller, the second one headers that go to the callee.
469+
Use empty string for no headers to be passed at caller.
470+
</para></listitem>
462471
</itemizedlist>
463472
<para>
464473
MI FIFO Command Format:
@@ -500,6 +509,15 @@ opensips-cli -x mi call_hold \
500509
and <emphasis>bold</emphasis> and indicate the leg that
501510
is being resumed. If not used, both legs are resumed.
502511
</para></listitem>
512+
<listitem><para>
513+
<emphasis>headers</emphasis> (string or array, optional) -
514+
extra headers to be added to the outgoing re-INVITE.
515+
If a string is provided, the headers go to both caller
516+
and callee. If a two string elements array is provided,
517+
the first element represents the headers that go to the
518+
caller, the second one headers that go to the callee.
519+
Use empty string for no headers to be passed at caller.
520+
</para></listitem>
503521
</itemizedlist>
504522
<para>
505523
MI FIFO Command Format:

0 commit comments

Comments
 (0)