#!/usr/bin/perl
#
# HLstatsX - Real-time player and clan rankings and statistics for Half-Life 2
# http://www.hlstatsx.com/
# Copyright (C) 2005-2007 Tobias Oetzel (Tobi@hlstatsx.com)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#

use strict;
no strict 'vars';

use POSIX;
use Getopt::Long;
use Time::Local;
use IO::Socket;
use IO::Select;
require "./raw_send.pm";

$VERSION = "1.00";
$g_version = $VERSION;

$|=1;
Getopt::Long::Configure ("bundling");

##
## Functions
##

sub is_number ($) { ( $_[0] ^ $_[0] ) eq '0' }


sub printEvent
{
	my ($code, $description, $update_timestamp) = @_;
	
	if ($g_debug > 0)
	{
	    if ($update_timestamp > 0)
	    {
  		  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
		  my $timestamp = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
	    } else {
	      my $timestamp = $ev_timestamp;
	    }
		print localtime(time) . "" unless ($timestamp);
		if (is_number($code))
		{
  		  printf("%s: %21s - E%03d: %s\n", $timestamp, $s_addr, $code, $description);
  		} else {
  		  printf("%s: %21s - %s: %s\n", $timestamp, $s_addr, $code, $description);
  		}  
	}
}


#
# void printNotice (string notice)
#
# Prins a debugging notice to stdout.
#

sub printNotice
{
	my ($notice) = @_;
	
	if ($g_debug > 1)
	{
		print ">> $notice\n";
	}
}


##
## MAIN
##

# Options

$opt_help        = 0;
$opt_version     = 0;
$g_debug         = 1;
$g_nodebug       = 0;
$s_ip            = "";
$s_port          = "27510";
$hlx_ip          = ""; # Ip address from your hlx perl deamon

# Usage message

$usage = <<EOT
Usage: hlproxy.pl [OPTION]...
HLstatsX proxy server to send raw sockets

  -h, --help                      display this help and exit
  -v, --version                   output version information and exit
  -d, --debug                     enable debugging output (-dd for more)
  -n, --nodebug                   disables above; reduces debug level
  -a, --address                   Ip address from your hlx perl deamon
EOT
;

# Read Command Line Arguments

GetOptions(
	"help|h"			=> \$opt_help,
	"version|v"			=> \$opt_version,
	"debug|d+"			=> \$g_debug,
	"nodebug|n+"		=> \$g_nodebug,
	"ip|i=s"			=> \$s_ip,
	"port|p=i"			=> \$s_port,
	"timestamp!"		=> \$g_timestamp,
	"t"					=> \$g_timestamp,
	"address|a=s"      => \$hlx_ip
) or die($usage);

if ($opt_help)
{
	print $usage;
	exit(0);
}

if ($opt_version)
{
	print "hlproxy.pl V$g_version\n"
		. "HLstatsX Proxy Server to send raw packets\n"
		. "Copyright (C) 2005 Tobias Oetzel (Tobi@gameme.de)\n\n";
	
	print "\nThis is free software; see the source for copying conditions.  There is NO\n"
		. "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
	
	exit(0);
}

$g_debug -= $g_nodebug;
$g_debug = 0 if ($g_debug < 0);

# Startup

&printEvent("HLXPROXY", "HLXProxy V$g_version starting...", 1);


# Create the UDP socket

if ($s_ip) { $ip = $s_ip . ":"; } else { $ip = "port "; }

$s_socket = IO::Socket::INET->new(
	Proto=>"udp",
	LocalAddr=>"$s_ip",
	LocalPort=>"$s_port"
) or die ("\nCan't setup UDP socket on $ip$s_port: $!\n");
&printEvent("UDP", "Opening UDP listen socket on $ip$s_port ... ok", 1);

# Main data loop

$c = 0;

sub getLine
{
	return 1;
}


$timeout = 0;
while ($loop = &getLine())
{
  if( IO::Select->new($s_socket)->can_read(300) ) {
     $s_socket->recv($s_output, 1024);
     $timeout = 0;
  } else {
    &printEvent("HLPROXY", "No data since 30 seconds");
    $timeout++;
  }

  if ($timeout == 0) 
  {
	  $s_peerhost  = $s_socket->peerhost;
	  $s_peerport  = $s_socket->peerport;
	  $s_addr = "$s_peerhost:$s_peerport";
		
	  if ((substr($s_output, 0, 1) eq chr(0xff)) && (substr($s_output, 1, 1) eq chr(0xff)))  {
	    $s_output = substr($s_output, 2, length($s_output)-2);
	  } else {
	    &printEvent("DATA", "Wrong data, skip paket: ".$s_output);
	    next;
	  }  
	
	  my @data = split chr(0xff), $s_output;
	  #&printEvent("DATA", $s_output);
	  
	  $cmd = $data[0];
	  
	  if (($cmd eq "R") && (@data == 6) && ($s_peerhost eq $hlx_ip))  {
	    my $s_addr  = $data[1];
	    my $s_port  = $data[2];
	    my $cl_addr = $data[3];
	    my $cl_port = $data[4];
	    my $cl_msg  = $data[5];
        my $msg = chr(0xff).chr(0xff).chr(0xff).chr(0xff)."l".$cl_msg.chr(0x00);
        $pork = new pork ("UDP", [$s_addr, $cl_addr, $s_port , $cl_port], $msg);
        $pork->sendPacket();
    	printEvent("SEND", "Send data from server '$s_addr:$s_port' to player at '$cl_addr:$cl_port'", 1);
	  }
  }
  

}

