@@ -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 )
0 commit comments