Home > Net >  packing an incrementing counter into hex with perl
packing an incrementing counter into hex with perl

Time:06-09

i am trying to create a 12 byte header and i am using pack. everything was going awesome until i needed to include an incrementing value in the pack function..

EDIT:

i have an open ffmpeg pipe that i am capturing the output from. the captured data is going to be a payload that will be encrypted and appended to the end of the header. my loop is not a for loop but i thought i would make it a little easier for the readers to understand.

so let me update the question here in hopes it clears any confusion. if i need to provide any more information let me know.

my $m = 00;
my $n = 00;

while( <$source_audio> ) { 
    if(($n % 16) == 0){
        $m  ; #this should increment when n reaches 0xff
    }
    my $header = pack( 'C C n n C*', 0x80, 0x78, $m, $n, 0x12, 0x34, 0x98, 0x76, 0x01, 0x02, 0x03, 0x04 );
    print $file $header ;
    $n  ;
}

i just need to be able to pack $m and $n so i get the expected output:

80 78 00 01 12 34 98 76 01 02 03 04
80 78 00 02 12 34 98 76 01 02 03 04
80 78 00 03 12 34 98 76 01 02 03 04
80 78 00 04 12 34 98 76 01 02 03 04
80 78 00 05 12 34 98 76 01 02 03 04
... iterating 0x0000 to 0xFFFF ...
80 78 FF FB 12 34 98 76 01 02 03 04
80 78 FF FC 12 34 98 76 01 02 03 04
80 78 FF FD 12 34 98 76 01 02 03 04
80 78 FF FE 12 34 98 76 01 02 03 04
80 78 FF FF 12 34 98 76 01 02 03 04

EDIT2:

this gives me the desired output, but i get errors with strict and warnings enabled:

my $m = 0x00;
my $n = 0x00;

my $message = "this";

while ( <$source_audio> ) {
    my $header = pack('C*', 0x80, 0x78, $m, $n, 0x12, 0x34, 0x98, 0x76, 0x01, 0x02, 0x03, 0x04);
    
    if(($n % 0xFF) == 0 and $n != 0x00){
        $m  ;
    }
    
    $n  ;
print $temp $header;
}
Character in 'C' format wrapped in pack

Solution was exactly as ikegami pointed out:

pack('C C n C*', 0x80, 0x78, $n, 0x12, 0x34, 0x98, 0x76, 0x01, 0x02, 0x03, 0x04);

CodePudding user response:

The problem has nothing to do with pack or your use of it. The problem is that you are miscalculating $m and $n. The warning is the result of $m exceeding 0xFF, which clearly should not happen.

The following properly calculates $m and $n (which I renamed to $hi and $lo for reasons that will soon become obvious):

my $hi = 0x00;
my $lo = 0x00;
while ( <$source_audio> ) {
    my $header = pack( 'C*',
       0x80, 0x78, $hi, $lo, 0x12, 0x34, 0x98, 0x76, 0x01, 0x02, 0x03, 0x04 );
    
    ...

    if ( $lo == 0xFF ) {
        $lo = 0;
          $hi;
    } else {
          $lo;
    }
}

This could also be written as follows:

    $lo = ( $lo   1 ) & 0xFF;
      $hi if !$lo;

But we're really just incrementing one number which is stored across two octets.

my $n = 0;
while ( <$source_audio> ) {
    my $hi = $n >> 8;
    my $lo = $n & 0xFF;
    my $header = pack( 'C*',
       0x80, 0x78, $hi, $lo, 0x12, 0x34, 0x98, 0x76, 0x01, 0x02, 0x03, 0x04 );
    
    ...

      $n;
}

But let's leave the packing to pack! We're trying to store the value as a 16 bit unsigned int using big-endian byte order. Consulting Formats for Packing and Unpacking Numbers or the documentation for pack shows we can use S> or n.

my $n = 0;
while ( <$source_audio> ) {
   my $header = pack( 'C C n C*',
      0x80, 0x78, $n, 0x12, 0x34, 0x98, 0x76, 0x01, 0x02, 0x03, 0x04 );
    
    ...

      $n;
}
  • Related