Reputation: 1271
I have a function in Perl that reads a packet from a template in this way:
sub read_packet {
my $contents = shift;
my @decode = unpack('nnnN', $contents);
my $version = $decode[0];
my $identifier = $decode[1];
my $type = $decode[2];
my $size = $decode [3];
@contents = ($version, $identifier, $type, $size);
return (@contents);
}
A change was required to the template in the unpack function. Now $identifier must support 32 bits, so according to PerlMonks: Pack/Unpack Tutorial (aka How the System Stores Data) (N) -> n,N A 16/32 bit value in "network" (big-endian) order.
So the function was rewritten doing this small change. Now, the program that sends the "packet" could be sending 16/32 bit values. The customer required from me to support both 16/32 bit. What can I do to know when a packet contains an 16 or 32 bit identifier?
Upvotes: 2
Views: 202
Reputation: 385917
When the protocol changed in an incompatible manner, the version should have been changed as well. If so, you can use the following:
sub read_packet {
my $contents = shift;
(my $version, $contents) = unpack('na*', $contents);
if ($version < X) {
return ( $version, unpack('nnN', $rest) );
} else {
return ( $version, unpack('NnN', $rest) );
}
}
Otherwise, you'll have the base it on the size of the packet. However, that requires the size of the packet to be communicated, and not always the case. Fortunately, it does appear to be the case here, so you can use the following:
sub read_packet {
my $contents = shift;
return unpack(length($contents) < 12 ? 'nnnN' : 'nNnN', $contents);
}
Upvotes: 2
Reputation: 126722
If those four fields are all that the packet contains then you can check the length of $contents
If the format is nnnN
then the length will be 2 + 2 + 2 + 4 = 10 bytes
If the format is nNnN
then the length will be 2 + 4 + 2 + 4 = 12 bytes
However, if there is data following those four fields then you must try the most commonunpack
template and check the result for sanity, using the alternative template if it fails
Upvotes: 5