diff common-session.c @ 454:7e43f5e473b9

- Add -K keepalive flag for dropbear and dbclient - Try to reduce the frequency of select() timeouts - Add a max receive window size of 1MB
author Matt Johnston <matt@ucc.asn.au>
date Wed, 08 Aug 2007 15:12:06 +0000
parents 4cab61369879
children e3db1f7a2e43
line wrap: on
line diff
--- a/common-session.c	Sat Jul 28 08:59:24 2007 +0000
+++ b/common-session.c	Wed Aug 08 15:12:06 2007 +0000
@@ -34,8 +34,10 @@
 #include "kex.h"
 #include "channel.h"
 #include "atomicio.h"
+#include "runopts.h"
 
 static void checktimeouts();
+static long select_timeout();
 static int ident_readln(int fd, char* buf, int count);
 
 struct sshsession ses; /* GLOBAL */
@@ -59,7 +61,8 @@
 	ses.sock = sock;
 	ses.maxfd = sock;
 
-	ses.connecttimeout = 0;
+	ses.connect_time = 0;
+	ses.last_packet_time = 0;
 	
 	if (pipe(ses.signal_pipe) < 0) {
 		dropbear_exit("signal pipe failed");
@@ -129,7 +132,7 @@
 	/* main loop, select()s for all sockets in use */
 	for(;;) {
 
-		timeout.tv_sec = SELECT_TIMEOUT;
+		timeout.tv_sec = select_timeout();
 		timeout.tv_usec = 0;
 		FD_ZERO(&writefd);
 		FD_ZERO(&readfd);
@@ -359,20 +362,22 @@
 	return pos+1;
 }
 
+void send_msg_ignore() {
+	CHECKCLEARTOWRITE();
+	buf_putbyte(ses.writepayload, SSH_MSG_IGNORE);
+	buf_putstring(ses.writepayload, "", 0);
+	encrypt_packet();
+}
+
 /* Check all timeouts which are required. Currently these are the time for
  * user authentication, and the automatic rekeying. */
 static void checktimeouts() {
 
-	struct timeval tv;
-	long secs;
+	time_t now;
 
-	if (gettimeofday(&tv, 0) < 0) {
-		dropbear_exit("Error getting time");
-	}
-
-	secs = tv.tv_sec;
+	now = time(NULL);
 	
-	if (ses.connecttimeout != 0 && secs > ses.connecttimeout) {
+	if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) {
 			dropbear_close("Timeout before auth");
 	}
 
@@ -382,10 +387,27 @@
 	}
 
 	if (!ses.kexstate.sentkexinit
-			&& (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
-			|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){
+			&& (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
+			|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
 		TRACE(("rekeying after timeout or max data reached"))
 		send_msg_kexinit();
 	}
+	
+	if (opts.keepalive_secs > 0 
+		&& now - ses.last_packet_time >= opts.keepalive_secs) {
+		send_msg_ignore();
+	}
 }
 
+static long select_timeout() {
+	/* determine the minimum timeout that might be required, so
+	as to avoid waking when unneccessary */
+	long ret = LONG_MAX;
+	if (KEX_REKEY_TIMEOUT > 0)
+		ret = MIN(KEX_REKEY_TIMEOUT, ret);
+	if (AUTH_TIMEOUT > 0)
+		ret = MIN(AUTH_TIMEOUT, ret);
+	if (opts.keepalive_secs > 0)
+		ret = MIN(opts.keepalive_secs, ret);
+	return ret;
+}