+ my ($magic, $schema, $type) = eval {unpack 'N N N', $data};
+ return 0 unless $magic == 0xadbccbda && $schema >= 0 && $schema <= 3 && $spec{$type};
+ my $out = $self->unpack($data, $spec{$type}, $origin);
+ dbg($out) if $out && $type != 0;
+
+ return $out;
+}
+
+use constant NAME => 0;
+use constant SORT => 1;
+use constant FUNC => 2;
+use constant LASTTIME => 0;
+use constant MYCALL => 1;
+use constant MYGRID => 2;
+use constant MYQRG => 3;
+
+sub unpack
+{
+ my $self = shift;
+ my $data = shift;
+ my $spec = shift;
+ my $ip = shift;
+
+ my $now = time;
+ my $mycall;
+ my $mygrid;
+ my $myqrg;
+
+ if ($ip) {
+ my $cr = $self->{CR}->{$ip};
+ if ($cr) {
+ $mycall = $cr->[MYCALL];
+ $mygrid = $cr->[MYGRID];
+ $myqrg = $cr->[MYQRG];
+ $cr->[LASTTIME] = $now;
+ }
+ $self->{ip} = $ip
+ } else {
+ delete $self->{ip};
+ }
+
+ my $pos = $self->{unpackpos} || 8;
+ my $out = $pos ? '{' : '';
+
+ foreach my $r (@$spec) {
+ my $v = 'NULL';
+ my $l;
+ my $alpha;
+
+ last if $pos >= length $data;
+
+ if ($r->[SORT] eq 'int32') {
+ $l = 4;
+ ($v) = unpack 'l>', substr $data, $pos, $l;
+ } elsif ($r->[SORT] eq 'int64') {
+ $l = 8;
+ ($v) = unpack 'Q>', substr $data, $pos, $l;
+ } elsif ($r->[SORT] eq 'int8') {
+ $l = 1;
+ ($v) = unpack 'c', substr $data, $pos, $l;
+
+ } elsif ($r->[SORT] eq 'bool') {
+ $l = 1;
+ ($v) = unpack 'c', substr $data, $pos, $l;
+ $v += 0;
+ } elsif ($r->[SORT] eq 'float') {
+ $l = 8;
+ ($v) = unpack 'd>', substr $data, $pos, $l;
+ $v = sprintf '%.3f', $v;
+ $v += 0;
+ } elsif ($r->[SORT] eq 'utf') {
+ $l = 4;
+ ($v) = unpack 'l>', substr $data, $pos, 4;
+ if ($v > 0) {
+ ($v) = unpack "a$v", substr $data, $pos+4;
+ $l += length $v;
+ ++$alpha;
+ } else {
+ $pos += 4;
+ next; # null alpha field
+ }
+ }
+
+ $out .= qq{"$r->[NAME]":};
+ if ($r->[FUNC]) {
+ no strict 'refs';
+ ($v, $alpha) = $r->[FUNC]($self, $v);
+ }
+ $out .= $alpha ? qq{"$v"} : $v;
+ $out .= ',';
+ $pos += $l;
+ }
+
+ return undef unless $mycall;
+
+ $out .= qq{"ocall":"$mycall",} if $mycall;
+ $out .= qq{"ogrid":"$mygrid",} if $mygrid;
+ $out .= qq{"oqrg":"$myqrg",} if $myqrg;
+# $out .= qq{"oip":"$ip",} if $ip;
+
+ $out =~ s/,$//;
+ $out .= '}';
+
+ delete $self->{unpackpos};
+
+ return $out;