소스 검색

Implemented t_uac_dlg and build_uac_request_dlg. These functions are more
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.

Jan Janak 23 년 전
부모
커밋
27c28ba118
4개의 변경된 파일373개의 추가작업 그리고 0개의 파일을 삭제
  1. 168 0
      modules/tm/t_msgbuilder.c
  2. 19 0
      modules/tm/t_msgbuilder.h
  3. 166 0
      modules/tm/uac.c
  4. 20 0
      modules/tm/uac.h

+ 168 - 0
modules/tm/t_msgbuilder.c

@@ -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)
 {

+ 19 - 0
modules/tm/t_msgbuilder.h

@@ -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);
 

+ 166 - 0
modules/tm/uac.c

@@ -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:[email protected]: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)
 {

+ 20 - 0
modules/tm/uac.h

@@ -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