#!/usr/bin/perl -w
#
# Copyright (c) 2006-2007 University of Utah and the Flux Group.
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
#
#
# This script is a wrapper around the program-agent to handle
# the runtime knowledge of the event server port on local node

# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }


# Script specific goo.
$EVENTSERVER  = "/usr/local/libexec/pubsubd";
$EVENTPING    = "$BINDIR/eventping";
$PORT_SUMMARY = "/proc/scout/ports/summary";

#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
use libsetup;
use libtmcc;
use librc;

# create a list of active ports: using associate arrays
# for quick serarching.

my %portmap;
open(FP, "< $PORT_SUMMARY");

while ($abc = <FP>) {
    my ($prot, $port, $slice, $type) = split(" ", $abc);

    if ($prot eq "tcp") {
        $portmap["$port"]  = 1;
    }
}

sub start_eventserver {
    my $port = shift;

    # check in the portmap list if it's already active
    if ($portmap[$port]) {
	return 0;
    }
   
    system("$EVENTSERVER -p $port");

    # HACK: allow server to complete the bind/listen, and daemonize.
    sleep(1);

    # check if event server is successfully able to bind the port
    system("$EVENTPING -s localhost -p $port");
    if ($?) {
	return 0;
    }
    
    return $port;
}

sub start_evproxy {
    my $port = shift;

    # start evproxy
    $nodeid = "plab";
    $content = `cat /var/emulab/boot/nodeid`;
    if ($content =~ /plabvm(\d+)-*/) {
	$nodeid .= $1;
    } else {
	fatal("not able to get physical node id");
    }
    
    system("$BINDIR/evproxy -s event-server.emulab.net -n $nodeid -l $port");
    if ($?) {
	fatal("Not able to start evproxy");
    }
    
    # make a tmcc call, and let emulab know of event server port
    if (tmcc(TMCCCMD_ELVINDPORT, "$port") < 0) {
	fatal("Error sending event server port to emulab central!");
    }
    
}

#
# Start the event server and evproxy
#	
if ((-x "$EVENTSERVER") && (-x "$BINDIR/evproxy")) {
    my $res = start_eventserver(16505); # first try 16505
    while ($res == 0) {
	# select a random port between 10000 and 60000
	$num = rand(50000);
	$num = int($num) + 10000;
	$res = start_eventserver($num);
    }

    start_evproxy($res);
}

