generalise write iovec handling

--HG--
branch : fastopen
This commit is contained in:
Matt Johnston 2015-02-18 23:02:49 +08:00
parent 755c1458f0
commit 5f0cc969a0

View File

@ -52,25 +52,52 @@ static buffer* buf_decompress(buffer* buf, unsigned int len);
static void buf_compress(buffer * dest, buffer * src, unsigned int len); static void buf_compress(buffer * dest, buffer * src, unsigned int len);
#endif #endif
#if 0 struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count) {
struct iovec * dropbear_queue_to_iovec(struct Queue *queue) {
struct iovec *iov = NULL; struct iovec *iov = NULL;
struct Link *l; struct Link *l;
int iov_max_count; unsigned int i, packet_type;
int len;
buffer *writebuf;
#ifndef IOV_MAX #ifndef IOV_MAX
#define IOV_MAX UIO_MAXIOV #define IOV_MAX UIO_MAXIOV
#endif #endif
#error incomplete *ret_iov_count = MIN(queue->count, IOV_MAX);
iov = m_malloc(sizeof(*iov) * *ret_iov_count);
for (l = queue->head, i = 0; l; l = l->link, i++)
{
writebuf = (buffer*)l->item;
packet_type = writebuf->data[writebuf->len-1];
len = writebuf->len - 1 - writebuf->pos;
dropbear_assert(len > 0);
TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type,
len, writebuf->len-1))
iov[i].iov_base = buf_getptr(writebuf, len);
iov[i].iov_len = len;
}
return iov;
} }
void dropbear_queue_consume(struct Queue *queue, ssize_t written) { void packet_queue_consume(struct Queue *queue, ssize_t written) {
buffer *writebuf;
int len;
while (written > 0) {
writebuf = (buffer*)examine(queue);
len = writebuf->len - 1 - writebuf->pos;
if (len > written) {
/* partial buffer write */
buf_incrpos(writebuf, written);
written = 0;
} else {
written -= len;
dequeue(queue);
buf_free(writebuf);
}
}
} }
#endif
/* non-blocking function writing out a current encrypted packet */ /* non-blocking function writing out a current encrypted packet */
void write_packet() { void write_packet() {
@ -83,7 +110,7 @@ void write_packet() {
struct iovec *iov = NULL; struct iovec *iov = NULL;
int i; int i;
struct Link *l; struct Link *l;
int iov_max_count; int iov_count;
#endif #endif
TRACE2(("enter write_packet")) TRACE2(("enter write_packet"))
@ -91,62 +118,28 @@ void write_packet() {
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV)) #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
#ifndef IOV_MAX iov = packet_queue_to_iovec(&ses.writequeue, &iov_count);
#define IOV_MAX UIO_MAXIOV
#endif
/* Make sure the size of the iov is below the maximum allowed by the OS. */
iov_max_count = ses.writequeue.count;
if (iov_max_count > IOV_MAX)
{
iov_max_count = IOV_MAX;
}
iov = m_malloc(sizeof(*iov) * iov_max_count);
for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
{
writebuf = (buffer*)l->item;
packet_type = writebuf->data[writebuf->len-1];
len = writebuf->len - 1 - writebuf->pos;
dropbear_assert(len > 0);
TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type,
len, writebuf->len-1))
iov[i].iov_base = buf_getptr(writebuf, len);
iov[i].iov_len = len;
}
/* This may return EAGAIN. The main loop sometimes /* This may return EAGAIN. The main loop sometimes
calls write_packet() without bothering to test with select() since calls write_packet() without bothering to test with select() since
it's likely to be necessary */ it's likely to be necessary */
written = writev(ses.sock_out, iov, iov_max_count); written = writev(ses.sock_out, iov, iov_count);
if (written < 0) { if (written < 0) {
if (errno == EINTR || errno == EAGAIN) { if (errno == EINTR || errno == EAGAIN) {
m_free(iov);
TRACE2(("leave write_packet: EINTR")) TRACE2(("leave write_packet: EINTR"))
m_free(iov);
return; return;
} else { } else {
dropbear_exit("Error writing: %s", strerror(errno)); dropbear_exit("Error writing: %s", strerror(errno));
} }
} }
m_free(iov);
packet_queue_consume(&ses.writequeue, written);
if (written == 0) { if (written == 0) {
ses.remoteclosed(); ses.remoteclosed();
} }
while (written > 0) {
writebuf = (buffer*)examine(&ses.writequeue);
len = writebuf->len - 1 - writebuf->pos;
if (len > written) {
/* partial buffer write */
buf_incrpos(writebuf, written);
written = 0;
} else {
written -= len;
dequeue(&ses.writequeue);
buf_free(writebuf);
}
}
m_free(iov);
#else /* No writev () */ #else /* No writev () */
/* Get the next buffer in the queue of encrypted packets to write*/ /* Get the next buffer in the queue of encrypted packets to write*/
writebuf = (buffer*)examine(&ses.writequeue); writebuf = (buffer*)examine(&ses.writequeue);