Function t_uac splitted into two parts - one which prepares the message and one
authorVaclav Kubart <vaclav.kubart@iptel.org>
Fri, 30 Jun 2006 13:04:18 +0000 (13:04 +0000)
committerVaclav Kubart <vaclav.kubart@iptel.org>
Fri, 30 Jun 2006 13:04:18 +0000 (13:04 +0000)
which sends it. Both are accessible for requests within dialogs through
tm_binds structure (prepare_request_within, send_prepared_request).

This is needed to allow sending in-dialog messages outside of critical section
(VERY useful for TCP transport when used nonzero TCP timeouts - in that case
may be the critical section locked for seconds!).

modules/tm/tm_load.c
modules/tm/tm_load.h
modules/tm/uac.c
modules/tm/uac.h

index 2730487..c516452 100644 (file)
@@ -158,7 +158,9 @@ int load_tm( struct tm_binds *tmb)
                LOG( L_ERR, LOAD_ERROR "'t_uac' not found\n");
                return -1;
        }
-
+       tmb->prepare_request_within = prepare_req_within;
+       tmb->send_prepared_request = send_prepared_request;
+       
        tmb->route_mode = &rmode;
        return 1;
 }
index 1bc501b..2179882 100644 (file)
@@ -100,6 +100,8 @@ struct tm_binds {
        tgett_f            t_gett;
        calculate_hooks_f  calculate_hooks;
        t_uac_t            t_uac;
+       prepare_request_within_f  prepare_request_within;
+       send_prepared_request_f   send_prepared_request;
        enum route_mode*   route_mode;
 };
 
index 7b54267..3ac3347 100644 (file)
@@ -164,11 +164,8 @@ static inline unsigned int dlg2hash( dlg_t* dlg )
        return hashid;
 }
 
-/*
- * 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)
+static inline int t_uac_prepare(str* method, str* headers, str* body, dlg_t* dialog,
+         transaction_cb cb, void* cbp, struct retr_buf **dst_req)
 {
        struct dest_info dst;
        struct cell *new_cell;
@@ -178,6 +175,7 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
        unsigned int hi;
 
        ret=-1;
+       /*if (dst_req) *dst_req = NULL;*/
        
        /*** added by dcm 
         * - needed by external ua to send a request within a dlg
@@ -216,12 +214,12 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 
        /* add the callback the the transaction for LOCAL_COMPLETED event */
  
-        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; 
+       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;
        }
@@ -255,14 +253,7 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
        request->buffer_len = buf_len;
        new_cell->nr_of_outgoings++;
        
-       if (SEND_BUFFER(request) == -1) {
-               LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", 
-                       dialog->hooks.next_hop->len,
-                       dialog->hooks.next_hop->s);
-       }
-       
-       if (start_retr(request)!=0)
-               LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
+       if (dst_req) *dst_req = request;
        return 1;
 
  error1:
@@ -274,6 +265,66 @@ error2:
        return ret;
 }
 
+/*
+ * Prepare a message within a dialog
+ */
+int prepare_req_within(str* method, str* headers, 
+               str* body, dlg_t* dialog, transaction_cb completion_cb, 
+               void* cbp, struct retr_buf **dst_req)
+{
+       if (!method || !dialog) {
+               LOG(L_ERR, "req_within: Invalid parameter value\n");
+               goto err;
+       }
+
+       if (dialog->state != DLG_CONFIRMED) {
+               LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");
+               goto err;
+       }
+
+       if ((method->len == 3) && (!memcmp("ACK", method->s, 3))) goto send;
+       if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
+       dialog->loc_seq.value++; /* Increment CSeq */
+ send:
+       return t_uac_prepare(method, headers, body, dialog, completion_cb, cbp, dst_req);
+
+ err:
+       /* if (cbp) shm_free(cbp); */
+       /* !! never free cbp here because if t_uac_prepare fails, cbp is not freed
+        * and thus caller has no chance to discover if it is freed or not !! */
+       return -1;
+}
+
+static inline void send_prepared_request_impl(struct retr_buf *request)
+{
+       if (SEND_BUFFER(request) == -1) {
+               LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
+       }
+       
+       if (start_retr(request)!=0)
+               LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
+}
+
+void send_prepared_request(struct retr_buf *request)
+{
+       send_prepared_request_impl(request);
+}
+
+/*
+ * 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)
+{
+       struct retr_buf *request;
+       int ret;
+
+       ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request);
+       if (ret < 0) return ret;
+       send_prepared_request_impl(request);
+       return ret;
+}
+
 
 /*
  * Send a message within a dialog
index 39051bf..b503203 100644 (file)
@@ -37,6 +37,7 @@
 #include "../../str.h"
 #include "dlg.h"
 #include "t_hooks.h"
+#include "h_table.h"
 
 #define DEFAULT_CSEQ 10 /* Default CSeq number */
 
@@ -50,6 +51,10 @@ typedef int (*reqwith_t)(str* m, str* h, str* b, dlg_t* d, transaction_cb c, voi
 typedef int (*reqout_t)(str* m, str* t, str* f, str* h, str* b, dlg_t** d, transaction_cb c, void* cp);
 typedef int (*req_t)(str* m, str* ruri, str* t, str* f, str* h, str* b, str *next_hop, transaction_cb c, void* cp);
 typedef int (*t_uac_t)(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp);
+typedef int (*prepare_request_within_f)(str* method, str* headers, 
+               str* body, dlg_t* dialog, transaction_cb cb, void* cbp,
+               struct retr_buf **request_dst);
+typedef void (*send_prepared_request_f)(struct retr_buf *request_dst);
 
 
 /*
@@ -86,5 +91,10 @@ int req_outside(str* m, str* t, str* f, str* h, str* b, dlg_t** d, transaction_c
  */
 int request(str* m, str* ruri, str* to, str* from, str* h, str* b, str *next_hop, transaction_cb c, void* cp);
 
+int prepare_req_within(str* method, str* headers, str* body, dlg_t* dialog,
+         transaction_cb cb, void* cbp, struct retr_buf **dst_req);
+
+void send_prepared_request(struct retr_buf *request);
+
 
 #endif