Subject: UDP forwarder

From: Thomas Koenig <[email-masked]>
Date: Sun, 2 Feb 1997 03:19:22 +0100 (MET)

Well, the version I just sent out only worked for a few hours,
then got caught up in some race condition or other.

Here's a patch.  Long live non-blocking I/O! :-)

--- udp_fwd.old	Sun Feb  2 03:17:06 1997
+++ udp_fwd	Sun Feb  2 02:57:47 1997
@@ -3,6 +3,7 @@
 require 5.002;
 use Socket;
 use Sys::Hostname;
+use Fcntl;
 
 $port = $ARGV[0] or die "Need local port number!\n";
 $host = $ARGV[1] or die "Need remote hostname!\n";
@@ -19,6 +20,8 @@
 bind(KA, sockaddr_in($port, INADDR_ANY))
     or die "Can't bind local socket:$!\n";
 
+fcntl(KA, F_SETFL, O_NONBLOCK);
+
 $kain = $rin = '';
 vec($kain,fileno(KA),1) = 1;
 $rin = $kain;
@@ -31,6 +34,7 @@
 
     if (vec($rout, fileno(KA),1)) {
 	$addr = recv ( KA,$packet, 200, 0);
+	next unless $addr;
         ($fport, $fiaddr) = unpack_sockaddr_in($addr);
 	$name = $name{$addr} = inet_ntoa($fiaddr) . "."  .$fport;
 	# print "Getting packet from $name{$addr}; filehandle: ";
@@ -48,6 +52,7 @@
 		    vec($rin, $fn,1) = 1;
 		    $fromaddr{$fn} = $addr;
 		    $fh{$fn} = $filehandle{$name};
+	            fcntl($filehandle{$name}, F_SETFL, O_NONBLOCK);
 		}
 		else {
 		    warn "Connect failed for $name{$addr}\n";
@@ -70,7 +75,8 @@
     if ($rout !~ /^\000*$/) {
 	foreach $fn (keys %fromaddr) {
 	    if (vec($rout, $fn, 1)) {
-		recv($fh{$fn}, $packet, 200, 0);
+		$val = recv($fh{$fn}, $packet, 200, 0);
+		next unless $val;
 		send(KA, $packet, 0, $fromaddr{$fn});
 	    }
 	}
@@ -81,6 +87,7 @@
 	    if ($nowtime - $lasttime{$_} > 3600.) {
 		close($filehandle{$_});
 		undef $filehandle{$_};
+		warn "Removing stale client $_\n";
 	    }
 	}
 	$lasttime = $nowtime;
-- 
Thomas Koenig, [email-masked], [email-masked].
The joy of engineering is to find a straight line on a double
logarithmic diagram.