#!/usr/local/bin/perl
require('tcpsockets.pl');

$crosslog="/dev/null";
$crossbinport = 13326;
$crosservport = 3326;
$writeamount = 10240; # Blocksize to write when transferring font.

$crossfontname = "/usr/lib/X11/fonts/crossfire.bdf";

open(CROSSFONT,$crossfontname) || die("Unable to open $crossfontname\n");

$bak = $/;$/=0377;
$crossfont = <CROSSFONT>;
$/ = $bak;

$crossfontlen = length($crossfont);
print "Crossfontlen = ", $crossfontlen , "\n";
close(CROSSFONT);

$| = 1;

$crosspid = open(CROSSSERVER,"/home/root/bin/crossfire -server -f 2>&1 |");

print "Waiting ($crosservport)....\n";

sleep 1;

$crossconn = &tcpsockets'getconnection("localhost",$crossbinport);

die("No Connection available???\n") unless defined $crossconn;

$oldfh = select($crossconn);$|=1;select($oldfh);

$acceptsocket = &tcpsockets'getacceptor($crosservport,1);
setsockopt($acceptsocket,&SO_REUSEADDR,undef,undef);

$rconns{$acceptsocket} = fileno($acceptsocket);
$rconns{CROSSSERVER} = fileno(CROSSSERVER);

while(1) {
    $rin = &fhbits(keys %rconns);
    $win = &fhbits(keys %wconns);
    $ein = $rin|$win;
    print "Selecting...\n";
    $nfound = select($rout=$rin,$wout=$win,$eout=$ein,undef);
    print "Select returned ($nfound)\n";
    undef @rdels;
    undef @wdels;
    while (($key,$value) = each %rconns) {
	if (vec($rout,$value,1)==1) {
	    print "Hir:$key,$value\n";
	    &handlerconn($key);
	}
    }
    foreach $_ (@rdels) {
	close($_);
	delete $rconns{$_};
    }
    while (($key,$value) = each %wconns) {
	if (vec($wout,$value,1)==1) {
	    print "Hiw:$key,$value\n";
	    &handlewconn($key);
	}
    }
    foreach $_ (@wdels) {
	close($_);
	delete $wconns{$_};
    }
# Check for errors
    while (($key,$value) = each %rconns) {
	if (vec($eout,$value,1)==1) {
	    print "Error on $key\n";
	    close($key);
	    delete $rconns{$key};
	    &recrossfire if (fileno($fh)==fileno(CROSSSERVER));
	}
    }
    while (($key,$value) = each %wconns) {
	if (vec($eout,$value,1)==1) {
	    print "Error on $key\n";
	    close($key);
	    delete $wconns{$key};
	}
    }
}

sub handlerconn {
    local($fh) = @_;
    if (fileno($fh) == fileno($acceptsocket)) {
	print "($fh,$acceptsocket)Accepting Connection...\n";
	local($afh) = &gensym'get;
	($addr = accept($afh,$acceptsocket)) || die $!;
	print "accept ok\n";

	$oldfh=select($afh);$|=1;select($oldfh);
	@inetaddr = &tcpsockets'getinetaddr($addr);
	print "Connected to @inetaddr\n";
	$rconns{$afh} = fileno($afh);
	return;
    }
    if (fileno($fh) == fileno(CROSSSERVER)) {
	$_ = <CROSSSERVER>;
        unless (defined $_) {
	    &recrossfire;
	    return;
	}
	chop $_;
	print "Crossfire says:'$_'\n";
	return;
    }
    if (defined($rconns{$fh})) {
	$_ = <$fh>;
	s/(\n|\r)*//iog;
	print "Read in $_\n";
	if (/^quit$/io) {
	    push(@rdels,$fh);
	    return;
	}
	if (/^window (.*)$/io) {
	    $_ = $1;
	    $_ .= ":0.0" unless $_=~ /\:\d(\.\d)?$/o;
	    print "Trying to add $_\n";
	    return unless &checkcrossfire;
	    print $crossconn "$_\n";
	    print "Sent out command\n";
	    return;
	}
	if (/^sendfont (\d+\.\d+\.\d+\.\d+) (\d+)$/io) {
	    $datasocket = &open_send_data_socket($1,$2);
	    $wconns{$datasocket} = fileno($datasocket);
	    $wpos{$datasocket} = 0;
	    return;
	}
	print ("Generated bad request\n");
	push(@rdels,$fh);
	return;
    }
    die("Didn't know how to handle connetion $fh," . fileno($fh) . "\n");
}

sub handlewconn {
    local($fh) = @_;

    if (defined($wconns{$fh})) {
#	print "Writefont ($writeamount,$wpos{$fh})\n";
	$x = print $fh substr($crossfont,$wpos{$fh},$writeamount);
	$wpos{$fh} += $writeamount;
	if (($x==0)||($wpos{$fh}>$crossfontlen)) {
	    push(@wdels,$fh);
	}
	return;
    }
    die("Didn't know how to handle connection $fh," . fileno($fh) . "\n");
}

sub fhbits {
    local (@fhlist) = @_;
    local($bits);
    for (@fhlist) {
	vec($bits,fileno($_),1) = 1;
    }
    $bits;
}

sub open_send_data_socket {
    local($them,$port) = @_;

    print "Opening data socket to $them,$port.\n";
    $datasocket = &tcpsockets'getconnection($them,$port);
    return $datasocket;
}

sub recrossfire {
    print "Crossfire Died, Restarting\n";

    close(CROSSSERVER);
    close($crossconn);

    $crosspid = open(CROSSSERVER,"./crossfire -server 2>&1 |");
    
    print "Waiting ($crosservport)....\n";
    
    sleep 1;
    
    $crossconn = &tcpsockets'getconnection("localhost",$crossbinport);
    
    die("No Connection available???\n") unless defined $crossconn;
    
    $oldfh = select($crossconn);$|=1;select($oldfh);
    
    $rconns{CROSSSERVER} = fileno(CROSSSERVER);
}

sub checkcrossfire {
    return 1;
}
