Trying to force 32-bit in pack()

Discussion in 'Perl Misc' started by Brad Walton, Oct 13, 2004.

  1. Brad Walton

    Brad Walton Guest

    I am trying to force 32-bit integers in this pack statement:

    pack("iiiaa", 18, 1, 3, "password", "");

    18+2+3 should = 22 bytes sent

    Instead it is only sending 14 bytes. Is there a way to _force_ 32-bits?

    Thanks for any help,
    Brad
     
    Brad Walton, Oct 13, 2004
    #1
    1. Advertising

  2. Brad Walton

    Brad Walton Guest

    > 18+2+3 should = 22 bytes sent

    Typo there.. should be 18+1+3 = 22
     
    Brad Walton, Oct 13, 2004
    #2
    1. Advertising

  3. "Brad Walton" <> wrote in news:AN6dnVxQ75fw-
    :

    > I am trying to force 32-bit integers in this pack statement:
    >
    > pack("iiiaa", 18, 1, 3, "password", "");
    >
    > 18+2+3 should = 22 bytes sent
    >
    > Instead it is only sending 14 bytes.


    How did you come to that conclusion?

    From perldoc -f pack:

    With all types except "a", "A", "Z", "b", "B", "h",
    "H", "@", "x", "X" and "P" the pack function will
    gobble up that many values from the LIST.

    > Is there a way to _force_ 32-bits?


    From the same document:


    l A signed long value.
    L An unsigned long value.
    (This 'long' is _exactly_ 32 bits, which may differ from
    what a local C compiler calls 'long'. If you want
    native-length longs, use the '!' suffix.)

    But this is irrelevant because you have misdiagnosed the problem. Just
    looking at the hex dump of the result of your pack should have given you a
    clue (which is exactly what I did before anything else, because pack is
    magic to me):

    0000000: 1200 0000 0100 0000 0300 0000 7000

    That is 18, 1, 3 and 'p' and '' on a x86 platform.

    The solution is to use:

    pack('iiiZ*Z*', 18, 1, 3, 'password', '');

    On the other hand, if you are sending this stuff over the network you
    probably want something else.

    Sinan.
     
    A. Sinan Unur, Oct 13, 2004
    #3
  4. Brad Walton

    Brad Walton Guest

    > But this is irrelevant because you have misdiagnosed the problem. Just
    > looking at the hex dump of the result of your pack should have given you a
    > clue (which is exactly what I did before anything else, because pack is
    > magic to me):
    >
    > 0000000: 1200 0000 0100 0000 0300 0000 7000
    >
    > That is 18, 1, 3 and 'p' and '' on a x86 platform.
    >
    > The solution is to use:
    >
    > pack('iiiZ*Z*', 18, 1, 3, 'password', '');
    >
    > On the other hand, if you are sending this stuff over the network you
    > probably want something else.
    >
    > Sinan.


    I broke out a packet sniffer and saw this too. And yes, I am sending this
    over a network. I am going to try your suggestion and see what happens. What
    else would you suggest?

    Thanks,
    Brad
     
    Brad Walton, Oct 13, 2004
    #4
  5. "Brad Walton" <> wrote in
    news::

    > And yes, I am sending this over a network. I am going to
    > try your suggestion and see what happens. What else would
    > you suggest?


    Depends on the protocol you are using. That should specify how things get
    interpreted at both ends of the connection.

    Sinan.
     
    A. Sinan Unur, Oct 13, 2004
    #5
  6. Brad Walton

    Brad Walton Guest

    > > And yes, I am sending this over a network. I am going to
    > > try your suggestion and see what happens. What else would
    > > you suggest?

    >
    > Depends on the protocol you are using. That should specify how things get
    > interpreted at both ends of the connection.
    >


    It's a TCP/IP connection. Here's the whole script (with my notes):

    #!/usr/bin/perl -w
    use strict;
    use IO::Socket;

    # Connect to the rcon server
    print "Connecting to server ... ";
    my $sock = new IO::Socket::INET(PeerAddr => '209.209.44.30', PeerPort =>
    '27015', proto => 'tcp',);
    if (!$sock) {
    die "Unable to connect $@\n";
    }
    print "done\n";

    # Now we send something
    # The packet structure is as follows:
    #
    # PACKET {
    # 32bits size; # This is the size of the data to follow
    # # The 32 bits packet size is not included
    # 32bits requestid; # The request identifier. This can be a continuously
    # # incrementing value (I think) Used to map responses
    # # with requests, (I think).
    # 32bits commandid # This rells the server which type of request we are
    # # makeing In the example it is a LOGIN #3
    #
    # Random amounts and types of data follow. The types are allways constant
    # for a particular command id.
    # };
    #
    # Note 1 32bit integer would be a size 4. Four * 8 bits.
    # A char is 1 8 bits to represent the entire ascii table
    #
    # The example packet was a login packet #3 with the following structure
    #
    # COMMAND_LOGIN {
    # 32bits size = (requestid + commandid + password + unknown)
    # (4 + 4 + (8 + 1) + (0 + 1)) # We count the null char.
    # 18; # * 8 bits
    # 32bits request = 1; # next is 2, 3....
    # 32bits command = 3; # COMMAND_LOGIN
    # null terminated char = "password\0"; # \0 == null
    # null terminated char = "\0"; #
    # };
    #
    #

    # Pack packs the data according to a format string
    # integer,integer,integer,null terminated string,null terminated string
    print "Constructing packet ... ";
    my $login_packet = pack('iiiZ*Z*', 18, 1, 3, 'password', '');
    print "done: $login_packet\n";

    # Send on the wire
    print "Sending packet ... ";
    print $sock $login_packet;
    print "done\n";

    # Dirty hack from Alfred_Reynolds program
    # sleep(1);

    print "Waiting for response ... ";
    my $buf;
    if (!$sock->recv($buf, 4)) {
    die "bad recv $@\n";
    }
    my $response_size = unpack("i", $buf);
    if (!$sock->recv($buf, $response_size)) {
    die "bad recv $@\n";
    }
    my ($request_id, $command_response, $string1, $string2) = unpack("iiaa",
    $buf);
    print "received: $request_id, $command_response, $string1, $string2\n";

    exit(0);

    --------------------------

    I am getting proper pack size using Z*.

    thanks, Brad
     
    Brad Walton, Oct 13, 2004
    #6
  7. "Brad Walton" <> wrote in
    news::

    >> > And yes, I am sending this over a network. I am going to
    >> > try your suggestion and see what happens. What else would
    >> > you suggest?

    >>
    >> Depends on the protocol you are using. That should specify how things
    >> get interpreted at both ends of the connection.


    > It's a TCP/IP connection. Here's the whole script (with my notes):


    What is the application protocol?

    > # Pack packs the data according to a format string
    > # integer,integer,integer,null terminated string,null terminated
    > # string
    > print "Constructing packet ... ";
    > my $login_packet = pack('iiiZ*Z*', 18, 1, 3, 'password', '');


    You probably want N rather than i.

    However, your script will likely have other problems.

    > print "Waiting for response ... ";
    > my $buf;
    > if (!$sock->recv($buf, 4)) {
    > die "bad recv $@\n";


    Do you realize that recv is for UDP whereas you have specified a tcp
    socket?

    Sinan.
     
    A. Sinan Unur, Oct 13, 2004
    #7
  8. Brad Walton

    Brad Walton Guest

    > What is the application protocol?

    Not sure how to answer that, but this is what is sent to/from:

    Size,RequestID,Command,String1,String2(String 2 is always null "")

    > Do you realize that recv is for UDP whereas you have specified a tcp
    > socket?


    No, I did not. One problem I am having, is the response is sent without a
    newline. I tried:

    $response = <$sock>;

    But that expects a newline (right?). I need some way to figure out the
    length of data being sent, then read it. I also need to be able to receive
    multiple responses to one request. I got lots of issues...

    Thanks,
    Brad
     
    Brad Walton, Oct 13, 2004
    #8
  9. Brad Walton

    Brad Walton Guest

    "Brad Walton" <> wrote in message
    news:...
    > > What is the application protocol?

    >
    > Not sure how to answer that, but this is what is sent to/from:
    >
    > Size,RequestID,Command,String1,String2(String 2 is always null "")
    >
    > > Do you realize that recv is for UDP whereas you have specified a tcp
    > > socket?

    >
    > No, I did not. One problem I am having, is the response is sent without a
    > newline. I tried:
    >
    > $response = <$sock>;
    >
    > But that expects a newline (right?). I need some way to figure out the
    > length of data being sent, then read it. I also need to be able to receive
    > multiple responses to one request. I got lots of issues...
    >
    > Thanks,
    > Brad


    I got it to work. After some research (emails), I found out it needed
    little-endian 32 bit 'V'. Thanks again for your help. It is appreciated!

    Brad
     
    Brad Walton, Oct 13, 2004
    #9
  10. Brad Walton

    krakle Guest

    "Brad Walton" <> wrote in message news:<>...
    > 18+2+3 should = 22 bytes sent


    It does? 18+2+3=22? :)
     
    krakle, Oct 14, 2004
    #10
  11. Brad Walton

    Joe Smith Guest

    Brad Walton wrote:

    > I got it to work. After some research (emails), I found out it needed
    > little-endian 32 bit 'V'. Thanks again for your help. It is appreciated!


    In the case of a protocol that you've invented yourself, it does not make
    much difference when using V instead of N, as long as both ends agree
    and are the same endian-ness. But if you intend to talk to another
    machine that is not based the the x86 architecture, you need to use
    the network-byte-order (n and N).
    -Joe
     
    Joe Smith, Oct 14, 2004
    #11
  12. Brad Walton

    Ben Morrow Guest

    Quoth Joe Smith <>:
    > Brad Walton wrote:
    >
    > > I got it to work. After some research (emails), I found out it needed
    > > little-endian 32 bit 'V'. Thanks again for your help. It is appreciated!

    >
    > In the case of a protocol that you've invented yourself, it does not make
    > much difference when using V instead of N, as long as both ends agree
    > and are the same endian-ness. But if you intend to talk to another
    > machine that is not based the the x86 architecture, you need to use
    > the network-byte-order (n and N).


    No, both N and V are byte-order-independant (big- and little-endian
    respectively). iIlL are the ones you need to watch when talking to
    different architectures.

    Of course, if you're designing your own protocol you should use N,
    because it's the standard, but if you're following someone else's you
    have no choice.

    Ben

    --
    The cosmos, at best, is like a rubbish heap scattered at random.
    - Heraclitus
     
    Ben Morrow, Oct 14, 2004
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tim Jones
    Replies:
    0
    Views:
    384
    Tim Jones
    Jan 31, 2004
  2. Replies:
    3
    Views:
    1,769
    Timothy Bendfelt
    Jan 19, 2007
  3. Replies:
    9
    Views:
    984
    Juha Nieminen
    Aug 22, 2007
  4. Alexander Farber

    pack 'C3U*' not same as pack 'C3(xC)*'

    Alexander Farber, Jun 23, 2005, in forum: Perl Misc
    Replies:
    2
    Views:
    137
    Ilmari Karonen
    Jun 23, 2005
  5. Replies:
    4
    Views:
    199
    Peter J. Holzer
    Aug 16, 2013
Loading...

Share This Page