#!/usr/bin/perl -w

# Copyright 2004 Andreas Bernauer.  All rights reserved except:
#
# You are free to use this software privately or in a non-profit
# organization.  I would like to hear from you if you want to use this
# software.  You can reach me at andreas.bernauer@gmx.de.

package Collector;
require Exporter;

# Implements a client for the Distributor server.  See there for
# details about protocol and interface descriptions.  If you use this
# class, you don't have to know anything about the protocol but can
# rely on these functions here.
#
# The function you probably want to use is readData, which connects to
# the server, fetches the data and returns with an array of the data.
# The array is empty if there was no other data on the server.

our @ISA=qw(Exporter);
our @EXPORT=qw(readData doConnect wrapper);
our $VERSION = 0.1;

use IO::Socket::INET;


my $verbose = 0;		# internal use

# Connects to a given data server
# Args: remote host, remote port, number of retries
# number of retries defaults to zero.
# Returns: undef, if no connection, socket of connection otherwise
# Example: my $socket = doConnect("hgt.mcb.uconn.edu",  49876)
sub doConnect {
  my ($remote_host, $remote_port, $retries) = @_
    or die "Wrong number of arguments to doConnect (@_)\n";
  $retries = 0 if (!defined($retries));

  my $socket;
  while ($retries >=0) {
    $socket = IO::Socket::INET->new(PeerAddr => $remote_host,
				    PeerPort => $remote_port,
				    Proto => "tcp",
				    Type => SOCK_STREAM);
    last if ($socket);
    warn "Could not connect to $remote_host:$remote_port ($!); $retries retries left.";
    sleep 1;
    $retries--;
  }
  return $socket;
}

# Reads data of data server.
# Args: remote host, remote port.
# Returns: Array of data items got from server.  Data items are
# strings without linebreak
# Example: my @data = readData("hgt.mcb.uconn.edu",  49876)
sub readData {
  my ($remote_host, $remote_port) = @_;
  my $socket = doConnect($remote_host, $remote_port)
    or die "Cannot connect to server, giving up.\n";

  print $socket "HELO 1\r\n";
  my $answer = <$socket>;
  my @result;
  if ($answer =~ /^HELO 1/) {
    print "Got answer '$answer'\n" if ($verbose);
    print $socket "RECV\r\n";
    while (($answer = <$socket>) =~ /^DATA (.*)\r\n/) {
      print "Got answer '$answer'\n" if ($verbose);
      push @result, $1;
    }
  }
  return @result;
}


# Wrapper function that launches program for data items.  The function
# gets @data from the data server and runs system "$command @data".
# NOTE: no checks done on $command.
# Args: command to launch, remote host, remote port
# Returns: true, if we received any data from data server
#          false, if we did not receive any data from data server.
# Example: exit (!wrapper("echo", "hgt.mcb.uconn.edu",  49876));
sub wrapper {
  my $command = shift
    or die "Command missing\n";
  my ($remote_host, $remote_port) = @_;
  # Usually, "hgt.mcb.uconn.edu"  49876
  my @data;
  my $atLeastOnce = 0;
  while (@data = readData($remote_host, $remote_port)) {
    system "$command @data";
    $atLeastOnce = 1;
  }
  return $atLeastOnce;
}

1;
