#!/usr/bin/perl

use IO::Socket;
use Data::Dumper;
use Data::Hexdumper;

sub hex2dec($) { return hex $_[0] }

$sock = IO::Socket::INET->new(
	LocalAddr => '0.0.0.0',
	LocalPort => 9910,
	Proto => 'udp'
) || die "Fail!: $@";

while($sock->recv($data, 4096)) {
	print hexdump($data);
	($cmd, $len, $uid, $cnt_out, $unkn1, $unkn2, $cnt_in, $payload) = unpack("CCnnnnnC*", $data);
	($port, $ipaddr) = sockaddr_in($sock->peername);
	$len = (($cmd & 0x07) << 8) + $len;
	$cmd = $cmd & 0xF8;
	printf("CMD: %X\n", $cmd);
	printf("LEN: %4d (%03X) - UID: %X\n", $len, $len, $uid);
	printf("CNT_OUT: %04X - CNT_IN: %04X\n", $cnt_out, $cnt_in);
	printf("UNKN1: %04X - UNKN2: %04X\n", $unkn1, $unkn2);

	$rcmd = 0;

	if ($cmd == 0x10) {
		# Hello
		$rcmd     = 0x10;
		$rpayload = '0300000000000000';
		$rcnt_out = 0;
		$rcnt_in  = 0;
		$runkn2   = 0;
		$ruid     = $uid;
	}

	if ($cmd == 0x30) {
		$rcmd     = 0x30;
		$rpayload = '0200000100000000';
		$rcnt_out = 0;
		$rcnt_in  = 0;
		$runkn2   = 0x0023;
		$ruid     = $uid;
	}

	if ($cmd == 0x08) {
		$rcmd     = 0x80;
		$rpayload = '';
		$rcnt_out = $cnt_in;
		$rcnt_in  = 0;
		$runkn1   = 0x0;
		$runkn2   = 0x0023;
		$ruid     = $uid;
	}

	if ($rcmd) {
		$rlen = 12 + (length($rpayload) / 2);
		$rbin = ($rcmd & 0xF8) + (($rlen >> 8) & 0x7);
		$rhead = sprintf("%02X%02X%04X%04X%04X%04X%04X",
			$rcmd, $rlen, $ruid, $rcnt_out, $runkn1, $runkn2, $rcnt_in);
		print "Sending: " . $rhead . $rpayload . "\n";
		$rpkt = pack("H*", $rhead . $rpayload);
		$sock->send($rpkt);
	}
}

exit 0;
