root/trunk/Sniffer-Postgres/lib/Postgres/Request.pm

Revision 92, 2.5 kB (checked in by jesus, 4 years ago)

Move this into pgtreats

Line 
1 package Postgres::Request;
2
3 use strict;
4 use Data::Dumper;
5
6 sub log {
7   my $self = shift;
8   my $class = ref $self || $self;
9   my $m = shift;
10 #  print "$class: $m\n";
11 }
12 sub logf {
13   my $self = shift;
14   my $fmt = shift;
15   $self->log(sprintf($fmt, @_));
16 }
17
18 my $types = {
19   'B' => { name => 'Bind', parse => sub { ($_[0]->{portal}, $_[0]->{handle}) = unpack("x5Z*Z*", $_[1]); } },
20   'E' => { name => 'Execute', parse => sub { ($_[0]->{handle}, $_[0]->{limit}) = unpack("x5Z*N", $_[1]); }, complete => 1 },
21   'F' => { name => 'Function Call', complete =>1  },
22   'H' => { name => 'Flush' },
23   'P' => { name => 'Parse', parse => \&parse_parse, complete => 1 },
24   'p' => { name => 'Password Message' },
25   'Q' => { name => 'Simple Query', parse => sub { $_[0]->{query} = unpack("x5Z*", $_[1]); }, complete => 1 },
26   'C' => { name => 'Close', complete => 1 },
27   'S' => { name => 'Sync' },
28   'X' => { name => 'Terminate', complete => 1 },
29   'D' => { name => 'Describe', parse => sub { ($_[0]->{describing}, $_[0]->{handle}) = unpack("x5cZ*", $_[1]); } },
30   'd' => { name => 'Copy Data' },
31   'c' => { name => 'Copy Data Completed' },
32   'f' => { name => 'Copy Data Failed' },
33 };
34
35 sub is_complete {
36   my $self = shift;
37   my $t = $types->{$self->{type}};
38   return 1 if($t && $t->{complete});
39   return 0;
40 }
41
42 sub parse_parse {
43   my $self = shift;
44   my $buf = shift;
45   my ($handle, $query, @args) = unpack("x5 Z*Z* n/N", $buf);
46   $self->{handle} = $handle;
47   $self->{query} = $query;
48   $self->{args} = \@args
49 }
50
51 sub parse {
52   my $class = shift;
53   my $buf = shift;
54   my $self = bless { whence => shift }, $class;
55
56   # special case for cancel query
57   if(unpack("N", substr($$buf, 0, 4)) == 16 &&
58      unpack("N", substr($$buf, 4, 4)) == 80877102) {
59     $self->{type} = 'Cancel';
60     $self->{pid} = unpack("N", substr($$buf, 8, 4));
61     return $self;
62   }
63
64   my $type = substr($$buf, 0, 1);
65   my $len = unpack("N", substr($$buf, 1, 4));
66   # short-circuit the short packet.
67   return undef if(length($$buf) - 1 < $len);
68
69   $self->{type} = $type;
70   $self->{len} = $len;
71
72   $self->{query} = '';
73   if(exists $types->{$type}) {
74     my $t = $types->{$type};
75     $class->log("type: " . $t->{name});
76     $t->{parse}->($self, $$buf) if($t->{parse});
77   }
78   else {
79     $class->logf("type: '%s'", $self->{type});
80   }
81   #$class->logf("len: %d", $len);
82   #$class->logf("actual len: %d", length($$buf) - 1);
83   if($len != (length($$buf) - 1)) {
84     substr($$buf, 0, 1 + $len) = '';
85   }
86   else {
87     $$buf = '';
88   }
89   return $self;
90 }
91
92 sub as_string {
93   my $self = shift;
94   return $self->{query};
95 }
96 1;
Note: See TracBrowser for help on using the browser.