This reverts commit 1465a9b6e9fda36617b7b198ae051f0957803550.
... | ... |
@@ -123,6 +123,9 @@ str dlg_bridge_controller = str_init("sip:controller@kamailio.org"); |
123 | 123 |
|
124 | 124 |
str dlg_bridge_contact = str_init("sip:controller@kamailio.org:5060"); |
125 | 125 |
|
126 |
+int bye_early_code = 480; |
|
127 |
+str bye_early_reason = str_init("Temporarily Unavailable"); |
|
128 |
+ |
|
126 | 129 |
str ruri_pvar_param = str_init("$ru"); |
127 | 130 |
pv_elem_t * ruri_param_model = NULL; |
128 | 131 |
str empty_str = STR_NULL; |
... | ... |
@@ -204,6 +207,16 @@ static int w_dlg_remote_profile(sip_msg_t *msg, char *cmd, char *pname, |
204 | 207 |
char *pval, char *puid, char *expires); |
205 | 208 |
static int fixup_dlg_remote_profile(void** param, int param_no); |
206 | 209 |
|
210 |
+static int w_dlg_req_with_headers_and_content(struct sip_msg *, char *, char *, char* , char *, char *); |
|
211 |
+static int w_dlg_req_with_content(struct sip_msg *, char *, char *, char *, char *); |
|
212 |
+static int w_dlg_req_with_headers(struct sip_msg *, char *, char *, char *); |
|
213 |
+static int w_dlg_req_within(struct sip_msg *, char *, char *); |
|
214 |
+ |
|
215 |
+static int fixup_dlg_dlg_req_within(void** , int ); |
|
216 |
+static int fixup_dlg_req_with_headers(void** , int ); |
|
217 |
+static int fixup_dlg_req_with_content(void** , int ); |
|
218 |
+static int fixup_dlg_req_with_headers_and_content(void** , int ); |
|
219 |
+ |
|
207 | 220 |
static cmd_export_t cmds[]={ |
208 | 221 |
{"dlg_manage", (cmd_function)w_dlg_manage, 0,0, |
209 | 222 |
0, REQUEST_ROUTE }, |
... | ... |
@@ -265,6 +278,14 @@ static cmd_export_t cmds[]={ |
265 | 278 |
fixup_dlg_get_var_free, ANY_ROUTE }, |
266 | 279 |
{"dlg_set_var",(cmd_function)w_dlg_set_var, 5, fixup_dlg_set_var, |
267 | 280 |
fixup_dlg_set_var_free, ANY_ROUTE }, |
281 |
+ {"dlg_req_within", (cmd_function)w_dlg_req_within, 2, fixup_dlg_dlg_req_within, |
|
282 |
+ 0, ANY_ROUTE}, |
|
283 |
+ {"dlg_req_within", (cmd_function)w_dlg_req_with_headers, 3, fixup_dlg_req_with_headers, |
|
284 |
+ 0, ANY_ROUTE}, |
|
285 |
+ {"dlg_req_within", (cmd_function)w_dlg_req_with_content, 4, fixup_dlg_req_with_content, |
|
286 |
+ 0, ANY_ROUTE}, |
|
287 |
+ {"dlg_req_within", (cmd_function)w_dlg_req_with_headers_and_content, 5, |
|
288 |
+ fixup_dlg_req_with_headers_and_content, 0, ANY_ROUTE}, |
|
268 | 289 |
|
269 | 290 |
{"load_dlg", (cmd_function)load_dlg, 0, 0, 0, 0}, |
270 | 291 |
{0,0,0,0,0,0} |
... | ... |
@@ -338,6 +359,8 @@ static param_export_t mod_params[]={ |
338 | 359 |
{ "h_id_step", PARAM_INT, &dlg_h_id_step }, |
339 | 360 |
{ "keep_proxy_rr", INT_PARAM, &dlg_keep_proxy_rr }, |
340 | 361 |
{ "dlg_filter_mode", INT_PARAM, &dlg_filter_mode }, |
362 |
+ { "bye_early_code", PARAM_INT, &bye_early_code }, |
|
363 |
+ { "bye_early_reason", PARAM_STR, &bye_early_reason }, |
|
341 | 364 |
{ 0,0,0 } |
342 | 365 |
}; |
343 | 366 |
|
... | ... |
@@ -1112,6 +1135,232 @@ static int w_dlg_manage(struct sip_msg *msg, char *s1, char *s2) |
1112 | 1135 |
return dlg_manage(msg); |
1113 | 1136 |
} |
1114 | 1137 |
|
1138 |
+static int fixup_dlg_dlg_req_within(void** param, int param_no) |
|
1139 |
+{ |
|
1140 |
+ char *val; |
|
1141 |
+ int n = 0; |
|
1142 |
+ |
|
1143 |
+ if (param_no==1) { |
|
1144 |
+ val = (char*)*param; |
|
1145 |
+ if (strcasecmp(val,"all")==0) { |
|
1146 |
+ n = 0; |
|
1147 |
+ } else if (strcasecmp(val,"caller")==0) { |
|
1148 |
+ n = 1; |
|
1149 |
+ } else if (strcasecmp(val,"callee")==0) { |
|
1150 |
+ n = 2; |
|
1151 |
+ } else { |
|
1152 |
+ LM_ERR("invalid param \"%s\"\n", val); |
|
1153 |
+ return E_CFG; |
|
1154 |
+ } |
|
1155 |
+ pkg_free(*param); |
|
1156 |
+ *param=(void*)(long)n; |
|
1157 |
+ } else if (param_no==2) { |
|
1158 |
+ return fixup_spve_null(param, 1); |
|
1159 |
+ } else { |
|
1160 |
+ LM_ERR("called with parameter != 1\n"); |
|
1161 |
+ return E_BUG; |
|
1162 |
+ } |
|
1163 |
+ return 0; |
|
1164 |
+} |
|
1165 |
+ |
|
1166 |
+static int fixup_dlg_req_with_headers(void** param, int param_no) |
|
1167 |
+{ |
|
1168 |
+ char *val; |
|
1169 |
+ int n = 0; |
|
1170 |
+ |
|
1171 |
+ if (param_no==1) { |
|
1172 |
+ val = (char*)*param; |
|
1173 |
+ if (strcasecmp(val,"all")==0) { |
|
1174 |
+ n = 0; |
|
1175 |
+ } else if (strcasecmp(val,"caller")==0) { |
|
1176 |
+ n = 1; |
|
1177 |
+ } else if (strcasecmp(val,"callee")==0) { |
|
1178 |
+ n = 2; |
|
1179 |
+ } else { |
|
1180 |
+ LM_ERR("invalid param \"%s\"\n", val); |
|
1181 |
+ return E_CFG; |
|
1182 |
+ } |
|
1183 |
+ pkg_free(*param); |
|
1184 |
+ *param=(void*)(long)n; |
|
1185 |
+ } else if (param_no==2) { |
|
1186 |
+ return fixup_spve_null(param, 1); |
|
1187 |
+ } else if (param_no==3) { |
|
1188 |
+ return fixup_spve_null(param, 1); |
|
1189 |
+ } else { |
|
1190 |
+ LM_ERR("called with parameter != 1\n"); |
|
1191 |
+ return E_BUG; |
|
1192 |
+ } |
|
1193 |
+ return 0; |
|
1194 |
+} |
|
1195 |
+ |
|
1196 |
+ |
|
1197 |
+static int fixup_dlg_req_with_content(void** param, int param_no) |
|
1198 |
+{ |
|
1199 |
+ char *val; |
|
1200 |
+ int n = 0; |
|
1201 |
+ |
|
1202 |
+ if (param_no==1) { |
|
1203 |
+ val = (char*)*param; |
|
1204 |
+ if (strcasecmp(val,"all")==0) { |
|
1205 |
+ n = 0; |
|
1206 |
+ } else if (strcasecmp(val,"caller")==0) { |
|
1207 |
+ n = 1; |
|
1208 |
+ } else if (strcasecmp(val,"callee")==0) { |
|
1209 |
+ n = 2; |
|
1210 |
+ } else { |
|
1211 |
+ LM_ERR("invalid param \"%s\"\n", val); |
|
1212 |
+ return E_CFG; |
|
1213 |
+ } |
|
1214 |
+ pkg_free(*param); |
|
1215 |
+ *param=(void*)(long)n; |
|
1216 |
+ } else if (param_no==2) { |
|
1217 |
+ return fixup_spve_null(param, 1); |
|
1218 |
+ } else if (param_no==3) { |
|
1219 |
+ return fixup_spve_null(param, 1); |
|
1220 |
+ } else if (param_no==4) { |
|
1221 |
+ return fixup_spve_null(param, 1); |
|
1222 |
+ } else { |
|
1223 |
+ LM_ERR("called with parameter != 1\n"); |
|
1224 |
+ return E_BUG; |
|
1225 |
+ } |
|
1226 |
+ return 0; |
|
1227 |
+} |
|
1228 |
+ |
|
1229 |
+static int fixup_dlg_req_with_headers_and_content(void** param, int param_no) |
|
1230 |
+{ |
|
1231 |
+ char *val; |
|
1232 |
+ int n = 0; |
|
1233 |
+ |
|
1234 |
+ if (param_no==1) { |
|
1235 |
+ val = (char*)*param; |
|
1236 |
+ if (strcasecmp(val,"all")==0) { |
|
1237 |
+ n = 0; |
|
1238 |
+ } else if (strcasecmp(val,"caller")==0) { |
|
1239 |
+ n = 1; |
|
1240 |
+ } else if (strcasecmp(val,"callee")==0) { |
|
1241 |
+ n = 2; |
|
1242 |
+ } else { |
|
1243 |
+ LM_ERR("invalid param \"%s\"\n", val); |
|
1244 |
+ return E_CFG; |
|
1245 |
+ } |
|
1246 |
+ pkg_free(*param); |
|
1247 |
+ *param=(void*)(long)n; |
|
1248 |
+ } else if (param_no==2) { |
|
1249 |
+ return fixup_spve_null(param, 1); |
|
1250 |
+ } else if (param_no==3) { |
|
1251 |
+ return fixup_spve_null(param, 1); |
|
1252 |
+ } else if (param_no==4) { |
|
1253 |
+ return fixup_spve_null(param, 1); |
|
1254 |
+ } else if (param_no==5) { |
|
1255 |
+ return fixup_spve_null(param, 1); |
|
1256 |
+ } else { |
|
1257 |
+ LM_ERR("called with parameter != 1\n"); |
|
1258 |
+ return E_BUG; |
|
1259 |
+ } |
|
1260 |
+ return 0; |
|
1261 |
+} |
|
1262 |
+ |
|
1263 |
+static int w_dlg_req_with_headers_and_content(struct sip_msg *msg, char *side, char *method, char* headers, char *content_type, char *content) |
|
1264 |
+{ |
|
1265 |
+ dlg_cell_t *dlg = NULL; |
|
1266 |
+ int n; |
|
1267 |
+ str str_method = {0,0}; |
|
1268 |
+ str str_headers = {0,0}; |
|
1269 |
+ str str_content_type = {0,0}; |
|
1270 |
+ str str_content = {0,0}; |
|
1271 |
+ |
|
1272 |
+ dlg = dlg_get_ctx_dialog(); |
|
1273 |
+ if(dlg==NULL) |
|
1274 |
+ return -1; |
|
1275 |
+ |
|
1276 |
+ if(fixup_get_svalue(msg, (gparam_p)method, &str_method)!=0) |
|
1277 |
+ { |
|
1278 |
+ LM_ERR("unable to get Method\n"); |
|
1279 |
+ goto error; |
|
1280 |
+ } |
|
1281 |
+ if(str_method.s==NULL || str_method.len == 0) |
|
1282 |
+ { |
|
1283 |
+ LM_ERR("invalid Method parameter\n"); |
|
1284 |
+ goto error; |
|
1285 |
+ } |
|
1286 |
+ |
|
1287 |
+ if (headers) { |
|
1288 |
+ if(fixup_get_svalue(msg, (gparam_p)headers, &str_headers)!=0) |
|
1289 |
+ { |
|
1290 |
+ LM_ERR("unable to get Method\n"); |
|
1291 |
+ goto error; |
|
1292 |
+ } |
|
1293 |
+ if(str_headers.s==NULL || str_headers.len == 0) |
|
1294 |
+ { |
|
1295 |
+ LM_ERR("invalid Headers parameter\n"); |
|
1296 |
+ goto error; |
|
1297 |
+ } |
|
1298 |
+ } |
|
1299 |
+ if (content_type && content) { |
|
1300 |
+ if(fixup_get_svalue(msg, (gparam_p)content_type, &str_content_type)!=0) |
|
1301 |
+ { |
|
1302 |
+ LM_ERR("unable to get Content-Type\n"); |
|
1303 |
+ goto error; |
|
1304 |
+ } |
|
1305 |
+ if(str_content_type.s==NULL || str_content_type.len == 0) |
|
1306 |
+ { |
|
1307 |
+ LM_ERR("invalid Headers parameter\n"); |
|
1308 |
+ goto error; |
|
1309 |
+ } |
|
1310 |
+ if(fixup_get_svalue(msg, (gparam_p)content, &str_content)!=0) |
|
1311 |
+ { |
|
1312 |
+ LM_ERR("unable to get Content\n"); |
|
1313 |
+ goto error; |
|
1314 |
+ } |
|
1315 |
+ if(str_content.s==NULL || str_content.len == 0) |
|
1316 |
+ { |
|
1317 |
+ LM_ERR("invalid Content parameter\n"); |
|
1318 |
+ goto error; |
|
1319 |
+ } |
|
1320 |
+ } |
|
1321 |
+ |
|
1322 |
+ n = (int)(long)side; |
|
1323 |
+ if(n==1) |
|
1324 |
+ { |
|
1325 |
+ if(dlg_request_within(msg, dlg, DLG_CALLER_LEG, &str_method, &str_headers, &str_content_type, &str_content)!=0) |
|
1326 |
+ goto error; |
|
1327 |
+ goto done; |
|
1328 |
+ } else if(n==2) { |
|
1329 |
+ if(dlg_request_within(msg, dlg, DLG_CALLEE_LEG, &str_method, &str_headers, &str_content_type, &str_content)!=0) |
|
1330 |
+ goto error; |
|
1331 |
+ goto done; |
|
1332 |
+ } else { |
|
1333 |
+ if(dlg_request_within(msg, dlg, DLG_CALLER_LEG, &str_method, &str_headers, &str_content_type, &str_content)!=0) |
|
1334 |
+ goto error; |
|
1335 |
+ if(dlg_request_within(msg, dlg, DLG_CALLEE_LEG, &str_method, &str_headers, &str_content_type, &str_content)!=0) |
|
1336 |
+ goto error; |
|
1337 |
+ goto done; |
|
1338 |
+ } |
|
1339 |
+ |
|
1340 |
+done: |
|
1341 |
+ dlg_release(dlg); |
|
1342 |
+ return 1; |
|
1343 |
+ |
|
1344 |
+error: |
|
1345 |
+ dlg_release(dlg); |
|
1346 |
+ return -1; |
|
1347 |
+} |
|
1348 |
+ |
|
1349 |
+static int w_dlg_req_with_content(struct sip_msg *msg, char *side, char *method, char *content_type, char *content) |
|
1350 |
+{ |
|
1351 |
+ return w_dlg_req_with_headers_and_content(msg, side, method, NULL, content_type, content); |
|
1352 |
+} |
|
1353 |
+ |
|
1354 |
+static int w_dlg_req_with_headers(struct sip_msg *msg, char *side, char *method, char *headers) |
|
1355 |
+{ |
|
1356 |
+ return w_dlg_req_with_headers_and_content(msg, side, method, headers, NULL, NULL); |
|
1357 |
+} |
|
1358 |
+ |
|
1359 |
+static int w_dlg_req_within(struct sip_msg *msg, char *side, char *method) |
|
1360 |
+{ |
|
1361 |
+ return w_dlg_req_with_headers_and_content(msg, side, method, NULL, NULL, NULL); |
|
1362 |
+} |
|
1363 |
+ |
|
1115 | 1364 |
static int w_dlg_bye(struct sip_msg *msg, char *side, char *s2) |
1116 | 1365 |
{ |
1117 | 1366 |
dlg_cell_t *dlg = NULL; |
... | ... |
@@ -945,6 +945,8 @@ int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs) |
945 | 945 |
LM_ERR("failed to create new dialog\n"); |
946 | 946 |
return -1; |
947 | 947 |
} |
948 |
+ // Store link to Transaction |
|
949 |
+ dlg->t = t; |
|
948 | 950 |
|
949 | 951 |
/* save caller's tag, cseq, contact and record route*/ |
950 | 952 |
if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG, |
... | ... |
@@ -133,6 +133,7 @@ typedef struct dlg_cell |
133 | 133 |
struct dlg_head_cbl cbs; /*!< dialog callbacks */ |
134 | 134 |
struct dlg_profile_link *profile_links; /*!< dialog profiles */ |
135 | 135 |
struct dlg_var *vars; /*!< dialog variables */ |
136 |
+ struct cell *t; /*!< Reference to Transaction of the INVITE */ |
|
136 | 137 |
unsigned int ka_src_counter; /*!< keepalive src (caller) counter */ |
137 | 138 |
unsigned int ka_dst_counter; /*!< keepalive dst (callee) counter */ |
138 | 139 |
} dlg_cell_t; |
... | ... |
@@ -40,6 +40,7 @@ |
40 | 40 |
#include "../../modules/tm/dlg.h" |
41 | 41 |
#include "../../modules/tm/tm_load.h" |
42 | 42 |
#include "../../core/counters.h" |
43 |
+#include "../../core/parser/contact/parse_contact.h" |
|
43 | 44 |
#include "dlg_timer.h" |
44 | 45 |
#include "dlg_hash.h" |
45 | 46 |
#include "dlg_handlers.h" |
... | ... |
@@ -55,6 +56,9 @@ extern str dlg_lreq_callee_headers; |
55 | 56 |
extern int dlg_ka_failed_limit; |
56 | 57 |
extern int dlg_filter_mode; |
57 | 58 |
|
59 |
+extern int bye_early_code; |
|
60 |
+extern str bye_early_reason; |
|
61 |
+ |
|
58 | 62 |
/** |
59 | 63 |
* |
60 | 64 |
*/ |
... | ... |
@@ -378,10 +382,24 @@ static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs) |
378 | 382 |
dlg_iuid_t *iuid = NULL; |
379 | 383 |
str lhdrs; |
380 | 384 |
|
381 |
- /* do not send BYE request for non-confirmed dialogs (not supported) */ |
|
385 |
+ /* Send Cancel or final response for non-confirmed dialogs */ |
|
382 | 386 |
if (cell->state != DLG_STATE_CONFIRMED_NA && cell->state != DLG_STATE_CONFIRMED) { |
383 |
- LM_ERR("terminating non-confirmed dialogs not supported\n"); |
|
384 |
- return -1; |
|
387 |
+ if (cell->t) { |
|
388 |
+ if (dir == DLG_CALLER_LEG) { |
|
389 |
+ if(d_tmb.t_reply(cell->t->uas.request, bye_early_code, bye_early_reason.s)< 0) { |
|
390 |
+ LM_ERR("Failed to send reply to caller\n"); |
|
391 |
+ return -1; |
|
392 |
+ } |
|
393 |
+ LM_DBG("\"%d %.*s\" sent to caller\n", bye_early_code, bye_early_reason.len, bye_early_reason.s); |
|
394 |
+ } else { |
|
395 |
+ d_tmb.cancel_all_uacs(cell->t, 0); |
|
396 |
+ LM_DBG("CANCEL sent to callee(s)\n"); |
|
397 |
+ } |
|
398 |
+ return 0; |
|
399 |
+ } else { |
|
400 |
+ LM_ERR("terminating non-confirmed dialog not possible, transaction not longer available.\n"); |
|
401 |
+ return -1; |
|
402 |
+ } |
|
385 | 403 |
} |
386 | 404 |
|
387 | 405 |
/*verify direction*/ |
... | ... |
@@ -438,6 +456,262 @@ err: |
438 | 456 |
return -1; |
439 | 457 |
} |
440 | 458 |
|
459 |
+dlg_t * build_dlg_t_early(struct sip_msg *msg, struct dlg_cell * cell, int branch_id, str * rr_set){ |
|
460 |
+ |
|
461 |
+ dlg_t* td = NULL; |
|
462 |
+ str cseq; |
|
463 |
+ unsigned int loc_seq; |
|
464 |
+ char nbuf[MAX_URI_SIZE]; |
|
465 |
+ char dbuf[80]; |
|
466 |
+ str nuri = STR_NULL; |
|
467 |
+ str duri = STR_NULL; |
|
468 |
+ size_t sz; |
|
469 |
+ char *p; |
|
470 |
+ unsigned int own_rr = 0, skip_recs = 0; |
|
471 |
+ |
|
472 |
+ if (cell->state != DLG_STATE_UNCONFIRMED && cell->state != DLG_STATE_EARLY) { |
|
473 |
+ LM_ERR("Invalid state for build_dlg_state: %d (only working for unconfirmed or early dialogs)\n", cell->state); |
|
474 |
+ goto error; |
|
475 |
+ } |
|
476 |
+ |
|
477 |
+ if (msg == NULL || msg->first_line.type != SIP_REPLY) { |
|
478 |
+ if (!cell->t) { |
|
479 |
+ LM_ERR("No Transaction associated\n"); |
|
480 |
+ goto error; |
|
481 |
+ } |
|
482 |
+ |
|
483 |
+ if (branch_id <= 0 || branch_id > cell->t->nr_of_outgoings) { |
|
484 |
+ LM_ERR("Invalid branch %d (%d branches in transaction)\n", branch_id, cell->t->nr_of_outgoings); |
|
485 |
+ goto error; |
|
486 |
+ } |
|
487 |
+ msg = msg; |
|
488 |
+ } |
|
489 |
+ |
|
490 |
+ if (!msg->contact && (parse_headers(msg,HDR_CONTACT_F,0)<0 |
|
491 |
+ || !msg->contact)) { |
|
492 |
+ LM_ERR("bad sip message or missing Contact hdr\n"); |
|
493 |
+ goto error; |
|
494 |
+ } |
|
495 |
+ |
|
496 |
+ if ( parse_contact(msg->contact)<0 || |
|
497 |
+ ((contact_body_t *)msg->contact->parsed)->contacts==NULL) { |
|
498 |
+ LM_ERR("bad Contact HDR\n"); |
|
499 |
+ goto error; |
|
500 |
+ } |
|
501 |
+ |
|
502 |
+ /*try to restore alias parameter if no route set */ |
|
503 |
+ nuri.s = nbuf; |
|
504 |
+ nuri.len = MAX_URI_SIZE; |
|
505 |
+ duri.s = dbuf; |
|
506 |
+ duri.len = 80; |
|
507 |
+ if(uri_restore_rcv_alias(&((contact_body_t *)msg->contact->parsed)->contacts->uri, &nuri, &duri)<0) { |
|
508 |
+ nuri.len = 0; |
|
509 |
+ duri.len = 0; |
|
510 |
+ } |
|
511 |
+ |
|
512 |
+ if(nuri.len>0 && duri.len>0) { |
|
513 |
+ sz = sizeof(dlg_t) + (nuri.len+duri.len+2)*sizeof(char); |
|
514 |
+ } else { |
|
515 |
+ sz = sizeof(dlg_t); |
|
516 |
+ } |
|
517 |
+ |
|
518 |
+ td = (dlg_t*)pkg_malloc(sz); |
|
519 |
+ if(!td){ |
|
520 |
+ LM_ERR("out of pkg memory\n"); |
|
521 |
+ return NULL; |
|
522 |
+ } |
|
523 |
+ memset(td, 0, sz); |
|
524 |
+ |
|
525 |
+ /*route set*/ |
|
526 |
+ if (msg->record_route) { |
|
527 |
+ if (cell->t) { |
|
528 |
+ LM_DBG("Transaction exists\n"); |
|
529 |
+ own_rr = (cell->t->flags&TM_UAC_FLAG_R2)?2: |
|
530 |
+ (cell->t->flags&TM_UAC_FLAG_RR)?1:0; |
|
531 |
+ } else { |
|
532 |
+ own_rr = (msg->flags&TM_UAC_FLAG_R2)?2: |
|
533 |
+ (msg->flags&TM_UAC_FLAG_RR)?1:0; |
|
534 |
+ } |
|
535 |
+ skip_recs = cell->from_rr_nb + own_rr; |
|
536 |
+ |
|
537 |
+ LM_DBG("Skipping %u records, %u of myself\n", skip_recs, own_rr); |
|
538 |
+ |
|
539 |
+ if( print_rr_body(msg->record_route, rr_set, DLG_CALLEE_LEG, |
|
540 |
+ &skip_recs) != 0 ){ |
|
541 |
+ LM_ERR("failed to print route records \n"); |
|
542 |
+ goto error; |
|
543 |
+ } |
|
544 |
+ LM_DBG("New Route-Set: %.*s\n", STR_FMT(rr_set)); |
|
545 |
+ |
|
546 |
+ if( parse_rr_body(rr_set->s, rr_set->len, |
|
547 |
+ &td->route_set) !=0){ |
|
548 |
+ LM_ERR("failed to parse route set\n"); |
|
549 |
+ goto error; |
|
550 |
+ } |
|
551 |
+ } |
|
552 |
+ |
|
553 |
+ /*local sequence number*/ |
|
554 |
+ cseq = cell->cseq[DLG_CALLER_LEG]; |
|
555 |
+ |
|
556 |
+ if (cseq.len > 0) { |
|
557 |
+ LM_DBG("CSeq is %.*s\n", cseq.len, cseq.s); |
|
558 |
+ if(str2int(&cseq, &loc_seq) != 0){ |
|
559 |
+ LM_ERR("invalid cseq\n"); |
|
560 |
+ goto error; |
|
561 |
+ } |
|
562 |
+ } else { |
|
563 |
+ LM_DBG("CSeq not set yet, assuming 1\n"); |
|
564 |
+ loc_seq = 1; |
|
565 |
+ } |
|
566 |
+ |
|
567 |
+ /*we don not increase here the cseq as this will be done by TM*/ |
|
568 |
+ td->loc_seq.value = loc_seq; |
|
569 |
+ td->loc_seq.is_set = 1; |
|
570 |
+ |
|
571 |
+ LM_DBG("nuri: %.*s\n", STR_FMT(&nuri)); |
|
572 |
+ LM_DBG("duri: %.*s\n", STR_FMT(&duri)); |
|
573 |
+ |
|
574 |
+ if(nuri.len>0 && duri.len>0) { |
|
575 |
+ /* req uri */ |
|
576 |
+ p = (char*)td + sizeof(dlg_t); |
|
577 |
+ strncpy(p, nuri.s, nuri.len); |
|
578 |
+ p[nuri.len] = '\0'; |
|
579 |
+ td->rem_target.s = p; |
|
580 |
+ td->rem_target.len = nuri.len; |
|
581 |
+ /* dst uri */ |
|
582 |
+ p += nuri.len + 1; |
|
583 |
+ strncpy(p, duri.s, duri.len); |
|
584 |
+ p[duri.len] = '\0'; |
|
585 |
+ td->dst_uri.s = p; |
|
586 |
+ td->dst_uri.len = duri.len; |
|
587 |
+ } else { |
|
588 |
+ td->rem_target = ((contact_body_t *)msg->contact->parsed)->contacts->uri; |
|
589 |
+ } |
|
590 |
+ |
|
591 |
+ td->rem_uri = cell->from_uri; |
|
592 |
+ td->loc_uri = cell->to_uri; |
|
593 |
+ LM_DBG("rem_uri: %.*s\n", STR_FMT(&td->rem_uri)); |
|
594 |
+ LM_DBG("loc_uri: %.*s\n", STR_FMT(&td->loc_uri)); |
|
595 |
+ |
|
596 |
+ LM_DBG("rem_target: %.*s\n", STR_FMT(&td->rem_target)); |
|
597 |
+ LM_DBG("dst_uri: %.*s\n", STR_FMT(&td->dst_uri)); |
|
598 |
+ |
|
599 |
+ td->id.call_id = cell->callid; |
|
600 |
+ td->id.rem_tag = cell->tag[DLG_CALLER_LEG]; |
|
601 |
+ td->id.loc_tag = cell->tag[DLG_CALLEE_LEG]; |
|
602 |
+ |
|
603 |
+ td->state= DLG_EARLY; |
|
604 |
+ td->send_sock = cell->bind_addr[DLG_CALLER_LEG]; |
|
605 |
+ |
|
606 |
+ return td; |
|
607 |
+ |
|
608 |
+error: |
|
609 |
+ LM_ERR("Error occured creating early dialog\n"); |
|
610 |
+ free_tm_dlg(td); |
|
611 |
+ return NULL; |
|
612 |
+} |
|
613 |
+ |
|
614 |
+int dlg_request_within(struct sip_msg *msg, struct dlg_cell *dlg, int side, str * method, str * hdrs, str * content_type, str * content) |
|
615 |
+{ |
|
616 |
+ uac_req_t uac_r; |
|
617 |
+ dlg_t* dialog_info; |
|
618 |
+ int result; |
|
619 |
+ dlg_iuid_t *iuid = NULL; |
|
620 |
+ char rr_set_s[MAX_URI_SIZE]; |
|
621 |
+ str rr_set = {rr_set_s, 0}; |
|
622 |
+ str allheaders = {0, 0}; |
|
623 |
+ str content_type_hdr = {"Content-Type: ", 14}; |
|
624 |
+ int idx = 0; |
|
625 |
+ memset(rr_set_s, 0, 500); |
|
626 |
+ |
|
627 |
+ /* Special treatment for callee in early state*/ |
|
628 |
+ if (dlg->state != DLG_STATE_CONFIRMED_NA && dlg->state != DLG_STATE_CONFIRMED && side == DLG_CALLEE_LEG) { |
|
629 |
+ LM_DBG("Send request to callee in early state...\n"); |
|
630 |
+ |
|
631 |
+ if (dlg->t == NULL && d_tmb.t_gett) { |
|
632 |
+ dlg->t = d_tmb.t_gett(); |
|
633 |
+ if (dlg->t && dlg->t != T_UNDEFINED) |
|
634 |
+ idx = dlg->t->nr_of_outgoings; |
|
635 |
+ } |
|
636 |
+ LM_DBG("Branch %i\n", idx); |
|
637 |
+ |
|
638 |
+ /*verify direction*/ |
|
639 |
+ if ((dialog_info = build_dlg_t_early(msg, dlg, idx, &rr_set)) == 0){ |
|
640 |
+ LM_ERR("failed to create dlg_t\n"); |
|
641 |
+ goto err; |
|
642 |
+ } |
|
643 |
+ } else { |
|
644 |
+ LM_DBG("Send request to caller or in confirmed state...\n"); |
|
645 |
+ /*verify direction*/ |
|
646 |
+ if ((dialog_info = build_dlg_t(dlg, side)) == 0){ |
|
647 |
+ LM_ERR("failed to create dlg_t\n"); |
|
648 |
+ goto err; |
|
649 |
+ } |
|
650 |
+ } |
|
651 |
+ |
|
652 |
+ LM_DBG("sending %.*s to %s\n", method->len, method->s, (side==DLG_CALLER_LEG)?"caller":"callee"); |
|
653 |
+ |
|
654 |
+ iuid = dlg_get_iuid_shm_clone(dlg); |
|
655 |
+ if(iuid==NULL) |
|
656 |
+ { |
|
657 |
+ LM_ERR("failed to create dialog unique id clone\n"); |
|
658 |
+ goto err; |
|
659 |
+ } |
|
660 |
+ |
|
661 |
+ if (hdrs && hdrs->len > 0) { |
|
662 |
+ LM_DBG("Extra headers: %.*s\n", STR_FMT(hdrs)); |
|
663 |
+ allheaders.len += hdrs->len; |
|
664 |
+ } |
|
665 |
+ |
|
666 |
+ if (content_type && content_type->s && content && content->s) { |
|
667 |
+ LM_DBG("Content-Type: %.*s\n", STR_FMT(content_type)); |
|
668 |
+ allheaders.len += content_type_hdr.len + content_type->len + 2; |
|
669 |
+ } |
|
670 |
+ if (allheaders.len > 0) { |
|
671 |
+ allheaders.s = (char*)pkg_malloc(allheaders.len); |
|
672 |
+ if (allheaders.s == NULL) { |
|
673 |
+ PKG_MEM_ERROR; |
|
674 |
+ goto err; |
|
675 |
+ } |
|
676 |
+ allheaders.len = 0; |
|
677 |
+ if (hdrs && hdrs->len > 0) { |
|
678 |
+ memcpy(allheaders.s, hdrs->s, hdrs->len); |
|
679 |
+ allheaders.len += hdrs->len; |
|
680 |
+ } |
|
681 |
+ if (content_type && content_type->s && content && content->s) { |
|
682 |
+ memcpy(allheaders.s + allheaders.len, content_type_hdr.s, content_type_hdr.len); |
|
683 |
+ allheaders.len += content_type_hdr.len; |
|
684 |
+ memcpy(allheaders.s + allheaders.len, content_type->s, content_type->len); |
|
685 |
+ allheaders.len += content_type->len; |
|
686 |
+ memcpy(allheaders.s + allheaders.len, "\r\n", 2); |
|
687 |
+ allheaders.len += 2; |
|
688 |
+ } |
|
689 |
+ LM_DBG("All headers: %.*s\n", STR_FMT(&allheaders)); |
|
690 |
+ } |
|
691 |
+ |
|
692 |
+ set_uac_req(&uac_r, method, allheaders.len?&allheaders:NULL, (content && content->len)?content:NULL, dialog_info, TMCB_LOCAL_COMPLETED, |
|
693 |
+ bye_reply_cb, (void*)iuid); |
|
694 |
+ |
|
695 |
+ result = d_tmb.t_request_within(&uac_r); |
|
696 |
+ |
|
697 |
+ if (allheaders.s) |
|
698 |
+ pkg_free(allheaders.s); |
|
699 |
+ |
|
700 |
+ if(result < 0){ |
|
701 |
+ LM_ERR("failed to send request\n"); |
|
702 |
+ goto err; |
|
703 |
+ } |
|
704 |
+ |
|
705 |
+ free_tm_dlg(dialog_info); |
|
706 |
+ |
|
707 |
+ LM_DBG("%.*s sent to %s\n", method->len, method->s, (side==DLG_CALLER_LEG)?"caller":"callee"); |
|
708 |
+ |
|
709 |
+ return 0; |
|
710 |
+err: |
|
711 |
+ if(dialog_info) |
|
712 |
+ free_tm_dlg(dialog_info); |
|
713 |
+ return -1; |
|
714 |
+} |
|
441 | 715 |
|
442 | 716 |
/* send keep-alive |
443 | 717 |
* dlg - pointer to a struct dlg_cell |
... | ... |
@@ -52,5 +52,6 @@ int free_tm_dlg(dlg_t *td); |
52 | 52 |
int dlg_bye(struct dlg_cell *dlg, str *hdrs, int side); |
53 | 53 |
int dlg_bye_all(struct dlg_cell *dlg, str *hdrs); |
54 | 54 |
int dlg_send_ka(dlg_cell_t *dlg, int dir); |
55 |
+int dlg_request_within(struct sip_msg *msg, struct dlg_cell *dlg, int side, str * method, str * hdrs, str * content_type, str * content); |
|
55 | 56 |
|
56 | 57 |
#endif |
... | ... |
@@ -69,8 +69,8 @@ |
69 | 69 |
<holder>Voice Sistem SRL</holder> |
70 | 70 |
</copyright> |
71 | 71 |
<copyright> |
72 |
- <year>2011</year> |
|
73 |
- <holder>Carsten Bock, http://www.ng-voice.com</holder> |
|
72 |
+ <year>2011, 2022</year> |
|
73 |
+ <holder>ng-voice GmbH, Carsten Bock, http://www.ng-voice.com</holder> |
|
74 | 74 |
</copyright> |
75 | 75 |
</bookinfo> |
76 | 76 |
<toc></toc> |
... | ... |
@@ -1468,7 +1468,7 @@ modparam("dialog", "timer_procs", 1) |
1468 | 1468 |
</example> |
1469 | 1469 |
</section> |
1470 | 1470 |
|
1471 |
- <section> |
|
1471 |
+ <section id="dialog.p.enable_dmq"> |
|
1472 | 1472 |
<title><varname>enable_dmq</varname> (int)</title> |
1473 | 1473 |
<para> |
1474 | 1474 |
If set to 1, the dialog will be synced via dmq. |
... | ... |
@@ -1666,6 +1666,47 @@ modparam("dialog", "keep_proxy_rr", 1) |
1666 | 1666 |
</programlisting> |
1667 | 1667 |
</example> |
1668 | 1668 |
</section> |
1669 |
+ |
|
1670 |
+ <section id="dialog.p.bye_early_code"> |
|
1671 |
+ <title><varname>bye_early_code</varname> (int)</title> |
|
1672 |
+ <para> |
|
1673 |
+ This parameter defines the reply-code being used for |
|
1674 |
+ dialogs being terminated in early stage (e.g. before |
|
1675 |
+ 200 OK/ACK). |
|
1676 |
+ </para> |
|
1677 |
+ <emphasis> |
|
1678 |
+ Default value is <quote>480</quote>. |
|
1679 |
+ </emphasis> |
|
1680 |
+ <example> |
|
1681 |
+ <title>Set <varname>bye_early_code</varname> parameter</title> |
|
1682 |
+ <programlisting format="linespecific"> |
|
1683 |
+... |
|
1684 |
+modparam("dialog", "bye_early_code", 503) |
|
1685 |
+... |
|
1686 |
+</programlisting> |
|
1687 |
+ </example> |
|
1688 |
+ </section> |
|
1689 |
+ |
|
1690 |
+ <section id="dialog.p.bye_early_reason"> |
|
1691 |
+ <title><varname>bye_early_reason</varname> (string)</title> |
|
1692 |
+ <para> |
|
1693 |
+ This parameter defines the reply-reason being used for |
|
1694 |
+ dialogs being terminated in early stage (e.g. before |
|
1695 |
+ 200 OK/ACK). |
|
1696 |
+ </para> |
|
1697 |
+ <emphasis> |
|
1698 |
+ Default value is <quote>Temporarily Unavailable</quote>. |
|
1699 |
+ </emphasis> |
|
1700 |
+ <example> |
|
1701 |
+ <title>Set <varname>bye_early_reason</varname> parameter</title> |
|
1702 |
+ <programlisting format="linespecific"> |
|
1703 |
+... |
|
1704 |
+modparam("dialog", "bye_early_reason", "Call terminated") |
|
1705 |
+... |
|
1706 |
+</programlisting> |
|
1707 |
+ </example> |
|
1708 |
+ </section> |
|
1709 |
+ |
|
1669 | 1710 |
</section> |
1670 | 1711 |
|
1671 | 1712 |
<section> |
... | ... |
@@ -1936,7 +1977,9 @@ redlg_setflag("1"); |
1936 | 1977 |
<function moreinfo="none">dlg_bye(side)</function> |
1937 | 1978 |
</title> |
1938 | 1979 |
<para> |
1939 |
- Send BYE to both parties of a dialog. |
|
1980 |
+ Send BYE to parties of a dialog or - if in early stage - a CANCEL to the |
|
1981 |
+ B-Party and a SIP response to the A-Party (as defined in bye_early_code / |
|
1982 |
+ bye_early_reason). |
|
1940 | 1983 |
</para> |
1941 | 1984 |
<para>Meaning of the parameters is as follows:</para> |
1942 | 1985 |
<itemizedlist> |
... | ... |
@@ -2541,6 +2584,67 @@ dlg_reset_property("timeout-noreset"); |
2541 | 2584 |
</programlisting> |
2542 | 2585 |
</example> |
2543 | 2586 |
</section> |
2587 |
+ |
|
2588 |
+ <section id="dialog.f.dlg_req_within"> |
|
2589 |
+ <title> |
|
2590 |
+ <function moreinfo="none">dlg_req_within(side, method, [headers], [content_type, content])</function> |
|
2591 |
+ </title> |
|
2592 |
+ <para> |
|
2593 |
+ Sends a in-dialog SIP Request with method to a party of a dialog indicated by the side parameter. |
|
2594 |
+ </para> |
|
2595 |
+ <para>Meaning of the parameters is as follows:</para> |
|
2596 |
+ <itemizedlist> |
|
2597 |
+ <listitem> |
|
2598 |
+ <para> |
|
2599 |
+ <emphasis>side</emphasis> - where to send the request. It can be: |
|
2600 |
+ 'caller', 'callee', or 'all' (send to both sides). |
|
2601 |
+ </para> |
|
2602 |
+ </listitem> |
|
2603 |
+ <listitem> |
|
2604 |
+ <para> |
|
2605 |
+ <emphasis>method</emphasis> - Method of the request |
|
2606 |
+ </para> |
|
2607 |
+ </listitem> |
|
2608 |
+ <listitem> |
|
2609 |
+ <para> |
|
2610 |
+ <emphasis>headers</emphasis> (optional) - additional headers to be added to the request. |
|
2611 |
+ </para> |
|
2612 |
+ </listitem> |
|
2613 |
+ <listitem> |
|
2614 |
+ <para> |
|
2615 |
+ <emphasis>content_type</emphasis> (optional) - Content-Type of the request body - will |
|
2616 |
+ be added as Content-Type Header. |
|
2617 |
+ </para> |
|
2618 |
+ </listitem> |
|
2619 |
+ <listitem> |
|
2620 |
+ <para> |
|
2621 |
+ <emphasis>content</emphasis> (optional) - Content to be sent as body. |
|
2622 |
+ </para> |
|
2623 |
+ </listitem> |
|
2624 |
+ </itemizedlist> |
|
2625 |
+ <para> |
|
2626 |
+ This function can be used from ANY_ROUTE. |
|
2627 |
+ </para> |
|
2628 |
+ <example> |
|
2629 |
+ <title><function>dlg_req_within</function> usage</title> |
|
2630 |
+ <programlisting format="linespecific"> |
|
2631 |
+... |
|
2632 |
+ # Send a simple request: |
|
2633 |
+ dlg_req_within("all", "OPTIONS"); |
|
2634 |
+... |
|
2635 |
+ # Send a simple request with extra headers: |
|
2636 |
+ dlg_req_within("caller", "OPTIONS", "X-Info: Bandwidth granted\r\nX-Info-2: Go ahead\r\n"); |
|
2637 |
+... |
|
2638 |
+ # Send a simple request with body: |
|
2639 |
+ dlg_req_within("caller", "UPDATE", "application/sdp", "...some SDP..."); |
|
2640 |
+... |
|
2641 |
+ # Send a simple request with extra headers and body: |
|
2642 |
+ dlg_req_within("callee", "INFO", "X-Info: Bandwidth granted\r\n", "application/sdp", "...some SDP..."); |
|
2643 |
+... |
|
2644 |
+ </programlisting> |
|
2645 |
+ </example> |
|
2646 |
+ </section> |
|
2647 |
+ |
|
2544 | 2648 |
</section> |
2545 | 2649 |
|
2546 | 2650 |
|