[asterisk-commits] jamesgolovich: branch group/sip-tcptls r89525 - in /team/group/sip-tcptls: ch...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Nov 22 00:12:12 CST 2007


Author: jamesgolovich
Date: Thu Nov 22 00:12:11 2007
New Revision: 89525

URL: http://svn.digium.com/view/asterisk?view=rev&rev=89525
Log:
Update TLS code.  
This code has been tested to another asterisk box (TCP and TLS), 
Minisip (TCP and TLS), and a cisco IOS gateway (TCP only). 



Modified:
    team/group/sip-tcptls/channels/chan_sip.c
    team/group/sip-tcptls/include/asterisk/server.h
    team/group/sip-tcptls/main/server.c

Modified: team/group/sip-tcptls/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/sip-tcptls/channels/chan_sip.c?view=diff&rev=89525&r1=89524&r2=89525
==============================================================================
--- team/group/sip-tcptls/channels/chan_sip.c (original)
+++ team/group/sip-tcptls/channels/chan_sip.c Thu Nov 22 00:12:11 2007
@@ -1380,6 +1380,8 @@
 struct sip_threadinfo {
 	int stop;
 	pthread_t threadid;
+	struct server_instance *ser;
+	enum sip_transport type;	/* We keep a copy of the type here so we can display it in the connection list */
 	AST_LIST_ENTRY(sip_threadinfo) list;
 };
 
@@ -1947,8 +1949,7 @@
 /*! \brief SIP TCP helper function */
 static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct server_instance *ser) 
 {
-	int cl;
-	char buf[1024];
+	int res;
 	struct sip_request req = { 0, }, reqcpy = { 0, };
 	struct sip_threadinfo *me;
 
@@ -1958,6 +1959,12 @@
 		goto cleanup2;
 
 	me->threadid = pthread_self();
+	me->ser = ser;
+	if (ser->ssl)
+		me->type = SIP_TRANSPORT_TLS;
+	else
+		me->type = SIP_TRANSPORT_TCP;
+
 	AST_LIST_INSERT_TAIL(&threadl, me, list);
 
 	req.socket.lock = ast_calloc(1, sizeof(*req.socket.lock));
@@ -1968,50 +1975,44 @@
 	ast_mutex_init(req.socket.lock);
 
 	for (;;) {
-		bzero(req.data, sizeof(req.data));
+		memset(req.data, 0, sizeof(req.data));
 		req.len = 0;
-
-		while (req.len < 4 || strncmp((char *)&req.data + req.len - 4, "\r\n\r\n", 4)) {
-			if (!fgets(buf, sizeof(buf), ser->f))
-				goto cleanup;
-
-			if (me->stop) goto cleanup;
-
-			strncat(req.data, buf, sizeof(req.data) - req.len);
-			req.len = strlen(req.data);
-		}
-
-		parse_copy(&reqcpy, &req);
-
-		if (sscanf(get_header(&reqcpy, "Content-Length"), "%d", &cl)) {
-			while (cl > 0) {
-				if (!fread(buf, (cl < sizeof(buf)) ? cl : sizeof(buf), 1, ser->f))
-					goto cleanup;
-
-				if (me->stop) goto cleanup;
-
-				cl -= strlen(buf);
-				strncat(req.data, buf, sizeof(req.data) - req.len);
-				req.len = strlen(req.data);
-			}
-		}
+		req.ignore = 0;
 
 		req.socket.fd = ser->fd;
-
-		if (ser->parent->tls_cfg) {
+		if (ser->ssl) {
 			req.socket.type = SIP_TRANSPORT_TLS;
-			req.socket.port = ourport_tls;
+			req.socket.port = htons(ourport_tls);
 		} else {
 			req.socket.type = SIP_TRANSPORT_TCP;
-			req.socket.port = ourport_tcp;
-		}
-
+			req.socket.port = htons(ourport_tcp);
+		}
+
+		res = ast_wait_for_input(ser->fd, -1);
+		if (res < 0)
+			ast_log(LOG_DEBUG, "ast_wait_for_input returned %d\n", res);
+		if (req.socket.lock) 
+			ast_mutex_lock(req.socket.lock);
+
+		if (!(req.len = server_read(ser, req.data, sizeof(req.data)))) {
+			ast_log(LOG_DEBUG, "server_read failed: %s\n", strerror(errno));
+			goto cleanup;
+		}
+
+		if (req.socket.lock) 
+			ast_mutex_unlock(req.socket.lock);
+
+		if (me->stop) 
+			 goto cleanup;
+
+		parse_copy(&reqcpy, &req);
 		req.socket.ser = ser;
-
 		handle_request_do(&req, &ser->requestor);
 	}
 
 cleanup:
+	if (req.socket.lock) 
+		ast_mutex_unlock(req.socket.lock);
 	AST_LIST_REMOVE(&threadl, me, list);
 	ast_free(me);
 cleanup2:
@@ -2269,7 +2270,6 @@
 	return "UNKNOWN";
 }
 
-
 /*! \brief Transmit SIP message */
 static int __sip_xmit(struct sip_pvt *p, char *data, int len)
 {
@@ -2284,10 +2284,14 @@
 	if (p->socket.lock)
 		ast_mutex_lock(p->socket.lock);
 
-	if (p->socket.type & SIP_TRANSPORT_TLS)
-		res = fprintf(p->socket.ser->f, "%.*s", len, data);
-	else
+	if (p->socket.type & SIP_TRANSPORT_UDP) 
 		res = sendto(p->socket.fd, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+	else {
+		if (p->socket.ser->f) 
+			res = server_write(p->socket.ser, data, len);
+		else
+			ast_log(LOG_DEBUG, "No p->socket.ser->f len=%d\n", len);
+	} 
 
 	if (p->socket.lock)
 		ast_mutex_unlock(p->socket.lock);
@@ -2427,10 +2431,6 @@
 	int reschedule = DEFAULT_RETRANS;
 	int xmitres = 0;
 
-	/* Don't retransmit TCP packets */
-	if (!(pkt->owner->socket.type & SIP_TRANSPORT_UDP))
-		return 0;
-
 	/* Lock channel PVT */
 	sip_pvt_lock(pkt->owner);
 
@@ -2551,6 +2551,18 @@
 	struct sip_pkt *pkt;
 	int siptimer_a = DEFAULT_RETRANS;
 	int xmitres = 0;
+
+	/* If the transport is something reliable (TCP or TLS) then don't really send this reliably */
+	/* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */
+	/* According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */
+	if (!(p->socket.type & SIP_TRANSPORT_UDP)) {
+		xmitres = __sip_xmit(dialog_ref(p), data, len);	/* Send packet */
+		if (xmitres == XMIT_ERROR) {	/* Serious network trouble, no need to try again */
+			append_history(p, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
+			return AST_FAILURE;
+		} else
+			return AST_SUCCESS;
+	}
 
 	if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1)))
 		return AST_FAILURE;
@@ -7742,10 +7754,13 @@
 static void build_contact(struct sip_pvt *p)
 {
 	/* Construct Contact: header */
-	if (!sip_standard_port(p->socket))
-		ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), p->socket.port);
-	else
-		ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
+	if (p->socket.type & SIP_TRANSPORT_UDP) {
+		if (!sip_standard_port(p->socket))
+			ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->socket.port));
+		else
+			ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
+	} else 
+		ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ntohs(p->socket.port), get_transport(p->socket.type));
 }
 
 /*! \brief Build the Remote Party-ID & From using callingpres options */
@@ -7895,7 +7910,7 @@
 	}
 
 	if (!sip_standard_port(p->socket) && ast_strlen_zero(p->fromdomain))
-		snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), p->socket.port, p->tag);
+		snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), ntohs(p->socket.port), p->tag);
 	else
 		snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), p->tag);
 
@@ -8936,7 +8951,7 @@
 	ast_string_field_set(pvt, okcontacturi, c);
 
 	/* We should return false for URI:s we can't handle,
-		like sips:, tel:, mailto:,ldap: etc */
+		like tel:, mailto:,ldap: etc */
 	return TRUE;		
 }
 
@@ -10961,6 +10976,41 @@
 static const char *cli_yesno(int x)
 {
 	return x ? "Yes" : "No";
+}
+
+/*! \brief  Show active TCP connections */
+static char *sip_show_tcp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	struct sip_threadinfo *th;
+
+#define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n"
+#define FORMAT  "%-30.30s %-6d %-9.9s %-6.6s\n"
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "sip show tcp";
+		e->usage =
+			"Usage: sip show tcp\n"
+			"       Lists all active TCP/TLS sessions.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 3)
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, FORMAT2, "Host", "Port", "Transport", "Type");
+	AST_LIST_TRAVERSE(&threadl, th, list) {
+		ast_cli(a->fd, FORMAT, ast_inet_ntoa(th->ser->requestor.sin_addr), 
+			ntohs(th->ser->requestor.sin_port), 
+			get_transport(th->type), 
+			(th->ser->client ? "Client" : "Server"));
+
+	}
+	return CLI_SUCCESS;
+#undef FORMAT
+#undef FORMAT2
 }
 
 /*! \brief  CLI Command 'SIP Show Users' */
@@ -11689,6 +11739,7 @@
 		ast_cli(fd, "  ToHost       : %s\n", peer->tohost);
 		ast_cli(fd, "  Addr->IP     : %s Port %d\n",  peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port));
 		ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
+		ast_cli(fd, "  Transport    : %s\n", get_transport(peer->socket.type));
 		if (!ast_strlen_zero(global_regcontext))
 			ast_cli(fd, "  Reg. exten   : %s\n", peer->regexten);
 		ast_cli(fd, "  Def. Username: %s\n", peer->username);
@@ -16812,7 +16863,7 @@
 	req.socket.fd 	= sipsock;
 	req.socket.type = SIP_TRANSPORT_UDP;
 	req.socket.ser	= NULL;
-	req.socket.port = ntohs(bindaddr.sin_port);
+	req.socket.port = htons(bindaddr.sin_port);
 	req.socket.lock = NULL;
 
 	handle_request_do(&req, &sin);
@@ -16886,9 +16937,6 @@
 		return 1;
 	}
 
-	if (p->history)
-		append_history(p, "Rx", "%s / %s / %s", req->data, get_header(req, "CSeq"), req->rlPart2);
-
 	nounlock = 0;
 	if (handle_incoming(p, req, sin, &recount, &nounlock) == -1) {
 		/* Request failed */
@@ -16906,17 +16954,32 @@
 	return 1;
 }
 
-static int sip_standard_port(struct sip_socket s) {
+static int sip_standard_port(struct sip_socket s) 
+{
 	if (s.type & SIP_TRANSPORT_TLS)
 		return s.port == STANDARD_TLS_PORT;
 	else
 		return s.port == STANDARD_SIP_PORT;
 }
 
+static struct server_instance *sip_tcp_locate(struct sockaddr_in *s)
+{
+	struct sip_threadinfo *th;
+
+	AST_LIST_TRAVERSE(&threadl, th, list) {
+		if ((s->sin_family == th->ser->requestor.sin_family) &&
+			(s->sin_addr.s_addr == th->ser->requestor.sin_addr.s_addr) &&
+			(s->sin_port == th->ser->requestor.sin_port)) 
+				return th->ser;
+	}
+	return NULL;
+}
+
 static int sip_prepare_socket(struct sip_pvt *p) 
 {
 	struct sip_socket *s = &p->socket;
 	static const char name[] = "SIP socket";
+	struct server_instance *ser;
 	struct server_args ca = {
 		.name = name,
 		.accept_fd = -1,
@@ -16930,15 +16993,25 @@
 		return s->fd;
 	}
 
+	ca.sin = *(sip_real_dst(p));
+
+	if ((ser = sip_tcp_locate(&ca.sin))) {
+		s->fd = ser->fd;
+		s->ser = ser;
+		return s->fd;
+	}
+
 	ca.tls_cfg = (s->ser) ? s->ser->parent->tls_cfg : NULL;
-	ca.sin = *(sip_real_dst(p));
 	if (!ca.tls_cfg && s->type & SIP_TRANSPORT_TLS && 
 		!(ca.tls_cfg = ast_calloc(1, sizeof(*ca.tls_cfg))))
 		return -1;
 	s->ser = (!s->ser) ? client_start(&ca) : s->ser;
 
-	if (!s->ser)
+	if (!s->ser) {
+		if (ca.tls_cfg)
+			ast_free(ca.tls_cfg);
 		return -1;
+	}
 
 	s->fd = ca.accept_fd;
 
@@ -18064,11 +18137,12 @@
 		if (handle_common_options(&peerflags[0], &mask[0], v))
 			continue;
 		if (!strcasecmp(v->name, "transport")) {
-			if (!strcasecmp(v->value, "tcp")) {
+			if (!strcasecmp(v->value, "udp")) 
+				peer->socket.type = SIP_TRANSPORT_UDP;
+			else if (!strcasecmp(v->value, "tcp"))
 				peer->socket.type = SIP_TRANSPORT_TCP;
-			} else if (!strcasecmp(v->value, "tls")) {
+			else if (!strcasecmp(v->value, "tls"))
 				peer->socket.type = SIP_TRANSPORT_TLS;
-			}
 		} else if (realtime && !strcasecmp(v->name, "regseconds")) {
 			ast_get_time_t(v->value, &regseconds, 0, NULL);
 		} else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
@@ -18260,6 +18334,9 @@
 	if (!peer->addr.sin_port)
 		peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
 
+	if (!peer->socket.port)
+		peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
+
 	if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) {
 		time_t nowtime = time(NULL);
 
@@ -18341,8 +18418,8 @@
 	}
 
 	/* Initialize tcp sockets */
-	bzero(&sip_tcp_desc.sin, sizeof(sip_tcp_desc.sin));
-	bzero(&sip_tls_desc.sin, sizeof(sip_tls_desc.sin));
+	memset(&sip_tcp_desc.sin, 0, sizeof(sip_tcp_desc.sin));
+	memset(&sip_tls_desc.sin, 0, sizeof(sip_tls_desc.sin));
 
 	sip_tcp_desc.sin.sin_family = AF_INET;
 
@@ -18959,8 +19036,10 @@
 
 	if (ssl_setup(sip_tls_desc.tls_cfg))
 		server_start(&sip_tls_desc);
-	else if(sip_tls_desc.tls_cfg->enabled)
+	else if (sip_tls_desc.tls_cfg->enabled) {
+		sip_tls_desc.tls_cfg = NULL;
 		ast_log(LOG_WARNING, "SIP TLS server did not load because of errors.\n");
+	}
 
 	/* Done, tell the manager */
 	manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "ChannelType: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\nUser_Count: %d\r\n", channelreloadreason2txt(reason), registry_count, peer_count, user_count);
@@ -19534,6 +19613,7 @@
 	AST_CLI_DEFINE(sip_do_history, "Enable SIP history"),
 	AST_CLI_DEFINE(sip_no_history, "Disable SIP history"),
 	AST_CLI_DEFINE(sip_reload, "Reload SIP configuration"),
+	AST_CLI_DEFINE(sip_show_tcp, "List TCP Connections")
 };
 
 /*! \brief PBX load module - initialization */

Modified: team/group/sip-tcptls/include/asterisk/server.h
URL: http://svn.digium.com/view/asterisk/team/group/sip-tcptls/include/asterisk/server.h?view=diff&rev=89525&r1=89524&r2=89525
==============================================================================
--- team/group/sip-tcptls/include/asterisk/server.h (original)
+++ team/group/sip-tcptls/include/asterisk/server.h Thu Nov 22 00:12:11 2007
@@ -136,4 +136,7 @@
 
 void *ast_make_file_from_fd(void *data);
 
+ssize_t server_read(struct server_instance *ser, void *buf, size_t count);
+ssize_t server_write(struct server_instance *ser, void *buf, size_t count);
+
 #endif /* _ASTERISK_SERVER_H */

Modified: team/group/sip-tcptls/main/server.c
URL: http://svn.digium.com/view/asterisk/team/group/sip-tcptls/main/server.c?view=diff&rev=89525&r1=89524&r2=89525
==============================================================================
--- team/group/sip-tcptls/main/server.c (original)
+++ team/group/sip-tcptls/main/server.c Thu Nov 22 00:12:11 2007
@@ -65,6 +65,26 @@
 	return SSL_write(cookie, buf, len);
 }
 
+ssize_t server_read(struct server_instance *ser, void *buf, size_t count)
+{
+	if (!ser->ssl) 
+		return read(ser->fd, buf, count);
+#ifdef DO_SSL
+	else
+		return ssl_read(ser->ssl, buf, count);
+#endif
+}
+
+ssize_t server_write(struct server_instance *ser, void *buf, size_t count)
+{
+	if (!ser->ssl) 
+		return write(ser->fd, buf, count);
+#ifdef DO_SSL
+	else
+		return ssl_write(ser->ssl, buf, count);
+#endif
+}
+
 static int ssl_close(void *cookie)
 {
 	close(SSL_get_fd(cookie));
@@ -175,7 +195,11 @@
 	SSL_load_error_strings();
 	SSLeay_add_ssl_algorithms();
 
-	cfg->ssl_ctx = SSL_CTX_new( SSLv23_client_method() );
+	if (!(cfg->ssl_ctx = SSL_CTX_new( SSLv23_client_method() ))) {
+		ast_log(LOG_DEBUG, "SSL_CTX_new returned null\n");
+		cfg->enabled = 0;
+		return 0;
+	}
 
 	return 1;
 #endif
@@ -234,7 +258,7 @@
 		client_setup(desc->tls_cfg);
 	}
 
-	if(!ast_make_file_from_fd(ser))
+	if (!ast_make_file_from_fd(ser))
 		goto error;
 
 	return ser;
@@ -326,7 +350,7 @@
 	int ret;
 	char err[256];
 
-   /*
+	/*
 	* open a FILE * as appropriate.
 	*/
 	if (!ser->parent->tls_cfg)




More information about the asterisk-commits mailing list