File Coverage

blib/lib/Net/TCP/ConnHandler.pm
Criterion Covered Total %
statement 9 91 9.8
branch 0 34 0.0
condition 0 4 0.0
subroutine 3 16 18.7
pod 7 13 53.8
total 19 158 12.0


line stmt bran cond sub pod time code
1             package Net::TCP::ConnHandler;
2            
3 1     1   27425 use strict;
  1         2  
  1         39  
4 1     1   5 use warnings;
  1         2  
  1         40  
5            
6             our $VERSION = '0.01';
7            
8 1     1   916 use Net::Socket::NonBlock;
  1         51637  
  1         1216  
9            
10             sub new {
11 0     0 1   my $class = shift;
12 0           my %args = @_;
13 0           my $self = {};
14 0           bless($self, $class);
15 0 0         if ($args{PacketUnpackString}) {
    0          
16 0           $self->{unpackstr} = $args{PacketUnpackString};
17 0           delete $args{PacketUnpackString};
18             }
19             elsif ($args{NoMsgType}) {
20 0           $self->{nomsgtype} = 1;
21 0           delete $args{NoMsgType};
22             }
23             else {
24 0           $self->{unpackstr} = "n a*";
25             }
26 0 0         $self->{socknest} = Net::Socket::NonBlock::Nest->new(%args)
27             or die "Error creating sockets nest: $@\n";
28 0           return $self;
29             }
30            
31             sub Connect {
32 0     0 1   my $self = shift;
33 0           my %args = @_;
34 0 0 0       my $socket = $self->{socknest}->Connect(%args)
35             or $self->error("Couldn't connect to '$args{PeerAddr}:$args{PeerPort}': $@\n") and return;
36 0           $self->add_socket($socket);
37 0           return $socket;
38             }
39            
40             sub Listen {
41 0     0 1   my $self = shift;
42 0           my %args = @_;
43 0 0 0       my $socket = $self->{socknest}->Listen(%args)
44             or $self->error("Couldn't listen on port '$args{LocalPort}': $@\n") and return;
45 0           $self->add_socket($socket);
46 0           return $socket;
47             }
48            
49             sub Send {
50 0     0 1   my $self = shift;
51 0           my $socket = shift;
52 0           my $data = shift;
53 0           $socket->Send(pack("N a*", length $data, $data));
54             }
55            
56             sub IO {
57 0     0 1   my $self = shift;
58 0           my $aryref = @_;
59 0           my $recvnum = $self->{socknest}->IO($aryref);
60 0           for my $socket ($self->get_sockets()) {
61 0           my $buf = undef;
62 0 0         if ($socket->{rx} == 0) {
63 0           $buf = $socket->{obj}->Recv(4);
64 0 0         if ($buf) {
    0          
65 0           $socket->{rxlen} = unpack('N', $buf);
66 0           $socket->{rxbuf} = "";
67 0           $socket->{rx} = 1;
68             }
69             elsif (!defined $buf) {
70 0           $socket->Close();
71 0           $self->del_socket($socket);
72             }
73             }
74 0 0         if ($socket->{rx} == 1) {
75 0           my ($ip, $port);
76 0           ($buf, $ip, $port) = $socket->{obj}->Recv($socket->{rxlen});
77 0 0         if ($buf) {
    0          
78 0           $socket->{r_addr} = $ip;
79 0           $socket->{r_port} = $port;
80 0           $socket->{rxlen} -= length $buf;
81 0           $socket->{rxbuf} .= $buf;
82 0 0         if ($socket->{rxlen} == 0) {
83 0           $socket->{rx} = 0;
84 0           my @packet;
85 0 0         if ($self->{unpackstr}) {
86 0           @packet = unpack($self->{unpackstr}, $socket->{rxbuf});
87             }
88 0           else { @packet = ("GENERIC", $socket->{rxbuf}) }
89 0           $self->handle($socket->{obj}, @packet);
90             }
91             }
92             elsif (!defined $buf) {
93 0           $socket->Close();
94 0           $self->del_socket($socket);
95             }
96             }
97             }
98 0           return $recvnum
99             }
100            
101             sub add_socket {
102 0     0 1   $_[0]->{sockets}->{$_[1]}->{obj} = $_[1];
103 0           $_[0]->{sockets}->{$_[1]}->{rx} = 0;
104 0           $_[0]->{sockets}->{$_[1]}->{rxlen} = 0;
105 0           $_[0]->{sockets}->{$_[1]}->{rxbuf} = "";
106             }
107            
108 0     0 0   sub del_socket { delete $_[0]->{sockets}->{$_[1]} }
109 0     0 0   sub get_sockets { values %{$_[0]->{sockets}} }
  0            
110            
111             sub set_handler {
112 0     0 1   my $self = shift;
113 0           my $hlist = shift;
114 0           $self->{handlers}->{$_} = $hlist->{$_} for (keys %$hlist);
115             }
116            
117 0     0 0   sub set_handlers { set_handler(@_) }
118            
119             sub handle {
120 0     0 0   my $self = shift;
121 0           my $socket = shift;
122 0           my $msgtype = shift;
123 0 0         if ($self->is_handled($msgtype)) {
    0          
124 0           $self->{handlers}->{$msgtype}->($self, $socket, @_);
125             }
126             elsif ($self->is_handled('GENERIC')) {
127 0           $self->{handlers}->{'GENERIC'}->($self, $socket, $msgtype, @_);
128             }
129             else {
130 0           $self->error("Couldn't handle msgtype: $msgtype ($socket)\n");
131             }
132             }
133            
134             sub is_handled {
135 0     0 0   my $self = shift;
136 0           my $msgtype = shift;
137 0 0         return 1 if $self->{handlers}->{$msgtype};
138             }
139            
140            
141             sub error {
142 0     0 0   my $self = shift;
143 0 0         if ($self->is_handled('ERROR')) { $self->handle('ERROR', @_) }
  0            
144 0           else { die @_ }
145             }
146            
147             1;
148             __END__