... | ... |
@@ -43,16 +43,17 @@ struct sip_msg; |
43 | 43 |
struct cell; |
44 | 44 |
|
45 | 45 |
|
46 |
-#define TMCB_REQUEST_IN (1<<0) |
|
47 |
-#define TMCB_RESPONSE_IN (1<<1) |
|
48 |
-#define TMCB_E2EACK_IN (1<<2) |
|
49 |
-#define TMCB_REQUEST_FWDED (1<<3) |
|
50 |
-#define TMCB_RESPONSE_FWDED (1<<4) |
|
51 |
-#define TMCB_ON_FAILURE_RO (1<<5) |
|
52 |
-#define TMCB_ON_FAILURE (1<<6) |
|
53 |
-#define TMCB_RESPONSE_OUT (1<<7) |
|
54 |
-#define TMCB_LOCAL_COMPLETED (1<<8) |
|
55 |
-#define TMCB_MAX ((1<<9)-1) |
|
46 |
+#define TMCB_REQUEST_IN (1<<0) |
|
47 |
+#define TMCB_RESPONSE_IN (1<<1) |
|
48 |
+#define TMCB_E2EACK_IN (1<<2) |
|
49 |
+#define TMCB_REQUEST_FWDED (1<<3) |
|
50 |
+#define TMCB_RESPONSE_FWDED (1<<4) |
|
51 |
+#define TMCB_ON_FAILURE_RO (1<<5) |
|
52 |
+#define TMCB_ON_FAILURE (1<<6) |
|
53 |
+#define TMCB_RESPONSE_OUT (1<<7) |
|
54 |
+#define TMCB_LOCAL_COMPLETED (1<<8) |
|
55 |
+#define TMCB_LOCAL_RESPONSE_OUT (1<<9) |
|
56 |
+#define TMCB_MAX ((1<<10)-1) |
|
56 | 57 |
|
57 | 58 |
/* |
58 | 59 |
* Caution: most of the callbacks work with shmem-ized messages |
... | ... |
@@ -98,6 +98,7 @@ |
98 | 98 |
#include "t_fwd.h" |
99 | 99 |
#include "fix_lumps.h" |
100 | 100 |
#include "t_stats.h" |
101 |
+#include "uac.h" |
|
101 | 102 |
|
102 | 103 |
|
103 | 104 |
/* restart fr timer on each provisional reply, default yes */ |
... | ... |
@@ -1213,6 +1214,15 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
1213 | 1214 |
} |
1214 | 1215 |
} |
1215 | 1216 |
UNLOCK_REPLIES(t); |
1217 |
+ |
|
1218 |
+ if (local_winner >= 0 && pass_provisional_replies && winning_code < 200) { |
|
1219 |
+ if (!totag_retr && has_tran_tmcbs(t, TMCB_LOCAL_RESPONSE_OUT) ) { |
|
1220 |
+ DBG("DEBUG: Passing provisional reply %d to FIFO application\n", winning_code); |
|
1221 |
+ run_trans_callbacks( TMCB_LOCAL_RESPONSE_OUT, t, 0, |
|
1222 |
+ winning_msg, winning_code); |
|
1223 |
+ } |
|
1224 |
+ } |
|
1225 |
+ |
|
1216 | 1226 |
if (local_winner>=0 && winning_code>=200 ) { |
1217 | 1227 |
DBG("DEBUG: local transaction completed\n"); |
1218 | 1228 |
if (!totag_retr) { |
... | ... |
@@ -275,6 +275,7 @@ static param_export_t params[]={ |
275 | 275 |
{"fr_timer_avp", STR_PARAM, &fr_timer_param }, |
276 | 276 |
{"fr_inv_timer_avp", STR_PARAM, &fr_inv_timer_param }, |
277 | 277 |
{"tw_append", STR_PARAM|USE_FUNC_PARAM, (void*)parse_tw_append }, |
278 |
+ {"pass_provisional_replies", INT_PARAM, &pass_provisional_replies }, |
|
278 | 279 |
{0,0,0} |
279 | 280 |
}; |
280 | 281 |
|
... | ... |
@@ -75,6 +75,8 @@ static char from_tag[FROM_TAG_LEN + 1]; |
75 | 75 |
|
76 | 76 |
char* uac_from = "sip:foo@foo.bar"; /* Module parameter */ |
77 | 77 |
|
78 |
+/* Enable/disable passing of provisional replies to FIFO applications */ |
|
79 |
+int pass_provisional_replies = 0; |
|
78 | 80 |
|
79 | 81 |
/* |
80 | 82 |
* Initialize UAC |
... | ... |
@@ -164,15 +166,14 @@ static inline unsigned int dlg2hash( dlg_t* dlg ) |
164 | 166 |
* Send a request using data from the dialog structure |
165 | 167 |
*/ |
166 | 168 |
int t_uac(str* method, str* headers, str* body, dlg_t* dialog, |
167 |
- transaction_cb cb, void* cbp) |
|
169 |
+ transaction_cb cb, void* cbp) |
|
168 | 170 |
{ |
169 | 171 |
struct socket_info* send_sock; |
170 | 172 |
union sockaddr_union to_su; |
171 | 173 |
struct cell *new_cell; |
172 | 174 |
struct retr_buf *request; |
173 | 175 |
char* buf; |
174 |
- int buf_len; |
|
175 |
- int ret; |
|
176 |
+ int buf_len, ret, flags; |
|
176 | 177 |
unsigned int hi; |
177 | 178 |
|
178 | 179 |
ret=-1; |
... | ... |
@@ -205,8 +206,13 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, |
205 | 206 |
reset_user_avps(); |
206 | 207 |
|
207 | 208 |
/* add the callback the the transaction for LOCAL_COMPLETED event */ |
208 |
- if(cb && insert_tmcb(&(new_cell->tmcb_hl),TMCB_LOCAL_COMPLETED,cb,cbp)!=1){ |
|
209 |
- ret=E_OUT_OF_MEM; |
|
209 |
+ |
|
210 |
+ flags = TMCB_LOCAL_COMPLETED; |
|
211 |
+ /* Add also TMCB_LOCAL_REPLY_OUT if provisional replies are desired */ |
|
212 |
+ if (pass_provisional_replies) flags |= TMCB_LOCAL_RESPONSE_OUT; |
|
213 |
+ |
|
214 |
+ if(cb && insert_tmcb(&(new_cell->tmcb_hl), flags, cb, cbp)!=1){ |
|
215 |
+ ret=E_OUT_OF_MEM; |
|
210 | 216 |
LOG(L_ERR, "t_uac: short of tmcb shmem\n"); |
211 | 217 |
goto error2; |
212 | 218 |
} |
... | ... |
@@ -568,7 +568,10 @@ static void fifo_callback( struct cell *t, int type, struct tmcb_params *ps ) |
568 | 568 |
} |
569 | 569 |
DBG("DEBUG: fifo_callback successfully completed\n"); |
570 | 570 |
done: |
571 |
- shm_free(filename); |
|
571 |
+ if (ps->code >= 200) { |
|
572 |
+ /* Do not free if we received provisional reply */ |
|
573 |
+ shm_free(filename); |
|
574 |
+ } |
|
572 | 575 |
} |
573 | 576 |
|
574 | 577 |
|
... | ... |
@@ -50,6 +50,13 @@ struct str_list { |
50 | 50 |
struct str_list *next; |
51 | 51 |
}; |
52 | 52 |
|
53 |
+struct uac_cb_param { |
|
54 |
+ |
|
55 |
+ str from; |
|
56 |
+ str callid; |
|
57 |
+ str cseq; |
|
58 |
+ struct sockaddr_un addr; |
|
59 |
+}; |
|
53 | 60 |
|
54 | 61 |
#define skip_hf(_hf) ( \ |
55 | 62 |
((_hf)->type == HDR_FROM_T) || \ |
... | ... |
@@ -426,10 +433,67 @@ static int print_uris(struct sip_msg* reply) |
426 | 433 |
return 0; |
427 | 434 |
} |
428 | 435 |
|
436 |
+static int new_uac_cb_param(struct uac_cb_param** param, |
|
437 |
+ struct sip_msg* msg, |
|
438 |
+ struct sockaddr_un* addr) |
|
439 |
+{ |
|
440 |
+ int len=0; |
|
441 |
+ struct uac_cb_param* p_param=0; |
|
442 |
+ |
|
443 |
+ if(msg && addr) { |
|
444 |
+ |
|
445 |
+ *param = shm_malloc(sizeof(struct uac_cb_param)); |
|
446 |
+ if (!*param) { |
|
447 |
+ unixsock_reply_asciiz("500 No shared memory"); |
|
448 |
+ return -1; |
|
449 |
+ } |
|
450 |
+ |
|
451 |
+ p_param = *param; |
|
452 |
+ |
|
453 |
+ len += msg->from->len; |
|
454 |
+ len += msg->callid->len; |
|
455 |
+ len += msg->cseq->len; |
|
456 |
+ |
|
457 |
+ p_param->from.s = shm_malloc(len); |
|
458 |
+ if(!p_param->from.s){ |
|
459 |
+ |
|
460 |
+ shm_free(p_param); |
|
461 |
+ *param = 0; |
|
462 |
+ |
|
463 |
+ unixsock_reply_asciiz("500 No shared memory"); |
|
464 |
+ return -1; |
|
465 |
+ } |
|
466 |
+ |
|
467 |
+ memcpy(p_param->from.s,msg->from->name.s,msg->from->len); |
|
468 |
+ p_param->from.len = msg->from->len; |
|
469 |
+ |
|
470 |
+ p_param->callid.s = p_param->from.s + p_param->from.len; |
|
471 |
+ memcpy(p_param->callid.s,msg->callid->name.s,msg->callid->len); |
|
472 |
+ p_param->callid.len = msg->callid->len; |
|
473 |
+ |
|
474 |
+ p_param->cseq.s = p_param->callid.s + p_param->callid.len; |
|
475 |
+ memcpy(p_param->cseq.s,msg->cseq->name.s,msg->cseq->len); |
|
476 |
+ p_param->cseq.len = msg->cseq->len; |
|
477 |
+ |
|
478 |
+ memcpy(&(p_param->addr), addr, sizeof(struct sockaddr_un)); |
|
479 |
+ |
|
480 |
+ } else { |
|
481 |
+ *param = 0; |
|
482 |
+ } |
|
483 |
+ return 0; |
|
484 |
+} |
|
485 |
+ |
|
486 |
+static void free_uac_cb_param(struct uac_cb_param* param) |
|
487 |
+{ |
|
488 |
+ shm_free(param->from.s); |
|
489 |
+ shm_free(param); |
|
490 |
+} |
|
429 | 491 |
|
430 | 492 |
static void callback(struct cell *t, int type, struct tmcb_params *ps) |
431 | 493 |
{ |
432 |
- struct sockaddr_un* to; |
|
494 |
+ struct sockaddr_un* to; |
|
495 |
+ struct uac_cb_param* param=0; |
|
496 |
+ |
|
433 | 497 |
str text; |
434 | 498 |
|
435 | 499 |
if (!*ps->param) { |
... | ... |
@@ -437,7 +501,8 @@ static void callback(struct cell *t, int type, struct tmcb_params *ps) |
437 | 501 |
return; |
438 | 502 |
} |
439 | 503 |
|
440 |
- to = (struct sockaddr_un*)(*ps->param); |
|
504 |
+ param = (struct uac_cb_param*)(*ps->param); |
|
505 |
+ to = ¶m->addr; |
|
441 | 506 |
unixsock_reply_reset(); |
442 | 507 |
|
443 | 508 |
if (ps->rpl == FAKED_REPLY) { |
... | ... |
@@ -447,8 +512,15 @@ static void callback(struct cell *t, int type, struct tmcb_params *ps) |
447 | 512 |
unixsock_reply_asciiz("500 callback: get_reply_status failed\n"); |
448 | 513 |
goto done; |
449 | 514 |
} |
450 |
- unixsock_reply_printf("%.*s\n", text.len, text.s); |
|
515 |
+ |
|
516 |
+ unixsock_reply_printf("%.*s\n.\n.\n.\n", text.len, text.s); |
|
517 |
+ |
|
518 |
+ unixsock_reply_printf("%.*s", param->from.len, param->from.s); |
|
519 |
+ unixsock_reply_printf("%.*s", param->callid.len, param->callid.s); |
|
520 |
+ unixsock_reply_printf("%.*s\n", param->cseq.len, param->cseq.s); |
|
521 |
+ |
|
451 | 522 |
pkg_free(text.s); |
523 |
+ |
|
452 | 524 |
} else { |
453 | 525 |
text.s = ps->rpl->first_line.u.reply.reason.s; |
454 | 526 |
text.len = ps->rpl->first_line.u.reply.reason.len; |
... | ... |
@@ -460,9 +532,13 @@ static void callback(struct cell *t, int type, struct tmcb_params *ps) |
460 | 532 |
} |
461 | 533 |
done: |
462 | 534 |
unixsock_reply_sendto(to); |
463 |
- shm_free(to); |
|
464 |
- *ps->param=0; /* 0 it so the callback won't do anything if called |
|
465 |
- for a retransmission */ |
|
535 |
+ |
|
536 |
+ if (ps->code >= 200) { |
|
537 |
+ |
|
538 |
+ free_uac_cb_param(param); |
|
539 |
+ *ps->param=0; /* 0 it so the callback won't do |
|
540 |
+ anything if called for a retransmission */ |
|
541 |
+ } |
|
466 | 542 |
} |
467 | 543 |
|
468 | 544 |
|
... | ... |
@@ -484,7 +560,6 @@ static int duplicate_addr(struct sockaddr_un** dest, struct sockaddr_un* addr) |
484 | 560 |
return 0; |
485 | 561 |
} |
486 | 562 |
|
487 |
- |
|
488 | 563 |
int unixsock_uac(str* msg) |
489 | 564 |
{ |
490 | 565 |
str method, ruri, nexthop, headers, body, hfb, callid; |
... | ... |
@@ -493,6 +568,7 @@ int unixsock_uac(str* msg) |
493 | 568 |
int ret, sip_error, err_ret, fromtag, cseq_is, cseq; |
494 | 569 |
char err_buf[MAX_REASON_LEN]; |
495 | 570 |
struct sockaddr_un* shm_sockaddr; |
571 |
+ struct uac_cb_param* shm_param; |
|
496 | 572 |
dlg_t dlg; |
497 | 573 |
|
498 | 574 |
if (get_method(&method, msg) < 0) return -1; |
... | ... |
@@ -551,10 +627,14 @@ int unixsock_uac(str* msg) |
551 | 627 |
dlg.hooks.request_uri = &ruri; |
552 | 628 |
dlg.hooks.next_hop = (nexthop.len ? &nexthop : &ruri); |
553 | 629 |
|
554 |
- /* we got it all, initiate transaction now! */ |
|
555 |
- if (duplicate_addr(&shm_sockaddr, unixsock_sender_addr()) < 0) goto error01; |
|
630 |
+ if (new_uac_cb_param(&shm_param,&faked_msg,unixsock_sender_addr()) < 0) { |
|
631 |
+ |
|
632 |
+ unixsock_reply_send(); |
|
633 |
+ goto error01; |
|
634 |
+ } |
|
556 | 635 |
|
557 |
- ret = t_uac(&method, &hfb, &body, &dlg, callback, shm_sockaddr); |
|
636 |
+ /* we got it all, initiate transaction now! */ |
|
637 |
+ ret = t_uac(&method, &hfb, &body, &dlg, callback, shm_param); |
|
558 | 638 |
if (ret <= 0) { |
559 | 639 |
err_ret = err2reason_phrase(ret, &sip_error, err_buf, sizeof(err_buf), "FIFO/UAC"); |
560 | 640 |
if (err_ret > 0) { |
... | ... |
@@ -563,7 +643,7 @@ int unixsock_uac(str* msg) |
563 | 643 |
unixsock_reply_asciiz("500 UNIXSOCK/UAC error"); |
564 | 644 |
} |
565 | 645 |
unixsock_reply_send(); |
566 |
- shm_free(shm_sockaddr); |
|
646 |
+ free_uac_cb_param(shm_param); |
|
567 | 647 |
goto error01; |
568 | 648 |
} |
569 | 649 |
|