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