#!/afs/athena/contrib/perl/p
require 'sys/socket.ph';

($port) = @ARGV;
$port = 4005 unless $port;

$sockaddr = 'S n a4 x8';

($name, $aliases, $proto) = getprotobyname('udp');
if ($port !~ /^\d+$/) {
    ($name, $aliases, $port) = getservbyport($port, 'udp');
}

print "Port = $port\n";
open(ZPF, ">/tmp/pz.$$");
print ZPF $port;
close(ZPF);
$ENV{'WGFILE'} = "/tmp/pz.$$";

chop($myname = `hostname`);
($name, $aliases, $type, $len, $meaddr) = gethostbyname($myname);
$this = pack($sockaddr, $AF_INET, $port, $meaddr);

select(NS); $| = 1; select(stdout);

socket(S, &AF_INET, &SOCK_DGRAM, $proto) || die "socket: $!";
bind(S,$this) || die "bind: $!";
# listen(S,5) || die "connect: $!";

select(S); $| = 1; select(stdout);

$con = 0;
print "Listening for connection 1....\n";
system("zctl sub message %me%");
print("Subbed up...\n");
for(;;){
    $rin = $win = '';
    vec($rin, fileno(S), 1) = 1;
    while($howmuch = select($win, $rin, $ein, 1)){
#	print("Pending: $howmuch\n");
	$peeraddr = recv(S,$data, 1024, 0);
	($af,$port,$inetaddr) = unpack($sockaddr,$peeraddr);
	@inetaddr = unpack('C4',$inetaddr);
	
	&process_zephyr($data);
    }
}

sub process_zephyr {
    local($zgram) =@_;

    (@stuff) = split(/\0/, $zgram);
#    for $n (0..$#stuff){
#	$l = length($stuff[$n]);
#	printf("Field $n ($l): $stuff[$n]\n");
#    }

    $protocol = $stuff[0];
    $respport = $stuff[4];
    $class = $stuff[8];
    $instance = $stuff[9];
    $opcode = $stuff[10];
    $sender = $stuff[11];
    $recipient = $stuff[12];
    $format = $stuff[13];
    $zsig = $stuff[17];
    $mesg = $stuff[18];
    
    $rport = unpack("n", $respport);
    if($opcode eq "PING"){
	print("Ping from $sender\n");
    }
    else{
	print("To: $class, $instance, $recipient\n");
	print("From: $sender [$opcode]\n");
	print("-----$zsig-----\n");
	print("$mesg\n");
    }
    print("******I should respond on port $rport\n");
    $CLIENTACK = &zlong(7);
    &ack("ZEPH0.2\0$CLIENTACK\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}

sub ack {
	local($ack) =@_;
	send(S, "$ack\n", 0, $peeraddr);
}

sub zascii {
	local($retval,$data) = ("",$_[0]);
	while (length($data)>=4) {
		$retval .= " " if ($retval);
		($c1,$c2,$c3,$c4,$data) = unpack("C4a*",$data);
		$retval .= sprintf("0x%02X%02X%02X%02X",$c1,$c2,$c3,$c4);
	}

	if ($data) {
		$retval .= " " if ($retval);
		$retval .= "0x";
		while ($data) {
			($c1,$data) = unpack("Ca*",$data);
			$retval .= sprintf("%02X",$c1);
		}
	}

	return($retval);
}

sub zlong {
	return(&zascii(pack("N",$_[0]))."\0");
}
