File Coverage

blib/lib/Net/EmptyPort.pm
Criterion Covered Total %
statement 86 87 98.8
branch 40 48 83.3
condition 31 36 86.1
subroutine 16 16 100.0
pod 5 5 100.0
total 178 192 92.7


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