Try to look up protocol (by name) only iff it has non-numbers:
[p5sagit/p5-mst-13.2.git] / ext / IO / lib / IO / Socket / INET.pm
CommitLineData
cf7fe8a2 1# IO::Socket::INET.pm
2#
3# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
4# This program is free software; you can redistribute it and/or
5# modify it under the same terms as Perl itself.
6
7package IO::Socket::INET;
8
9use strict;
17f410f9 10our(@ISA, $VERSION);
cf7fe8a2 11use IO::Socket;
12use Socket;
13use Carp;
14use Exporter;
e541f5e7 15use Errno;
cf7fe8a2 16
17@ISA = qw(IO::Socket);
d6a466d7 18$VERSION = "1.26";
cf7fe8a2 19
e541f5e7 20my $EINVAL = exists(&Errno::EINVAL) ? Errno::EINVAL() : 1;
21
cf7fe8a2 22IO::Socket::INET->register_domain( AF_INET );
23
24my %socket_type = ( tcp => SOCK_STREAM,
25 udp => SOCK_DGRAM,
26 icmp => SOCK_RAW
27 );
28
29sub new {
30 my $class = shift;
31 unshift(@_, "PeerAddr") if @_ == 1;
32 return $class->SUPER::new(@_);
33}
34
35sub _sock_info {
36 my($addr,$port,$proto) = @_;
83fe8690 37 my $origport = $port;
cf7fe8a2 38 my @proto = ();
39 my @serv = ();
40
41 $port = $1
42 if(defined $addr && $addr =~ s,:([\w\(\)/]+)$,,);
43
7822251e 44 if(defined $proto && $proto =~ /\D/) {
45 if(@proto = getprotobyname($proto) {
c9fcc6c4 46 $proto = $proto[2] || undef;
47 }
48 else {
49 $@ = "Bad protocol '$proto'";
50 return;
51 }
cf7fe8a2 52 }
53
54 if(defined $port) {
55 $port =~ s,\((\d+)\)$,,;
56
57 my $defport = $1 || undef;
58 my $pnum = ($port =~ m,^(\d+)$,)[0];
59
83fe8690 60 @serv = getservbyname($port, $proto[0] || "")
61 if ($port =~ m,\D,);
cf7fe8a2 62
a957f605 63 $port = $serv[2] || $defport || $pnum;
83fe8690 64 unless (defined $port) {
65 $@ = "Bad service '$origport'";
66 return;
67 }
cf7fe8a2 68
69 $proto = (getprotobyname($serv[3]))[2] || undef
70 if @serv && !$proto;
71 }
72
73 return ($addr || undef,
74 $port || undef,
75 $proto || undef
76 );
77}
78
79sub _error {
80 my $sock = shift;
c9fcc6c4 81 my $err = shift;
82 {
83 local($!);
6f36ad4a 84 my $title = ref($sock).": ";
85 $@ = join("", $_[0] =~ /^$title/ ? "" : $title, @_);
c9fcc6c4 86 close($sock)
cf7fe8a2 87 if(defined fileno($sock));
c9fcc6c4 88 }
89 $! = $err;
cf7fe8a2 90 return undef;
91}
92
93sub _get_addr {
94 my($sock,$addr_str, $multi) = @_;
95 my @addr;
96 if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
97 (undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
98 } else {
99 my $h = inet_aton($addr_str);
100 push(@addr, $h) if defined $h;
101 }
102 @addr;
103}
104
105sub configure {
106 my($sock,$arg) = @_;
107 my($lport,$rport,$laddr,$raddr,$proto,$type);
108
109
110 $arg->{LocalAddr} = $arg->{LocalHost}
111 if exists $arg->{LocalHost} && !exists $arg->{LocalAddr};
112
113 ($laddr,$lport,$proto) = _sock_info($arg->{LocalAddr},
114 $arg->{LocalPort},
c9fcc6c4 115 $arg->{Proto})
116 or return _error($sock, $!, $@);
cf7fe8a2 117
118 $laddr = defined $laddr ? inet_aton($laddr)
119 : INADDR_ANY;
120
e541f5e7 121 return _error($sock, $EINVAL, "Bad hostname '",$arg->{LocalAddr},"'")
cf7fe8a2 122 unless(defined $laddr);
123
124 $arg->{PeerAddr} = $arg->{PeerHost}
125 if exists $arg->{PeerHost} && !exists $arg->{PeerAddr};
126
127 unless(exists $arg->{Listen}) {
128 ($raddr,$rport,$proto) = _sock_info($arg->{PeerAddr},
129 $arg->{PeerPort},
c9fcc6c4 130 $proto)
131 or return _error($sock, $!, $@);
cf7fe8a2 132 }
133
134 $proto ||= (getprotobyname('tcp'))[2];
135
136 my $pname = (getprotobynumber($proto))[0];
137 $type = $arg->{Type} || $socket_type{$pname};
138
139 my @raddr = ();
140
141 if(defined $raddr) {
142 @raddr = $sock->_get_addr($raddr, $arg->{MultiHomed});
e541f5e7 143 return _error($sock, $EINVAL, "Bad hostname '",$arg->{PeerAddr},"'")
cf7fe8a2 144 unless @raddr;
145 }
146
147 while(1) {
148
149 $sock->socket(AF_INET, $type, $proto) or
c9fcc6c4 150 return _error($sock, $!, "$!");
cf7fe8a2 151
121c220b 152 if ($arg->{Reuse} || $arg->{ReuseAddr}) {
cf7fe8a2 153 $sock->sockopt(SO_REUSEADDR,1) or
c9fcc6c4 154 return _error($sock, $!, "$!");
cf7fe8a2 155 }
156
8b9593b7 157 if ($arg->{ReusePort}) {
158 $sock->sockopt(SO_REUSEPORT,1) or
159 return _error($sock, $!, "$!");
160 }
161
cf7fe8a2 162 if($lport || ($laddr ne INADDR_ANY) || exists $arg->{Listen}) {
163 $sock->bind($lport || 0, $laddr) or
c9fcc6c4 164 return _error($sock, $!, "$!");
cf7fe8a2 165 }
166
167 if(exists $arg->{Listen}) {
168 $sock->listen($arg->{Listen} || 5) or
c9fcc6c4 169 return _error($sock, $!, "$!");
cf7fe8a2 170 last;
171 }
172
23925046 173 # don't try to connect unless we're given a PeerAddr
174 last unless exists($arg->{PeerAddr});
175
cf7fe8a2 176 $raddr = shift @raddr;
177
e541f5e7 178 return _error($sock, $EINVAL, 'Cannot determine remote port')
cf7fe8a2 179 unless($rport || $type == SOCK_DGRAM || $type == SOCK_RAW);
180
181 last
182 unless($type == SOCK_STREAM || defined $raddr);
183
e541f5e7 184 return _error($sock, $EINVAL, "Bad hostname '",$arg->{PeerAddr},"'")
cf7fe8a2 185 unless defined $raddr;
186
187# my $timeout = ${*$sock}{'io_socket_timeout'};
188# my $before = time() if $timeout;
189
6f36ad4a 190 undef $@;
cf7fe8a2 191 if ($sock->connect(pack_sockaddr_in($rport, $raddr))) {
192# ${*$sock}{'io_socket_timeout'} = $timeout;
193 return $sock;
194 }
195
6f36ad4a 196 return _error($sock, $!, $@ || "Timeout")
cf7fe8a2 197 unless @raddr;
198
199# if ($timeout) {
200# my $new_timeout = $timeout - (time() - $before);
c9fcc6c4 201# return _error($sock,
e541f5e7 202# (exists(&Errno::ETIMEDOUT) ? Errno::ETIMEDOUT() : $EINVAL),
c9fcc6c4 203# "Timeout") if $new_timeout <= 0;
cf7fe8a2 204# ${*$sock}{'io_socket_timeout'} = $new_timeout;
205# }
206
207 }
208
209 $sock;
210}
211
212sub connect {
213 @_ == 2 || @_ == 3 or
214 croak 'usage: $sock->connect(NAME) or $sock->connect(PORT, ADDR)';
215 my $sock = shift;
216 return $sock->SUPER::connect(@_ == 1 ? shift : pack_sockaddr_in(@_));
217}
218
219sub bind {
220 @_ == 2 || @_ == 3 or
221 croak 'usage: $sock->bind(NAME) or $sock->bind(PORT, ADDR)';
222 my $sock = shift;
223 return $sock->SUPER::bind(@_ == 1 ? shift : pack_sockaddr_in(@_))
224}
225
226sub sockaddr {
227 @_ == 1 or croak 'usage: $sock->sockaddr()';
228 my($sock) = @_;
229 my $name = $sock->sockname;
230 $name ? (sockaddr_in($name))[1] : undef;
231}
232
233sub sockport {
234 @_ == 1 or croak 'usage: $sock->sockport()';
235 my($sock) = @_;
236 my $name = $sock->sockname;
237 $name ? (sockaddr_in($name))[0] : undef;
238}
239
240sub sockhost {
241 @_ == 1 or croak 'usage: $sock->sockhost()';
242 my($sock) = @_;
243 my $addr = $sock->sockaddr;
244 $addr ? inet_ntoa($addr) : undef;
245}
246
247sub peeraddr {
248 @_ == 1 or croak 'usage: $sock->peeraddr()';
249 my($sock) = @_;
250 my $name = $sock->peername;
251 $name ? (sockaddr_in($name))[1] : undef;
252}
253
254sub peerport {
255 @_ == 1 or croak 'usage: $sock->peerport()';
256 my($sock) = @_;
257 my $name = $sock->peername;
258 $name ? (sockaddr_in($name))[0] : undef;
259}
260
261sub peerhost {
262 @_ == 1 or croak 'usage: $sock->peerhost()';
263 my($sock) = @_;
264 my $addr = $sock->peeraddr;
265 $addr ? inet_ntoa($addr) : undef;
266}
267
2681;
269
270__END__
271
272=head1 NAME
273
274IO::Socket::INET - Object interface for AF_INET domain sockets
275
276=head1 SYNOPSIS
277
278 use IO::Socket::INET;
279
280=head1 DESCRIPTION
281
282C<IO::Socket::INET> provides an object interface to creating and using sockets
283in the AF_INET domain. It is built upon the L<IO::Socket> interface and
284inherits all the methods defined by L<IO::Socket>.
285
286=head1 CONSTRUCTOR
287
288=over 4
289
290=item new ( [ARGS] )
291
292Creates an C<IO::Socket::INET> object, which is a reference to a
293newly created symbol (see the C<Symbol> package). C<new>
294optionally takes arguments, these arguments are in key-value pairs.
295
296In addition to the key-value pairs accepted by L<IO::Socket>,
297C<IO::Socket::INET> provides.
298
299
300 PeerAddr Remote host address <hostname>[:<port>]
301 PeerHost Synonym for PeerAddr
302 PeerPort Remote port or service <service>[(<no>)] | <no>
303 LocalAddr Local host bind address hostname[:port]
304 LocalHost Synonym for LocalAddr
305 LocalPort Local host bind port <service>[(<no>)] | <no>
306 Proto Protocol name (or number) "tcp" | "udp" | ...
307 Type Socket type SOCK_STREAM | SOCK_DGRAM | ...
308 Listen Queue size for listen
121c220b 309 ReuseAddr Set SO_REUSEADDR before binding
310 Reuse Set SO_REUSEADDR before binding (deprecated, prefer ReuseAddr)
8b9593b7 311 ReusePort Set SO_REUSEPORT before binding
cf7fe8a2 312 Timeout Timeout value for various operations
313 MultiHomed Try all adresses for multi-homed hosts
314
315
316If C<Listen> is defined then a listen socket is created, else if the
317socket type, which is derived from the protocol, is SOCK_STREAM then
318connect() is called.
319
320Although it is not illegal, the use of C<MultiHomed> on a socket
321which is in non-blocking mode is of little use. This is because the
322first connect will never fail with a timeout as the connaect call
323will not block.
324
325The C<PeerAddr> can be a hostname or the IP-address on the
326"xx.xx.xx.xx" form. The C<PeerPort> can be a number or a symbolic
327service name. The service name might be followed by a number in
328parenthesis which is used if the service is not known by the system.
329The C<PeerPort> specification can also be embedded in the C<PeerAddr>
330by preceding it with a ":".
331
332If C<Proto> is not given and you specify a symbolic C<PeerPort> port,
333then the constructor will try to derive C<Proto> from the service
334name. As a last resort C<Proto> "tcp" is assumed. The C<Type>
335parameter will be deduced from C<Proto> if not specified.
336
337If the constructor is only passed a single argument, it is assumed to
338be a C<PeerAddr> specification.
339
340Examples:
341
342 $sock = IO::Socket::INET->new(PeerAddr => 'www.perl.org',
343 PeerPort => 'http(80)',
344 Proto => 'tcp');
345
346 $sock = IO::Socket::INET->new(PeerAddr => 'localhost:smtp(25)');
347
348 $sock = IO::Socket::INET->new(Listen => 5,
349 LocalAddr => 'localhost',
350 LocalPort => 9000,
351 Proto => 'tcp');
352
353 $sock = IO::Socket::INET->new('127.0.0.1:25');
354
355
356 NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
3cb6de81 357
cf7fe8a2 358As of VERSION 1.18 all IO::Socket objects have autoflush turned on
359by default. This was not the case with earlier releases.
360
361 NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
362
a45bd81d 363=back
364
cf7fe8a2 365=head2 METHODS
366
367=over 4
368
369=item sockaddr ()
370
371Return the address part of the sockaddr structure for the socket
372
373=item sockport ()
374
375Return the port number that the socket is using on the local host
376
377=item sockhost ()
378
379Return the address part of the sockaddr structure for the socket in a
380text form xx.xx.xx.xx
381
382=item peeraddr ()
383
384Return the address part of the sockaddr structure for the socket on
385the peer host
386
387=item peerport ()
388
389Return the port number for the socket on the peer host.
390
391=item peerhost ()
392
393Return the address part of the sockaddr structure for the socket on the
394peer host in a text form xx.xx.xx.xx
395
396=back
397
398=head1 SEE ALSO
399
400L<Socket>, L<IO::Socket>
401
402=head1 AUTHOR
403
854822f1 404Graham Barr. Currently maintained by the Perl Porters. Please report all
405bugs to <perl5-porters@perl.org>.
cf7fe8a2 406
407=head1 COPYRIGHT
408
409Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
410This program is free software; you can redistribute it and/or
411modify it under the same terms as Perl itself.
412
413=cut