summaryrefslogtreecommitdiff
path: root/common-channel.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2015-03-21 22:43:08 +0800
committerMatt Johnston <matt@ucc.asn.au>2015-03-21 22:43:08 +0800
commitef20b9ff7a61a3619daf9d7f778d3b42c9322eb1 (patch)
tree4aa526feaea90cfaae3c1e20c6046e9d0e5b3dda /common-channel.c
parent275611fbaaa14824de69bccc68161d5ed195b745 (diff)
downloaddropbear-ef20b9ff7a61a3619daf9d7f778d3b42c9322eb1.tar.gz
Avoid channel writev() when there is nothing to write
Diffstat (limited to 'common-channel.c')
-rw-r--r--common-channel.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/common-channel.c b/common-channel.c
index 0e5c0f1..6dce497 100644
--- a/common-channel.c
+++ b/common-channel.c
@@ -473,6 +473,14 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
io_count++;
}
+ if (io_count == 0) {
+ /* writechannel may sometimes be called twice in a main loop iteration.
+ From common_recv_msg_channel_data() then channelio().
+ The second call may not have any data to write, so we just return. */
+ TRACE(("leave writechannel, no data"))
+ return;
+ }
+
if (morelen) {
/* Default return value, none consumed */
*morelen = 0;
@@ -482,7 +490,7 @@ static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
if (written < 0) {
if (errno != EINTR && errno != EAGAIN) {
- TRACE(("errno %d", errno))
+ TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
close_chan_fd(channel, fd, SHUT_WR);
}
} else {
@@ -830,6 +838,7 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
channel->recvwindow -= datalen;
dropbear_assert(channel->recvwindow <= opts.recv_window);
+ /* Attempt to write the data immediately without having to put it in the circular buffer */
consumed = datalen;
writechannel(channel, fd, cbuf, buf_getptr(ses.payload, datalen), &consumed);