File Coverage

blib/lib/IO/Stream/Proxy/SOCKSv4.pm
Criterion Covered Total %
statement 38 82 46.3
branch 0 20 0.0
condition 0 3 0.0
subroutine 13 18 72.2
pod 1 3 33.3
total 52 126 41.2


line stmt bran cond sub pod time code
1             package IO::Stream::Proxy::SOCKSv4;
2 2     2   168746 use 5.010001;
  2         15  
3 2     2   9 use warnings;
  2         4  
  2         41  
4 2     2   8 use strict;
  2         4  
  2         30  
5 2     2   541 use utf8;
  2         12  
  2         9  
6 2     2   49 use Carp;
  2         4  
  2         129  
7              
8             our $VERSION = 'v2.0.1';
9              
10 2     2   372 use IO::Stream::const;
  2         6636  
  2         11  
11 2     2   636 use IO::Stream::EV;
  2         25993  
  2         61  
12 2     2   11 use Scalar::Util qw( weaken );
  2         4  
  2         99  
13              
14 2     2   10 use constant VN => 0x04; # SOCKS protocol version number (4)
  2         3  
  2         91  
15 2     2   17 use constant CD => 0x01; # SOCKS protocol command code (CONNECT)
  2         3  
  2         71  
16 2     2   9 use constant REPLY_LEN=> 8; # SOCKS protocol reply length (bytes)
  2         3  
  2         73  
17 2     2   11 use constant REPLY_VN => 0; # SOCKS protocol reply code version
  2         3  
  2         103  
18 2     2   9 use constant REPLY_CD => 90;# SOCKS protocol reply code 'request granted'
  2         3  
  2         1116  
19              
20              
21             sub new {
22 0     0 1   my ($class, $opt) = @_;
23             croak '{host}+{port} required'
24             if !defined $opt->{host}
25             || !defined $opt->{port}
26 0 0 0       ;
27             my $self = bless {
28             host => undef,
29             port => undef,
30             userid => q{},
31 0           %{$opt},
  0            
32             out_buf => q{}, # modified on: OUT
33             out_pos => undef, # modified on: OUT
34             out_bytes => 0, # modified on: OUT
35             in_buf => q{}, # modified on: IN
36             in_bytes => 0, # modified on: IN
37             ip => undef, # modified on: RESOLVED
38             is_eof => undef, # modified on: EOF
39             _want_write => undef,
40             }, $class;
41 0           return $self;
42             }
43              
44             sub PREPARE {
45 0     0 0   my ($self, $fh, $host, $port) = @_;
46 0 0         croak '{fh} already connected'
47             if !defined $host;
48 0           $self->{_slave}->PREPARE($fh, $self->{host}, $self->{port});
49             IO::Stream::EV::resolve($host, $self, sub {
50 0     0     my ($self, $ip) = @_;
51 0           $self->{_master}{ip} = $ip;
52             $self->{out_buf} = pack 'C C n CCCC Z*',
53 0           VN, CD, $port, split(/[.]/xms, $ip), $self->{userid};
54 0           $self->{_slave}->WRITE();
55 0           });
56 0           return;
57             }
58              
59             sub WRITE {
60 0     0     my ($self) = @_;
61 0           $self->{_want_write} = 1;
62 0           return;
63             }
64              
65             sub EVENT {
66 0     0 0   my ($self, $e, $err) = @_;
67 0           my $m = $self->{_master};
68 0 0         if ($err) {
69 0           $m->EVENT(0, $err);
70             }
71 0 0         if ($e & IN) {
72 0 0         if (length $self->{in_buf} < REPLY_LEN) {
73 0           $m->EVENT(0, 'socks v4 proxy: protocol error');
74             } else {
75 0           my ($vn, $cd) = unpack 'CC', $self->{in_buf};
76 0           substr $self->{in_buf}, 0, REPLY_LEN, q{};
77 0 0         if ($vn != REPLY_VN) {
    0          
78 0           $m->EVENT(0, 'socks v4 proxy: unknown version of reply code');
79             }
80             elsif ($cd != REPLY_CD) {
81 0           $m->EVENT(0, 'socks v4 proxy: error '.$cd);
82             }
83             else {
84 0           $e = CONNECTED;
85 0 0         if (my $l = length $self->{in_buf}) {
86 0           $e |= IN;
87 0           $m->{in_buf} .= $self->{in_buf};
88 0           $m->{in_bytes} += $l;
89             }
90 0           $m->EVENT($e);
91 0           $self->{_slave}->{_master} = $m;
92 0           weaken($self->{_slave}->{_master});
93 0           $m->{_slave} = $self->{_slave};
94 0 0         if ($self->{_want_write}) {
95 0           $self->{_slave}->WRITE();
96             }
97             }
98             }
99             }
100 0 0         if ($e & EOF) {
101 0           $m->{is_eof} = $self->{is_eof};
102 0           $m->EVENT(0, 'socks v4 proxy: unexpected EOF');
103             }
104 0           return;
105             }
106              
107              
108             1; # Magic true value required at end of module
109             __END__