changeset 1072:686cd3e8e13e

avoid malloc for iovec
author Matt Johnston <matt@ucc.asn.au>
date Fri, 20 Mar 2015 22:53:32 +0800
parents ce21d0bfaf98
children 88043f9d40bd
files common-channel.c netio.c netio.h packet.c
diffstat 4 files changed, 15 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/common-channel.c	Mon Mar 16 21:33:01 2015 +0800
+++ b/common-channel.c	Fri Mar 20 22:53:32 2015 +0800
@@ -482,7 +482,7 @@
 
 	if (written < 0) {
 		if (errno != EINTR && errno != EAGAIN) {
-			TRACE(("errno %d len %d", errno, len))
+			TRACE(("errno %d", errno))
 			close_chan_fd(channel, fd, SHUT_WR);
 		}
 	} else {
--- a/netio.c	Mon Mar 16 21:33:01 2015 +0800
+++ b/netio.c	Fri Mar 20 22:53:32 2015 +0800
@@ -72,6 +72,7 @@
 	int fastopen = 0;
 #ifdef DROPBEAR_TCP_FAST_OPEN
 	struct msghdr message;
+	struct iovec message;
 #endif
 
 	for (r = c->res_iter; r; r = r->ai_next)
@@ -99,8 +100,11 @@
 		message.msg_namelen = r->ai_addrlen;
 
 		if (c->writequeue) {
-			int iovlen; /* Linux msg_iovlen is a size_t */
-			message.msg_iov = packet_queue_to_iovec(c->writequeue, &iovlen);
+			/* 6 is arbitrary, enough to hold initial packets */
+			int iovlen = 6; /* Linux msg_iovlen is a size_t */
+			struct iov[6];
+			packet_queue_to_iovec(c->writequeue, iov, &iovlen);
+			message.msg_iov = &iov;
 			message.msg_iovlen = iovlen;
 			res = sendmsg(c->sock, &message, MSG_FASTOPEN);
 			if (res < 0 && errno != EINPROGRESS) {
@@ -114,7 +118,6 @@
 				/* Set to NULL to avoid trying again */
 				c->writequeue = NULL;
 			}
-			m_free(message.msg_iov);
 			packet_queue_consume(c->writequeue, res);
 		}
 #endif
@@ -258,8 +261,7 @@
 	c->writequeue = writequeue;
 }
 
-struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count) {
-	struct iovec *iov = NULL;
+void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count) {
 	struct Link *l;
 	unsigned int i;
 	int len;
@@ -269,9 +271,8 @@
 	#define IOV_MAX UIO_MAXIOV
 	#endif
 
-	*ret_iov_count = MIN(queue->count, IOV_MAX);
+	*iov_count = MIN(MIN(queue->count, IOV_MAX), *iov_count);
 
-	iov = m_malloc(sizeof(*iov) * *ret_iov_count);
 	for (l = queue->head, i = 0; l; l = l->link, i++)
 	{
 		writebuf = (buffer*)l->item;
@@ -282,8 +283,6 @@
 		iov[i].iov_base = buf_getptr(writebuf, len);
 		iov[i].iov_len = len;
 	}
-
-	return iov;
 }
 
 void packet_queue_consume(struct Queue *queue, ssize_t written) {
--- a/netio.h	Mon Mar 16 21:33:01 2015 +0800
+++ b/netio.h	Fri Mar 20 22:53:32 2015 +0800
@@ -44,7 +44,8 @@
 void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue);
 
 /* TODO: writev #ifdef guard */
-struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count);
+/* Fills out iov which contains iov_count slots, returning the number filled in iov_count */
+void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count);
 void packet_queue_consume(struct Queue *queue, ssize_t written);
 
 #ifdef DROPBEAR_TCP_FAST_OPEN
--- a/packet.c	Mon Mar 16 21:33:01 2015 +0800
+++ b/packet.c	Fri Mar 20 22:53:32 2015 +0800
@@ -58,8 +58,9 @@
 
 	ssize_t written;
 #ifdef HAVE_WRITEV
-	struct iovec *iov = NULL;
-	int iov_count;
+	/* 50 is somewhat arbitrary */
+	int iov_count = 50;
+	struct iovec iov[50];
 #endif
 	
 	TRACE2(("enter write_packet"))
@@ -67,7 +68,7 @@
 
 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
 
-	iov = packet_queue_to_iovec(&ses.writequeue, &iov_count);
+	packet_queue_to_iovec(&ses.writequeue, iov, &iov_count);
 	/* This may return EAGAIN. The main loop sometimes
 	calls write_packet() without bothering to test with select() since
 	it's likely to be necessary */
@@ -75,13 +76,11 @@
 	if (written < 0) {
 		if (errno == EINTR || errno == EAGAIN) {
 			TRACE2(("leave write_packet: EINTR"))
-			m_free(iov);
 			return;
 		} else {
 			dropbear_exit("Error writing: %s", strerror(errno));
 		}
 	}
-	m_free(iov);
 
 	packet_queue_consume(&ses.writequeue, written);