Implemented t_uac_dlg and build_uac_request_dlg. These functions are more
authorJan Janak <jan@iptel.org>
Sat, 7 Dec 2002 20:09:51 +0000 (20:09 +0000)
committerJan Janak <jan@iptel.org>
Sat, 7 Dec 2002 20:09:51 +0000 (20:09 +0000)
generic variants of t_uac and build_uac_request. They can send a message
within or out of a dialog, depends on value of parameters.

If stable and working, these functions can become new t_uac and
build_uac_request in the future if Jiri agrees.

modules/tm/t_msgbuilder.c
modules/tm/t_msgbuilder.h
modules/tm/uac.c
modules/tm/uac.h

index 03f3bb0..e50f643 100644 (file)
@@ -317,6 +317,174 @@ error:
 }
 
 
+char *build_uac_request_dlg(str* msg,           /* Method */
+                           str* ruri,          /* Request-URI */
+                           str* to,            /* To */
+                           str* from,          /* From */
+                           str* totag,         /* To header tag */
+                           str* fromtag,       /* From header tag */
+                           unsigned int cseq,  /* CSeq number */
+                           str* callid,        /* Call-ID */
+                           str* headers,       /* Headers to be appended */
+                           str* body,          /* Body of the message */
+                           int branch,         /* Branch */
+                           struct cell *t,     
+                           unsigned int *len)
+{
+       char *via, *buf, *w, content_len[10], cseq_str[10], branch_buf[MAX_BRANCH_PARAM_LEN];
+       int content_len_len, cseq_str_len, branch_len;
+       unsigned int via_len;
+
+       buf=0;
+       content_len_len = 0; /* Makes gcc happy */
+
+            /* 
+             * Print Content-Length
+             */
+       if (body) {
+               content_len_len = snprintf(content_len, sizeof(content_len), "%d", body->len);
+               if (content_len_len == -1) {
+                       LOG(L_ERR, "ERROR: build_uac_request_dlg: content_len too big\n");
+                       return 0;
+               }
+       }
+       
+            /* 
+             * Print CSeq 
+             */
+       cseq_str_len = snprintf(cseq_str, sizeof(cseq_str), "%d", cseq);
+       if (cseq_str_len == -1) {
+               LOG(L_ERR, "ERROR: build_uac_request_dlg: cseq too big\n");
+               return 0;
+       }
+       
+       *len = msg->len + 1 + ruri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
+
+       if (!t_calc_branch(t, branch, branch_buf, &branch_len)) {
+               LOG(L_ERR, "ERROR: build_uac_request_dlg: branch calculation failed\n");
+               goto error;
+       }
+
+       via = via_builder(&via_len, t->uac[branch].request.send_sock, branch_buf, branch_len);
+       if (!via) {
+               LOG(L_ERR, "ERROR: build_uac_request_dlg: via building failed\n");
+               goto error;
+       }
+       
+       *len += via_len;
+       
+       /* header names and separators */
+       *len +=   TO_LEN + CRLF_LEN
+               + FROM_LEN + CRLF_LEN
+               + CSEQ_LEN + CRLF_LEN
+               + CALLID_LEN + CRLF_LEN
+               + ((body) ? (CONTENT_LENGTH_LEN + CRLF_LEN) : 0)
+               + (server_signature ? USER_AGENT_LEN + CRLF_LEN : 0)
+               + CRLF_LEN; /* EoM */
+       
+            /* header field value and body length */
+       *len +=   to->len + ((totag) ? (TOTAG_LEN + totag->len) : 0) /* To */
+               + from->len + FROMTAG_LEN + fromtag->len             /* From */
+               + cseq_str_len + 1 + msg->len                        /* CSeq */
+               + callid->len                                        /* Call-ID */
+               + ((body) ? (content_len_len) : 0)                   /* Content-Length */
+               + ((headers) ? (headers->len) : 0)                   /* Headers */
+               + ((body) ? (body->len) : 0);                        /* Body */
+       
+       buf = shm_malloc(*len + 1);
+       if (!buf) {
+               LOG(L_ERR, "ERROR: build_uac_request_dlg: no shmem\n");
+               goto error1;
+       }
+       
+       w = buf;
+
+            /* First line */
+       memapp(w, msg->s, msg->len); 
+       memapp(w, " ", 1); 
+
+       t->uac[branch].uri.s = w; 
+       t->uac[branch].uri.len = ruri->len;
+
+       memapp(w, ruri->s, ruri->len); 
+       memapp(w, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
+
+            /* First Via */
+       memapp(w, via, via_len);
+
+            /* To */
+       t->to.s = w;
+       t->to.len = TO_LEN + to->len + ((totag) ? (TOTAG_LEN + totag->len) : 0);
+
+       memapp(w, TO, TO_LEN);
+       memapp(w, to->s, to->len);
+       if (totag) {
+               memapp(w, TOTAG, TOTAG_LEN);
+               memapp(w, totag->s, totag->len);
+       }
+       memapp(w, CRLF, CRLF_LEN);
+
+            /* From */
+       t->from.s = w;
+       t->from.len = FROM_LEN + from->len + FROMTAG_LEN + fromtag->len;
+
+       memapp(w, FROM, FROM_LEN);
+       memapp(w, from->s, from->len);
+       memapp(w, FROMTAG, FROMTAG_LEN);
+       memapp(w, fromtag->s, fromtag->len);
+       memapp(w, CRLF, CRLF_LEN);
+       
+            /* CSeq */
+       t->cseq_n.s = w; 
+       t->cseq_n.len = CSEQ_LEN + cseq_str_len;
+
+       memapp(w, CSEQ, CSEQ_LEN);
+       memapp(w, cseq_str, cseq_str_len);
+       memapp(w, " ", 1);
+       memapp(w, msg->s, msg->len);
+
+            /* Call-ID */
+       t->callid.s = w + CRLF_LEN; 
+       t->callid.len = callid->len;
+       memapp(w, CRLF CALLID, CRLF_LEN + CALLID_LEN);
+       memapp(w, callid->s, callid->len);
+
+            /* Content-Length */
+       if (body) {
+               memapp(w, CRLF CONTENT_LENGTH, CRLF_LEN + CONTENT_LENGTH_LEN);
+               memapp(w, content_len, content_len_len);
+               memapp(w, CRLF, CRLF_LEN);
+       }
+       
+            /* Server signature */
+       if (server_signature) {
+               memapp(w, USER_AGENT CRLF, USER_AGENT_LEN + CRLF_LEN);
+       }
+
+            /* Headers */
+       if (headers) {
+               memapp(w, headers->s, headers->len);
+       }
+
+            /* EoH */
+       memapp(w, CRLF, CRLF_LEN);
+       
+            /* Body */
+       if (body) {
+               memapp(w, body->s, body->len);
+       }
+
+#ifdef EXTRA_DEBUG
+       if (w-buf != *len ) abort();
+#endif
+       
+ error1:
+       pkg_free(via);  
+ error:
+       return buf;
+}
+
+
 int t_calc_branch(struct cell *t, 
        int b, char *branch, int *branch_len)
 {
index 5f7c8f6..63d40c1 100644 (file)
@@ -40,6 +40,8 @@
 #define FROM_LEN (sizeof(FROM)-1)
 #define FROMTAG ";tag="
 #define FROMTAG_LEN (sizeof(FROMTAG)-1)
+#define TOTAG ";tag="
+#define TOTAG_LEN (sizeof(TOTAG)-1)
 
 #ifdef _OBSOLETED
 #define UAC_CSEQNR "1"
@@ -78,6 +80,23 @@ char *build_uac_request(  str msg_type, str dst, str from,
        str body, int branch,
        struct cell *t, unsigned int *len);
 
+
+char *build_uac_request_dlg(str* msg,            /* Method */
+                           str* ruri,           /* Request-URI */
+                           str* to,             /* To header field w/o tag */
+                           str* from,           /* From header field w/o tag */
+                           str* totag,          /* To tag */
+                           str* fromtag,        /* From tag */
+                           unsigned int cseq,  /* CSeq number */
+                           str* callid,         /* Call-ID */
+                           str* headers,        /* Headers to be appended including CRLF */
+                           str* body,           /* Body of the message */
+                           int branch,         /* Branch */
+                           struct cell *t,
+                           unsigned int *len
+                          );
+
+
 int t_calc_branch(struct cell *t,
        int b, char *branch, int *branch_len);
 
index 86e7e36..5f6b49c 100644 (file)
@@ -42,6 +42,7 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <limits.h>
+#include <string.h>
 #include "../../dprint.h"
 #include "../../ut.h"
 #include "../../hash_func.h"
@@ -83,6 +84,8 @@ static char callid[CALLID_NR_LEN+CALLID_SUFFIX_LEN];
 
 char *uac_from="\"UAC Account\" <sip:uac@dev.null:9>";
 
+str uac_from_str;
+
 static char from_tag[ FROM_TAG_LEN+1 ];
 
 
@@ -144,6 +147,9 @@ int uac_init() {
        MDStringArray( from_tag, src, 3 );
        from_tag[MD5_LEN]=CID_SEP;
 
+       uac_from_str.s = uac_from;
+       uac_from_str.len = strlen(uac_from);
+
        return 1;
 }
 
@@ -297,6 +303,166 @@ done:
        return ser_error=ret;
 }
 
+
+/*
+ * Send a request within a dialog
+ */
+int t_uac_dlg(str* msg,                     /* Type of the message - MESSAGE, OPTIONS etc. */
+             str* dst,                     /* Real destination (can be different than R-URI) */
+             str* ruri,                    /* Request-URI */
+             str* to,                      /* To - w/o tag*/
+             str* from,                    /* From - w/o tag*/
+             str* totag,                   /* To tag */
+             str* fromtag,                 /* From tag */
+             int* cseq,                    /* Variable holding CSeq */
+             str* cid,                     /* Call-ID */
+             str* headers,                 /* Optional headers including CRLF */
+             str* body,                    /* Message body */
+             transaction_cb completion_cb, /* Callback parameter */
+             void* cbp                     /* Callback pointer */
+             )
+{
+
+       int r, branch, ret;
+       unsigned int req_len;
+       char *buf;
+       struct cell *new_cell;
+       struct proxy_l *proxy;
+       union sockaddr_union to_su;
+       struct socket_info* send_sock;
+       struct retr_buf *request;
+       str callid_s, ftag, tmp;
+
+       /* make -Wall shut up */
+       ret=0;
+
+       proxy = uri2proxy((dst) ? (dst) : ((ruri) ? (ruri) : (to)));
+       if (proxy == 0) {
+               ser_error = ret = E_BAD_ADDRESS;
+               LOG(L_ERR, "ERROR: t_uac_dlg: Can't create a dst proxy\n");
+               goto done;
+       }
+
+       branch=0;
+       hostent2su(&to_su, &proxy->host, proxy->addr_idx, (proxy->port) ? htons(proxy->port) : htons(SIP_PORT));
+       send_sock=get_send_socket(&to_su);
+       if (send_sock == 0) {
+               LOG(L_ERR, "ERROR: t_uac_dlg: no corresponding listening socket for af %d\n", to_su.s.sa_family );
+               ret = E_NO_SOCKET;
+               goto error00;
+       }
+       
+            /* No Call-ID given, calculate it */
+       if (cid == 0) {
+               callid_nr++;
+               r = snprintf(callid, rand_len + 1, "%0*lx", rand_len, callid_nr);
+               if (r == -1) {
+                       LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
+                       goto error00;
+               }
+
+                    /* fix the ZT 0 */
+               callid[rand_len] = CID_SEP;
+               callid_s.s = callid;
+               callid_s.len = rand_len + callid_suffix_len;
+       }
+
+       new_cell = build_cell(0); 
+       if (!new_cell) {
+               ret = E_OUT_OF_MEM;
+               LOG(L_ERR, "ERROR: t_uac: short of cell shmem\n");
+               goto error00;
+       }
+
+       new_cell->completion_cb = completion_cb;
+       new_cell->cbp = cbp;
+
+       /* cbp is installed -- tell error handling bellow not to free it */
+       cbp = 0;
+
+       new_cell->is_invite = msg->len == INVITE_LEN && memcmp(msg->s, INVITE, INVITE_LEN) == 0;
+       new_cell->local= 1 ;
+       new_cell->kr = REQ_FWDED;
+
+       request = &new_cell->uac[branch].request;
+       request->to = to_su;
+       request->send_sock = send_sock;
+
+       /* need to put in table to calculate label which is needed for printing */
+       LOCK_HASH(new_cell->hash_index);
+       insert_into_hash_table_unsafe(new_cell);
+       UNLOCK_HASH(new_cell->hash_index);
+
+       if (fromtag == 0) {
+                    /* calculate from tag from callid */
+               crcitt_string_array(&from_tag[MD5_LEN + 1], (cid) ? (cid) : (&callid_s), 1);
+               ftag.s = from_tag; 
+               ftag.len = FROM_TAG_LEN;
+       }
+
+       buf = build_uac_request_dlg(msg, 
+                                   (ruri) ? (ruri) : (to),
+                                   to, 
+                                   (from) ? (from) : (&uac_from_str), 
+                                   totag,
+                                   (fromtag) ? (fromtag) : (&ftag), 
+                                   (cseq) ? (*cseq) : DEFAULT_CSEQ, 
+                                   (cid) ? (cid) : (&callid_s), 
+                                   headers, 
+                                   body, 
+                                   branch,
+                                   new_cell,
+                                   &req_len);
+       if (!buf) {
+               ret = E_OUT_OF_MEM;
+               LOG(L_ERR, "ERROR: t_uac: short of req shmem\n");
+               goto error01;
+       }
+       new_cell->method.s = buf;
+       new_cell->method.len = msg->len;
+
+       request->buffer = buf;
+       request->buffer_len = req_len;
+       new_cell->nr_of_outgoings++;
+
+       proxy->tx++;
+       proxy->tx_bytes += req_len;
+
+       if (SEND_BUFFER(request) == -1) {
+               if (dst) {
+                       tmp = *dst;
+               } else if (ruri) {
+                       tmp = *ruri;
+               } else {
+                       tmp = *to;
+               }
+               LOG(L_ERR, "ERROR: t_uac: UAC sending to \'%.*s\' failed\n", tmp.len, tmp.s);
+               proxy->errors++;
+               proxy->ok = 0;
+       }
+       
+       start_retr(request);
+
+       /* success */
+       return 1;
+
+error01:
+       LOCK_HASH(new_cell->hash_index);
+       remove_from_hash_table_unsafe(new_cell);
+       UNLOCK_HASH(new_cell->hash_index);
+       free_cell(new_cell);
+
+error00:
+       free_proxy(proxy);
+       free(proxy);
+
+done: 
+       /* if we did not install cbp, release it now */
+       if (cbp) shm_free(cbp);
+       return ser_error = ret;
+}
+
+
 static void fifo_callback( struct cell *t, struct sip_msg *msg,
        int code, void *param)
 {
index 40b59ff..6b08fc7 100644 (file)
@@ -86,6 +86,26 @@ int t_uac(
        void *cbp,
        struct dialog *dlg );
 
+
+/*
+ * Send a request within a dialog
+ */
+int t_uac_dlg(str* msg,                     /* Type of the message - MESSAGE, OPTIONS etc. */
+             str* dst,                     /* Real destination (can be different than R-URI */
+             str* ruri,                    /* Request-URI */
+             str* to,                      /* To - including tag */
+             str* from,                    /* From - including tag */
+             str* totag,                   /* To tag */
+             str* fromtag,                 /* From tag */
+             int* cseq,                    /* CSeq */
+             str* cid,                     /* Call-ID */
+             str* headers,                 /* Optional headers including CRLF */
+             str* body,                    /* Message body */
+             transaction_cb completion_cb, /* Callback parameter */
+             void* cbp                     /* Callback pointer */
+             );
+
+
 int fifo_uac( FILE *stream, char *response_file );
 int fifo_uac_from( FILE *stream, char *response_file );
 #endif