diff common-channel.c @ 70:b0316ce64e4b

Merging in the changes from 0.41-0.43 main Dropbear tree
author Matt Johnston <matt@ucc.asn.au>
date Thu, 12 Aug 2004 16:41:58 +0000
parents 20563735e8b5
children d3eb1fa8484e
line wrap: on
line diff
--- a/common-channel.c	Thu Aug 12 15:41:36 2004 +0000
+++ b/common-channel.c	Thu Aug 12 16:41:58 2004 +0000
@@ -172,6 +172,7 @@
 
 	struct Channel *channel;
 	unsigned int i;
+	int ret;
 
 	/* iterate through all the possible channels */
 	for (i = 0; i < ses.chansize; i++) {
@@ -196,8 +197,15 @@
 		 * see if it has errors */
 		if (channel->infd >= 0 && channel->infd != channel->outfd
 				&& FD_ISSET(channel->infd, readfd)) {
-			int ret;
-			ret = write(channel->infd, NULL, 0);
+			if (channel->initconn) {
+				/* Handling for "in progress" connection - this is needed
+				 * to avoid spinning 100% CPU when we connect to a server
+				 * which doesn't send anything (tcpfwding) */
+				checkinitdone(channel);
+				continue; /* Important not to use the channel after 
+							 checkinitdone(), as it may be NULL */
+			}
+			ret = write(channel->infd, NULL, 0); /* Fake write */
 			if (ret < 0 && errno != EINTR && errno != EAGAIN) {
 				closeinfd(channel);
 			}
@@ -209,9 +217,8 @@
 				checkinitdone(channel);
 				continue; /* Important not to use the channel after
 							 checkinitdone(), as it may be NULL */
-			} else {
-				writechannel(channel);
 			}
+			writechannel(channel);
 		}
 	
 		/* now handle any of the channel-closing type stuff */
@@ -285,10 +292,14 @@
 
 	if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen)
 			|| val != 0) {
+		send_msg_channel_open_failure(channel->remotechan,
+				SSH_OPEN_CONNECT_FAILED, "", "");
 		close(channel->infd);
 		deletechannel(channel);
 		TRACE(("leave checkinitdone: fail"));
 	} else {
+		send_msg_channel_open_confirmation(channel, channel->recvwindow,
+				channel->recvmaxpacket);
 		channel->outfd = channel->infd;
 		channel->initconn = 0;
 		TRACE(("leave checkinitdone: success"));
@@ -489,6 +500,7 @@
 	TRACE(("channel index is %d", channel->index));
 
 	buf_free(channel->writebuf);
+	channel->writebuf = NULL;
 
 	/* close the FDs in case they haven't been done
 	 * yet (ie they were shutdown etc */
@@ -497,6 +509,7 @@
 	if (channel->errfd >= 0) {
 		close(channel->errfd);
 	}
+	channel->typedata = NULL;
 
 	deletechannel(channel);
 
@@ -587,6 +600,7 @@
 			TRACE(("leave send_msg_channel_data: read err %d", channel->index));
 		}
 		buf_free(buf);
+		buf = NULL;
 		return;
 	}
 	buf_incrlen(buf, len);
@@ -601,6 +615,7 @@
 
 	buf_putstring(ses.writepayload, buf_getptr(buf, len), len);
 	buf_free(buf);
+	buf = NULL;
 
 	channel->transwindow -= len;
 
@@ -764,6 +779,10 @@
 	if (channel->type->inithandler) {
 		ret = channel->type->inithandler(channel);
 		if (ret > 0) {
+			if (ret == SSH_OPEN_IN_PROGRESS) {
+				/* We'll send the confirmation later */
+				goto cleanup;
+			}
 			errtype = ret;
 			deletechannel(channel);
 			TRACE(("inithandler returned failure %d", ret));