2 # Copyright (C) 2006-2008 Georgia Public Library Service
4 # Author: David J. Fiander
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of version 2 of the GNU General Public
8 # License as published by the Free Software Foundation.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public
16 # License along with this program; if not, write to the Free
17 # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 package Sip::Checksum;
25 use integer; # important
27 our @ISA = qw(Exporter);
28 our @EXPORT_OK = qw(checksum verify_cksum);
34 printf STDERR "# %16s: %016s %4.4s %6s\n",
36 substr(sprintf("%b", $var), -16),
37 uc substr(sprintf("%4.4x",$var), -4),
41 sub debug_split_print {
45 foreach(split('', $line)) {
48 if (scalar(@row) == 10) {
53 scalar(@row) and push @rows, \@row;
56 print map {" $_ "} @$_;
57 printf "\n%-50s", join '', map {sprintf " %3d ", $_} map {$subtotal += ord($_); ord($_)} @$_;
58 printf "= %4d\n\n", $subtotal;
60 printf "%56d\n", $total;
67 # my $u = unpack('%16U*', $pkt);
68 my $u = unpack('%U*', $pkt);
69 my $check = uc substr sprintf("%x", ~$u+1), -4;
71 my $total = debug_split_print($pkt);
72 $total == $u or warn "Internal error: mismatch between $total and $u";
73 printf STDERR "# checksum('$pkt')\n# %34s HEX DECIMAL\n", 'BINARY';
74 debug_print("ascii sum", $u );
75 debug_print("binary invert", ~$u );
76 debug_print("add one", ~$u+1);
77 printf STDERR "# %39s\n", $check;
81 # return (-unpack('%16U*', $pkt) & 0xFFFF);
89 return 0 if (not defined($pkt) or substr($pkt, -6, 2) ne "AZ"); # No checksum at end
91 # Convert the checksum back to hex and calculate the sum of the
92 # pack without the checksum.
93 $cksum = hex(substr($pkt, -4));
94 $shortsum = unpack("%16C*", substr($pkt, 0, -4));
96 # The checksum is valid if the hex sum, plus the checksum of the
97 # base packet short when truncated to 16 bits.
98 return (($cksum + $shortsum) & 0xFFFF) == 0;
106 # Some simple test data
110 my $cksum = checksum($testpkt);
111 my $fullpkt = sprintf("%s%4X", $testpkt, $cksum);
113 print $fullpkt, "\n";