

package Console;
use IO::Socket;
use strict;

# Commands
my $CMD_LOGIN 	= "c;";
my $CMD_SPY   	= "cs";
my $CMD_FRW   	= "cf";
my $CMD_REPLAYALL   	= "cR";


sub new {
	shift;
	my ($v1, $v2, $v3, $v4, $v5) = @_;
	($v5 = "consoles/$v1/$v2") if not $v5;
	my $con = {                        
		"server"         => $v1,            
		"console"        => $v2,
		"user"           => $v3,
		"password"       => $v4,
		"logfilename"    => $v5,
		"sock"		     => undef,
		"logfile"        => undef,
	};

	bless $con, 'Console';   # Tag object with pkg name
	return $con;                     # Return object
}
sub promote {
#...
}

sub getUser {
	my $con = shift;
	return $con->{'user'};
}

sub setLogFileName {
	my $con = shift;
	$con->{'logfilename'} = $_[0];
	return;
}

sub getServer {
	my $con = shift;
	return $con->{'server'};
}

sub getName {
	my $con = shift;
	return $con->{'console'};
}

sub isConnected {
	my $con = shift;

	$con->{sock} ;
}

sub getSocket {
	my $con = shift;

	$con->{sock} ;
}

sub getLogFile {
	my $con = shift;
	if($con->{logfile}) {
		return $con->{logfile};
	} else {
		return undef;
	}
}

sub stream {
	return;
}


#
# Implement enough of the portcommander protocol
# to attach to the required console (or die trying),
# return the live socket.
#
sub connect {
	my $con = shift;

	my $SERVER  = $con->{'server'};
	my $CONSOLE = $con->{'console'};
	my $USER    = $con->{'user'}; 
	my $PASS    = $con->{'password'};
	#
	# Create the socket to the main server
	# We'll recoeve a port number then connect to secondary
	# server for console data
	#
	my $sock = new IO::Socket::INET (PeerAddr => $SERVER,
								 PeerPort => 782,
								 Proto => 'tcp',) or 
								 return undef;
	
	# We do not want buffered output to socket
	$sock->autoflush();

	($_ = <$sock>) ;
	return undef unless /ok/ ;

	# Specify console name
	print $sock "call:$CONSOLE\n";

	# Only valid reply is a port number,
	# stick that in $1.
	($_ = <$sock>);
	return undef  unless /^(\d+)/ ;

	close($sock);


	$sock = new IO::Socket::INET (PeerAddr => $SERVER,
								 PeerPort => $1,
								 Proto => 'tcp',) or
		return undef;

	$sock->autoflush();
	setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1);

	($_ = <$sock>) ;
	return unless /ok/ ;

	# tell server we wish to log in
	print $sock $CMD_LOGIN;

	# TODO: test reply.
	($_ = <$sock>) ;


	# specify user name
	print $sock "$USER\n";
	($_ = <$sock>) ;

	if (/^host:/) {
		print $sock "$CONSOLE\n";

		#TODO
		#validate we are connected
		#to the console
		($_ = <$sock>) ;
	}

	if (/^passwd:/) {
		print $sock "$PASS\n";

		($_ = <$sock>) ;
		return undef if (/Sorry/) ;
	}

	# At this point we are connected.  We
	# now want to convert ourselves to "spy" mode
	print $sock $CMD_SPY;

	# TODO: test reply.
	($_ = <$sock>) ;

	$con->{'sock'} = $sock;
}

sub forceReadWrite {
	my $con = shift;
	print {$con->{'sock'}} $CMD_FRW;
	return;
}

sub closeSocket {
	my $con = shift;
	close($con->{'sock'}) if $con->{'sock'};
	$con->{'sock'} = undef;
	return;
}

sub closeLogFile {
	my $con = shift;
	close($con->{'logfile'}) if $con->{'logfile'};
	return;
}

sub openLogFile {
	my $con = shift;
	if(!$con->{logfilename}) {
		return undef;
	}

	open($con->{logfile}, ">>".$con->{logfilename}) 
		or return undef;

}

sub dumpInfo {
	my $con = shift;

	printf("%s\@%s %s/%s %s -> %s\n",
		$con->{console},
		$con->{server},
		$con->{user},
		$con->{password},
		$con->{sock} ? "connected" : "not connected",
		$con->{logfilename});

	return;
}

return 1;
