biovore has asked for the wisdom of the Perl Monks concerning the following question:

I am writing a UT2K4 Query script in perl. The problem I am having is that the data that is returned is in a binary structure. My goal is to use unpack($template,$query); where $template is the pack/unpack template, and $query is a string of data from the query. format details can be found at http://unreal.student.utwente.nl/UT2003-queryspec.html
The format of this structure is as follows:
4 bytes -- (int) $id
unknown bytes -- (null terminated string) $player
4 bytes -- (int) $ping
4 bytes -- (int) $score
4 bytes -- (int) $stats
this block is repeated for each player in the list. My goal is to use unpack($template,$query); where $template is the pack/unpack template, and $query is a string of data from the query. my main issue is that the ints are in little-endian and the string is in the correct endian. I have tried some different templates and have gotten nothing but junk out. I used pack('H*',$query) to get a hex dump to see what the data should be. more details can be found: http://unreal.student.utwente.nl/UT2003-queryspec.html Any suggestions on how to go about this? I have looked at the resources on the net, but they don't seem to be able to handle the null terminated string. I am begining to wonder if unpack can handle this. I might be able to break each data type into a string and use unpack on just that chunk to get the ints.
Some Example Code to monkey with:
#!/bin/perl -w #A product from the bordom of the BioVorE #UT2K4 Player Server Query -- test use strict; #example player status return from UT2K4 server my $packet = "\x0d\x0a\x80\x0d\x0a\x6a\x69\x6d\x6d\x79\x43\x48\x55\x5 +b\x43\x4f"; $packet .= "\x53\x42\x59\x5d\x2c\x0d\x0a\x0d\x0a\x6a\x61\x57\x41\x7c\x +44\x72"; $packet .= "\x2e\x50\x68\x69\x6c\x30\x20\x4a\x61\x64\x65\x2d\x63\x6c\x +61\x6e"; $packet .= "\x6c\x65\x73\x73\x2c\x40\x20\x20\x20\x6b\x31\x3a\x3a\x73\x +70\x6c"; $packet .= "\x69\x66\x66\x6d\x61\x73\x74\x61\x3a\x3a\x30\x29\x40\x0d\x +0a\xbb"; $packet .= "\xab\x4b\x65\x76\x69\x6e\xbb\xab\x38\x20\x20\x0d\x0a\x20\x +20\x20"; $packet .= "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x41\x79\x65\x43\x61\x +72\x61"; $packet .= "\x6d\x62\x61\x21\x44\x22\x40\x20\x20\x20\x20\x20\x20\xbb\x +62\x53"; $packet .= "\xb0\xc0\xee\x4d\xab\x48\x21\x20\x20\x20\x20\x20\x20\x3d\x +6f\x4e"; $packet .= "\x65\x3d\x46\x6c\x75\x38\x20\x3d\x6f\x4e\x65\x3d\xed\x6c\x +6c\xf9"; $packet .= "\x53\xef\xf8\xf1\x24\x27\xab\xfb\x2e\x4e\x65\x30\xbb\x52\x +65\x64"; $packet .= "\x42\x6c\x75\x65\x0d\x0a\x0d\x0a\x0d\x0a"; #drop first byte.. always 0d $packet = substr($packet,1); #print out the packet in hex chars my $data=0; $data = unpack('H*', $packet ); print $data; print "\n"; # parse out the $packet into varbles # structure format # int -- ID # string -- Player # int -- ping # int -- score # int -- stat # @player_info=unpack($template,$packet)
Peter Fetterer biovore biovore net

Replies are listed 'Best First'.
Re: parsing Binary Structures using unpack
by Zaxo (Archbishop) on Sep 11, 2005 at 05:47 UTC

    Your data doesn't appear to have a null-terminated string in it. At least it doesn't have a null byte.

    Allowing a throwaway byte and an int at the head, and three ints at the tail,

    my $player = substr $packet, 5, -12;
    seems to get a bunch of sane-looking data.

    The ints can be gotten with unpack and substr,

    my $id = unpack 'xV', $packet; my ($ping,$score,$stats) = unpack 'V3', substr $packet, -12;

    Looking at substr $packet, 5 , I suspect your $packet grabber is truncating at the null byte. The last few bytes read "RedBlue\n\n" from what looks like a Mac environment where newline is LFCR.

    After Compline,
    Zaxo

Re: parsing Binary Structures using unpack
by pg (Canon) on Sep 11, 2005 at 05:59 UTC

    Your pattern might be described as "nZ*nnn", but when I

    my @data = unpack("nZ*nnn", $packet); print Dumper(\@data);

    $data[1] contains everything starting from the 6th byte, which indicate there is no \x00 in between.

Re: parsing Binary Structures using unpack
by ambrus (Abbot) on Sep 11, 2005 at 08:13 UTC

    See also perldoc perlpacktut. If you don't have it, you have to get it from a newer version from perl, or read from the web.

Re: parsing Binary Structures using unpack
by dcd (Scribe) on Sep 11, 2005 at 20:28 UTC
    My first question would be, "where/how did you get the data that you put into $packet?" Try looking at data you get using.
       split /\r\n/,$packet
    The data you show doesn't seem to match the documention in the URL you posted