File Coverage

blib/lib/Net/EmptyPort.pm
Criterion Covered Total %
statement 70 71 98.5
branch 39 48 81.2
condition 25 30 83.3
subroutine 13 13 100.0
pod 5 5 100.0
total 152 167 91.0


line stmt bran cond sub pod time code
1             package Net::EmptyPort;
2 19     19   47268 use strict;
  19         38  
  19         489  
3 19     19   116 use warnings;
  19         45  
  19         537  
4 19     19   103 use base qw/Exporter/;
  19         38  
  19         1419  
5 19     19   9007 use IO::Socket::IP;
  19         268489  
  19         92  
6 19     19   7528 use Time::HiRes ();
  19         1054  
  19         12494  
7              
8             our @EXPORT = qw/ can_bind empty_port check_port wait_port /;
9             our @EXPORT_OK = qw/ listen_socket /;
10              
11             sub can_bind {
12 7     7 1 4450     my ($host, $port, $proto) = @_;
13             # The following must be split across two statements, due to
14             # https://rt.perl.org/Public/Bug/Display.html?id=124248
15 7         23     my $s = _listen_socket($host, $port, $proto);
16 7         4079     return defined $s;
17             }
18              
19             sub _listen_socket {
20 30     30   91     my ($host, $port, $proto) = @_;
21 30   100     194     $port ||= 0;
22 30   100     111     $proto ||= 'tcp';
23 30 100       536     IO::Socket::IP->new(
    50          
24                     (($proto eq 'udp') ? () : (Listen => 5)),
25                     LocalAddr => $host,
26                     LocalPort => $port,
27                     Proto => $proto,
28                     V6Only => 1,
29                     (($^O eq 'MSWin32') ? () : (ReuseAddr => 1)),
30                 );
31             }
32              
33             sub listen_socket {
34 1     1 1 3     my ($host, $proto) = @{$_[0]}{qw(host proto)};
  1         4  
35 1 50       4     $host = '127.0.0.1' unless defined $host;
36 1         4     return _listen_socket($host, undef, $proto);
37             }
38              
39             # get a empty port on 49152 .. 65535
40             # http://www.iana.org/assignments/port-numbers
41             sub empty_port {
42 26 100 100 26 1 5711     my ($host, $port, $proto) = @_ && ref $_[0] eq 'HASH' ? ($_[0]->{host}, $_[0]->{port}, $_[0]->{proto}) : (undef, @_);
43 26 100       112     $host = '127.0.0.1'
44                     unless defined $host;
45 26 100       115     $proto = $proto ? lc($proto) : 'tcp';
46              
47 26 100       92     if (defined $port) {
48             # to ensure lower bound, check one by one in order
49 4 100 100     26         $port = 49152 unless $port =~ /^[0-9]+$/ && $port < 49152;
50 4         15         while ( $port++ < 65000 ) {
51             # Remote checks don't work on UDP, and Local checks would be redundant here...
52 4 50 66     17             next if ($proto eq 'tcp' && check_port({ host => $host, port => $port }));
53 4 50       14             return $port if can_bind($host, $port, $proto);
54                     }
55                 } else {
56             # kernel will select an unused port
57 22         123         while ( my $sock = _listen_socket($host, undef, $proto) ) {
58 22         20171             $port = $sock->sockport;
59 22         1432             $sock->close;
60 22 50 33     892             next if ($proto eq 'tcp' && check_port({ host => $host, port => $port }));
61 22         190             return $port;
62                     }
63                 }
64 0         0     die "empty port not found";
65             }
66              
67             sub check_port {
68 109 100 100 109 1 1301     my ($host, $port, $proto) = @_ && ref $_[0] eq 'HASH' ? ($_[0]->{host}, $_[0]->{port}, $_[0]->{proto}) : (undef, @_);
69 109 100       381     $host = '127.0.0.1'
70                     unless defined $host;
71 109 100       417     $proto = $proto ? lc($proto) : 'tcp';
72              
73             # for TCP, we do a remote port check
74             # for UDP, we do a local port check, like empty_port does
75 109 0       1342     my $sock = ($proto eq 'tcp') ?
    50          
76                     IO::Socket::IP->new(
77                         Proto => 'tcp',
78                         PeerAddr => $host,
79                         PeerPort => $port,
80                         V6Only => 1,
81                     ) :
82                     IO::Socket::IP->new(
83                         Proto => $proto,
84                         LocalAddr => $host,
85                         LocalPort => $port,
86                         V6Only => 1,
87                         (($^O eq 'MSWin32') ? () : (ReuseAddr => 1)),
88                     )
89                 ;
90              
91 107 100       68869     if ($sock) {
92 16         414         close $sock;
93 16         150         return 1; # The port is used.
94                 }
95                 else {
96 91         578         return 0; # The port is not used.
97                 }
98              
99             }
100              
101             sub _make_waiter {
102 22     22   78     my $max_wait = shift;
103 22         45     my $waited = 0;
104 22         60     my $sleep = 0.001;
105              
106                 return sub {
107 87 100 100 87   624         return 0 if $max_wait >= 0 && $waited > $max_wait;
108              
109 82         17291213         Time::HiRes::sleep($sleep);
110 82         679         $waited += $sleep;
111 82         301         $sleep *= 2;
112              
113 82         458         return 1;
114 22         428     };
115             }
116              
117             sub wait_port {
118 22     22 1 3322     my ($host, $port, $max_wait, $proto);
119 22 100 100     419     if (@_ && ref $_[0] eq 'HASH') {
    100          
120 18         129         ($host, $port, $max_wait, $proto) = ($_[0]->{host}, $_[0]->{port}, $_[0]->{max_wait}, $_[0]->{proto});
121                 } elsif (@_==4) {
122             # backward compat.
123 1         4         ($port, (my $sleep), (my $retry), $proto) = @_;
124 1         4         $max_wait = $sleep * $retry;
125                 } else {
126 3         14         ($port, $max_wait, $proto) = @_;
127                 }
128 22 100       151     $host = '127.0.0.1' unless defined $host;
129 22   100     116     $max_wait ||= 10;
130 22 100       147     $proto = $proto ? lc($proto) : 'tcp';
131 22         128     my $waiter = _make_waiter($max_wait);
132              
133 22         86     while ( $waiter->() ) {
134 82 50 33     1551         if ($^O eq 'MSWin32' && defined($port) ? `$^X -MTest::TCP::CheckPort -echeck_port $host $port $proto` : check_port({ host => $host, port => $port, proto => $proto })) {
    100          
135 16         184             return 1;
136                     }
137                 }
138 5         69     return 0;
139             }
140              
141             1;
142              
143             __END__
144            
145             =encoding utf8
146            
147             =head1 NAME
148            
149             Net::EmptyPort - find a free TCP/UDP port
150            
151             =head1 SYNOPSIS
152            
153             use Net::EmptyPort qw(empty_port check_port);
154            
155             # get a socket listening on a random free port
156             my $socket = listen_socket();
157            
158             # get a random free port
159             my $port = empty_port();
160            
161             # check if a port is already used
162             if (check_port(5000)) {
163             say "Port 5000 already in use";
164             }
165            
166             =head1 DESCRIPTION
167            
168             Net::EmptyPort helps finding an empty TCP/UDP port.
169            
170             =head1 METHODS
171            
172             =over 4
173            
174             =item C<< listen_socket() >>
175            
176             =item C<< listen_socket(\%args) >>
177            
178            
179             my $socket = listen_socket();
180            
181             Returns a socket listening on a free port.
182            
183             The function recognizes the following keys in the hashref argument.
184            
185             =over 4
186            
187             =item C<< host >>
188            
189             The address on which to listen. Default is C<< 127.0.0.1 >>.
190            
191             =item C<< proto >>
192            
193             Name of the protocol. Default is C<< tcp >>.
194             You can get an UDP socket by specifying C<< udp >>.
195            
196             =back
197            
198             =item C<< empty_port() >>
199            
200             =item C<< empty_port(\%args) >>
201            
202             =item C<< empty_port($port) >>
203            
204             =item C<< empty_port($port, $proto) >>
205            
206             my $port = empty_port();
207            
208             Returns a port number that is NOT in use.
209            
210             The function recognizes the following keys when given a hashref as the argument.
211            
212             =over 4
213            
214             =item C<< host >>
215            
216             specifies the address on which the search should be performed. Default is C<< 127.0.0.1 >>.
217            
218             =item C<< port >>
219            
220             Lower bound of the search for an empty port. If omitted, the function searches for an empty port within 49152..65535.
221            
222             See L<http://www.iana.org/assignments/port-numbers>
223            
224             =item C<< proto >>
225            
226             Name of the protocol. Default is C<< tcp >>. You can find an empty UDP port by specifying C<< udp >>.
227            
228             =back
229            
230             To maintain backwards compatibility, the function accepts scalar arguments as well. For example, you can also find an empty UDP port by specifying the protocol as
231             the second parameter:
232            
233             my $port = empty_port(1024, 'udp');
234             # use 49152..65535 range
235             my $port = empty_port(undef, 'udp');
236            
237             =item C<< check_port(\%args) >>
238            
239             =item C<< check_port($port) >>
240            
241             =item C<< check_port($port, $proto) >>
242            
243             my $true_or_false = check_port(5000);
244            
245             Checks if the given port is already in use. Returns true if it is in use (i.e. if the port is NOT free). Returns false if the port is free.
246            
247             The function recognizes the following keys when given a hashref as the argument.
248            
249             =over 4
250            
251             =item C<< host >>
252            
253             specifies the address on which the search should be performed. Default is C<< 127.0.0.1 >>.
254            
255             =item C<< port >>
256            
257             specifies the port to check. This argument is mandatory.
258            
259             =item C<< proto >>
260            
261             name of the protocol. Default is C<< tcp >>.
262            
263             =back
264            
265             To maintain backwards compatibility, the function accepts scalar arguments as well in the form described above.
266            
267             =item C<< wait_port(\%args) >>
268            
269             =item C<< wait_port($port) >>
270            
271             =item C<< wait_port($port, $max_wait) >>
272            
273             =item C<< wait_port($port, $max_wait, $proto) >>
274            
275             Waits until a particular port becomes ready to connect to. Returns true if the port becomes ready, or false if otherwise.
276            
277             The function recognizes the following keys when given a hashref as the argument.
278            
279             =over 4
280            
281             =item C<< host >>
282            
283             specifies the address on which the search should be performed. Default is C<< 127.0.0.1 >>.
284            
285             =item C<< port >>
286            
287             specifies the port to check. This argument is mandatory.
288            
289             =item C<< max_wait >>
290            
291             maximum seconds to wait for (default is 10 seconds). Pass a negative value to wait infinitely.
292            
293             =item C<< proto >>
294            
295             name of the protocol. Default is C<< tcp >>.
296            
297             =back
298            
299             To maintain backwards compatibility, the function accepts scalar arguments as well in the form described above.
300            
301             B<Incompatible changes>: Before 2.0, C<< wait_port($port:Int[, $sleep:Number, $retry:Int, $proto:String]) >> is a signature.
302            
303             =item C<< can_bind($host) >>
304            
305             =item C<< can_bind($host, $port) >>
306            
307             =item C<< can_bind($host, $port, $proto) >>
308            
309             Checks if the application is capable of binding to given port.
310            
311             =back
312            
313             =head1 AUTHOR
314            
315             Tokuhiro Matsuno E<lt>tokuhirom@gmail.comE<gt>
316            
317             =head1 THANKS TO
318            
319             kazuhooku
320            
321             dragon3
322            
323             charsbar
324            
325             Tatsuhiko Miyagawa
326            
327             lestrrat
328            
329             =head1 SEE ALSO
330            
331             =head1 LICENSE
332            
333             This library is free software; you can redistribute it and/or modify
334             it under the same terms as Perl itself.
335            
336             =cut
337