added support for provisional responses while using t_uac_dlg.
authorRaphael Coeffic <rco@iptel.org>
Tue, 29 Nov 2005 14:48:50 +0000 (14:48 +0000)
committerRaphael Coeffic <rco@iptel.org>
Tue, 29 Nov 2005 14:48:50 +0000 (14:48 +0000)
added transaction relevant information on locally generated replies.

modules/tm/t_hooks.h
modules/tm/t_reply.c
modules/tm/tm.c
modules/tm/uac.c
modules/tm/uac.h
modules/tm/uac_fifo.c
modules/tm/uac_unixsock.c

index 73d8e15..cd1902a 100644 (file)
@@ -43,16 +43,17 @@ struct sip_msg;
 struct cell;
 
 
-#define TMCB_REQUEST_IN       (1<<0)
-#define TMCB_RESPONSE_IN      (1<<1)
-#define TMCB_E2EACK_IN        (1<<2)
-#define TMCB_REQUEST_FWDED    (1<<3)
-#define TMCB_RESPONSE_FWDED   (1<<4)
-#define TMCB_ON_FAILURE_RO    (1<<5)
-#define TMCB_ON_FAILURE       (1<<6)
-#define TMCB_RESPONSE_OUT     (1<<7)
-#define TMCB_LOCAL_COMPLETED  (1<<8)
-#define TMCB_MAX              ((1<<9)-1)
+#define TMCB_REQUEST_IN         (1<<0)
+#define TMCB_RESPONSE_IN        (1<<1)
+#define TMCB_E2EACK_IN          (1<<2)
+#define TMCB_REQUEST_FWDED      (1<<3)
+#define TMCB_RESPONSE_FWDED     (1<<4)
+#define TMCB_ON_FAILURE_RO      (1<<5)
+#define TMCB_ON_FAILURE         (1<<6)
+#define TMCB_RESPONSE_OUT       (1<<7)
+#define TMCB_LOCAL_COMPLETED    (1<<8)
+#define TMCB_LOCAL_RESPONSE_OUT (1<<9)
+#define TMCB_MAX                ((1<<10)-1)
 
 /* 
  *  Caution: most of the callbacks work with shmem-ized messages
index 4be7f8d..55bb66b 100644 (file)
@@ -98,6 +98,7 @@
 #include "t_fwd.h"
 #include "fix_lumps.h"
 #include "t_stats.h"
+#include "uac.h"
 
 
 /* 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,
                }
        }
        UNLOCK_REPLIES(t);
+        if (local_winner >= 0 && pass_provisional_replies && winning_code < 200) {
+                if (!totag_retr && has_tran_tmcbs(t, TMCB_LOCAL_RESPONSE_OUT) ) {
+                        DBG("DEBUG: Passing provisional reply %d to FIFO application\n", winning_code);
+                        run_trans_callbacks( TMCB_LOCAL_RESPONSE_OUT, t, 0,
+                                winning_msg, winning_code);
+                }
+        }
        if (local_winner>=0 && winning_code>=200 ) {
                DBG("DEBUG: local transaction completed\n");
                if (!totag_retr) {
index 1fe69c2..16223fe 100644 (file)
@@ -275,6 +275,7 @@ static param_export_t params[]={
        {"fr_timer_avp",        STR_PARAM, &fr_timer_param                       },
        {"fr_inv_timer_avp",    STR_PARAM, &fr_inv_timer_param                   },
        {"tw_append",           STR_PARAM|USE_FUNC_PARAM, (void*)parse_tw_append },
+        {"pass_provisional_replies", INT_PARAM, &pass_provisional_replies        },
        {0,0,0}
 };
 
index 48e3cc8..bb5321d 100644 (file)
@@ -75,6 +75,8 @@ static char from_tag[FROM_TAG_LEN + 1];
 
 char* uac_from = "sip:foo@foo.bar"; /* Module parameter */
 
+/* Enable/disable passing of provisional replies to FIFO applications */
+int pass_provisional_replies = 0;
 
 /*
  * Initialize UAC
@@ -164,15 +166,14 @@ static inline unsigned int dlg2hash( dlg_t* dlg )
  * Send a request using data from the dialog structure
  */
 int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
-                                                                                               transaction_cb cb, void* cbp)
+         transaction_cb cb, void* cbp)
 {
        struct socket_info* send_sock;
        union sockaddr_union to_su;
        struct cell *new_cell;
        struct retr_buf *request;
        char* buf;
-       int buf_len;
-       int ret;
+        int buf_len, ret, flags;
        unsigned int hi;
 
        ret=-1;
@@ -205,8 +206,13 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
        reset_user_avps();
 
        /* add the callback the the transaction for LOCAL_COMPLETED event */
-       if(cb && insert_tmcb(&(new_cell->tmcb_hl),TMCB_LOCAL_COMPLETED,cb,cbp)!=1){
-               ret=E_OUT_OF_MEM;
+        flags = TMCB_LOCAL_COMPLETED;
+             /* Add also TMCB_LOCAL_REPLY_OUT if provisional replies are desired */
+        if (pass_provisional_replies) flags |= TMCB_LOCAL_RESPONSE_OUT;
+        if(cb && insert_tmcb(&(new_cell->tmcb_hl), flags, cb, cbp)!=1){
+                ret=E_OUT_OF_MEM; 
                LOG(L_ERR, "t_uac: short of tmcb shmem\n");
                goto error2;
        }
index 8d61cc5..5936c73 100644 (file)
@@ -41,7 +41,7 @@
 #define DEFAULT_CSEQ 10 /* Default CSeq number */
 
 extern char *uac_from;  /* UAC From parameter */
-
+extern int pass_provisional_replies; /* Pass provisional replies to fifo applications */
 
 /*
  * Function prototypes
index 79cb662..09548a1 100644 (file)
@@ -568,7 +568,10 @@ static void fifo_callback( struct cell *t, int type, struct tmcb_params *ps )
        }
        DBG("DEBUG: fifo_callback successfully completed\n");
 done:
-       shm_free(filename);
+        if (ps->code >= 200) {
+               /* Do not free if we received provisional reply */
+                shm_free(filename);
+        }
 }
 
 
index bc545c3..97a4d7d 100644 (file)
@@ -50,6 +50,13 @@ struct str_list {
        struct str_list *next;
 };
 
+struct uac_cb_param {
+    
+    str from;
+    str callid;
+    str cseq;
+    struct sockaddr_un addr;
+};
 
 #define skip_hf(_hf) (             \
     ((_hf)->type == HDR_FROM_T)   || \
@@ -426,10 +433,67 @@ static int print_uris(struct sip_msg* reply)
        return 0;
 }
 
+static int new_uac_cb_param(struct uac_cb_param** param,
+                           struct sip_msg* msg, 
+                           struct sockaddr_un* addr)
+{
+    int len=0;
+    struct uac_cb_param* p_param=0;
+
+    if(msg && addr) {
+
+       *param = shm_malloc(sizeof(struct uac_cb_param));
+       if (!*param) {
+           unixsock_reply_asciiz("500 No shared memory");
+           return -1;
+       }
+       
+       p_param = *param;
+
+       len += msg->from->len;
+       len += msg->callid->len;
+       len += msg->cseq->len;
+
+       p_param->from.s = shm_malloc(len);
+       if(!p_param->from.s){
+
+           shm_free(p_param);
+           *param = 0;
+
+           unixsock_reply_asciiz("500 No shared memory");
+           return -1;
+       }
+
+       memcpy(p_param->from.s,msg->from->name.s,msg->from->len);
+       p_param->from.len = msg->from->len;
+
+       p_param->callid.s = p_param->from.s + p_param->from.len;
+       memcpy(p_param->callid.s,msg->callid->name.s,msg->callid->len);
+       p_param->callid.len = msg->callid->len;
+
+       p_param->cseq.s = p_param->callid.s + p_param->callid.len;
+       memcpy(p_param->cseq.s,msg->cseq->name.s,msg->cseq->len);
+       p_param->cseq.len = msg->cseq->len;
+
+       memcpy(&(p_param->addr), addr, sizeof(struct sockaddr_un));
+
+    } else {
+       *param = 0;
+    }
+    return 0;
+}
+
+static void free_uac_cb_param(struct uac_cb_param* param)
+{
+    shm_free(param->from.s);
+    shm_free(param);
+}
 
 static void callback(struct cell *t, int type, struct tmcb_params *ps)
 {
-       struct sockaddr_un* to;
+       struct sockaddr_un*  to;
+       struct uac_cb_param* param=0;
+
        str text;
 
        if (!*ps->param) {
@@ -437,7 +501,8 @@ static void callback(struct cell *t, int type, struct tmcb_params *ps)
                return;
        }
        
-       to = (struct sockaddr_un*)(*ps->param);
+       param = (struct uac_cb_param*)(*ps->param);
+       to = &param->addr;
        unixsock_reply_reset();
 
        if (ps->rpl == FAKED_REPLY) {
@@ -447,8 +512,15 @@ static void callback(struct cell *t, int type, struct tmcb_params *ps)
                        unixsock_reply_asciiz("500 callback: get_reply_status failed\n");
                        goto done;
                }
-               unixsock_reply_printf("%.*s\n", text.len, text.s);
+
+               unixsock_reply_printf("%.*s\n.\n.\n.\n", text.len, text.s);
+
+               unixsock_reply_printf("%.*s", param->from.len, param->from.s);
+               unixsock_reply_printf("%.*s", param->callid.len, param->callid.s);
+               unixsock_reply_printf("%.*s\n", param->cseq.len, param->cseq.s);
+
                pkg_free(text.s);
+
        } else {
                text.s = ps->rpl->first_line.u.reply.reason.s;
                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)
        }
 done:
        unixsock_reply_sendto(to);
-       shm_free(to);
-       *ps->param=0; /* 0 it so the callback won't do anything if called
-                                        for a retransmission */
+
+        if (ps->code >= 200) {
+
+           free_uac_cb_param(param);
+           *ps->param=0; /* 0 it so the callback won't do 
+                            anything if called for a retransmission */
+       }
 }
 
 
@@ -484,7 +560,6 @@ static int duplicate_addr(struct sockaddr_un** dest, struct sockaddr_un* addr)
        return 0;
 }
 
-
 int unixsock_uac(str* msg)
 {
        str method, ruri, nexthop, headers, body, hfb, callid;
@@ -493,6 +568,7 @@ int unixsock_uac(str* msg)
        int ret, sip_error, err_ret, fromtag, cseq_is, cseq;
        char err_buf[MAX_REASON_LEN];
        struct sockaddr_un* shm_sockaddr;
+       struct uac_cb_param* shm_param;
        dlg_t dlg;
 
        if (get_method(&method, msg) < 0) return -1;
@@ -551,10 +627,14 @@ int unixsock_uac(str* msg)
        dlg.hooks.request_uri = &ruri;
        dlg.hooks.next_hop = (nexthop.len ? &nexthop : &ruri);
        
-            /* we got it all, initiate transaction now! */
-       if (duplicate_addr(&shm_sockaddr, unixsock_sender_addr()) < 0) goto error01;
+       if (new_uac_cb_param(&shm_param,&faked_msg,unixsock_sender_addr()) < 0) {
+           
+           unixsock_reply_send();
+           goto error01;
+       }
 
-       ret = t_uac(&method, &hfb, &body, &dlg, callback, shm_sockaddr);
+            /* we got it all, initiate transaction now! */
+       ret = t_uac(&method, &hfb, &body, &dlg, callback, shm_param);
        if (ret <= 0) {
                err_ret = err2reason_phrase(ret, &sip_error, err_buf, sizeof(err_buf), "FIFO/UAC");
                if (err_ret > 0) {
@@ -563,7 +643,7 @@ int unixsock_uac(str* msg)
                        unixsock_reply_asciiz("500 UNIXSOCK/UAC error");
                }
                unixsock_reply_send();
-               shm_free(shm_sockaddr);
+               free_uac_cb_param(shm_param);
                goto error01;
        }