1#  You may distribute under the terms of either the GNU General Public License
2#  or the Artistic License (the same terms as Perl itself)
3#
4#  (C) Paul Evans, 2012-2019 -- leonerd@leonerd.org.uk
5
6package IO::Async::OS;
7
8use strict;
9use warnings;
10
11our $VERSION = '0.800';
12
13our @ISA = qw( IO::Async::OS::_Base );
14
15if( eval { require "IO/Async/OS/$^O.pm" } ) {
16   @ISA = "IO::Async::OS::$^O";
17}
18
19package # hide from CPAN
20   IO::Async::OS::_Base;
21
22use Carp;
23
24use Socket 1.95 qw(
25   AF_INET AF_INET6 AF_UNIX INADDR_LOOPBACK SOCK_DGRAM SOCK_RAW SOCK_STREAM
26   pack_sockaddr_in inet_aton
27   pack_sockaddr_in6 inet_pton
28   pack_sockaddr_un
29);
30
31use POSIX qw( sysconf _SC_OPEN_MAX );
32
33# Win32 [and maybe other places] don't have an _SC_OPEN_MAX. About the best we
34# can do really is just make up some largeish number and hope for the best.
35use constant OPEN_MAX_FD => eval { sysconf(_SC_OPEN_MAX) } || 1024;
36
37# Some constants that define features of the OS
38
39use constant HAVE_SOCKADDR_IN6 => defined eval { pack_sockaddr_in6 0, inet_pton( AF_INET6, "2001::1" ) };
40use constant HAVE_SOCKADDR_UN  => defined eval { pack_sockaddr_un "/foo" };
41
42# Do we have to fake S_ISREG() files read/write-ready in select()?
43use constant HAVE_FAKE_ISREG_READY => 0;
44
45# Do we have to select() for for evec to get connect() failures
46use constant HAVE_SELECT_CONNECT_EVEC => 0;
47# Ditto; do we have to poll() for POLLPRI to get connect() failures
48use constant HAVE_POLL_CONNECT_POLLPRI => 0;
49
50# Does connect() yield EWOULDBLOCK for nonblocking in progress?
51use constant HAVE_CONNECT_EWOULDBLOCK => 0;
52
53# Can we rename() files that are open?
54use constant HAVE_RENAME_OPEN_FILES => 1;
55
56# Can we reliably watch for POSIX signals, including SIGCHLD to reliably
57# inform us that a fork()ed child has exit()ed?
58use constant HAVE_SIGNALS => 1;
59
60# Do we support POSIX-style true fork()ed processes at all?
61use constant HAVE_POSIX_FORK => !$ENV{IO_ASYNC_NO_FORK};
62# Can we potentially support threads? (would still need to 'require threads')
63use constant HAVE_THREADS => !$ENV{IO_ASYNC_NO_THREADS} &&
64   eval { require Config && $Config::Config{useithreads} };
65
66# Preferred trial order for built-in Loop classes
67use constant LOOP_BUILTIN_CLASSES => qw( Poll Select );
68
69# Should there be any other Loop classes we try before the builtin ones?
70use constant LOOP_PREFER_CLASSES => ();
71
72=head1 NAME
73
74C<IO::Async::OS> - operating system abstractions for C<IO::Async>
75
76=head1 DESCRIPTION
77
78This module acts as a class to provide a number of utility methods whose exact
79behaviour may depend on the type of OS it is running on. It is provided as a
80class so that specific kinds of operating system can override methods in it.
81
82As well as these support functions it also provides a number of constants, all
83with names beginning C<HAVE_> which describe various features that may or may
84not be available on the OS or perl build. Most of these are either hard-coded
85per OS, or detected at runtime.
86
87The following constants may be overridden by environment variables.
88
89=over 4
90
91=item * HAVE_POSIX_FORK
92
93True if the C<fork()> call has full POSIX semantics (full process separation).
94This is true on most OSes but false on MSWin32.
95
96This may be overridden to be false by setting the environment variable
97C<IO_ASYNC_NO_FORK>.
98
99=item * HAVE_THREADS
100
101True if C<ithreads> are available, meaning that the C<threads> module can be
102used. This depends on whether perl was built with threading support.
103
104This may be overridable to be false by setting the environment variable
105C<IO_ASYNC_NO_THREADS>.
106
107=back
108
109=cut
110
111=head2 getfamilybyname
112
113   $family = IO::Async::OS->getfamilybyname( $name )
114
115Return a protocol family value based on the given name. If C<$name> looks like
116a number it will be returned as-is. The string values C<inet>, C<inet6> and
117C<unix> will be converted to the appropriate C<AF_*> constant.
118
119=cut
120
121sub getfamilybyname
122{
123   shift;
124   my ( $name ) = @_;
125
126   return undef unless defined $name;
127
128   return $name if $name =~ m/^\d+$/;
129
130   return AF_INET    if $name eq "inet";
131   return AF_INET6() if $name eq "inet6" and defined &AF_INET6;
132   return AF_UNIX    if $name eq "unix";
133
134   croak "Unrecognised socket family name '$name'";
135}
136
137=head2 getsocktypebyname
138
139   $socktype = IO::Async::OS->getsocktypebyname( $name )
140
141Return a socket type value based on the given name. If C<$name> looks like a
142number it will be returned as-is. The string values C<stream>, C<dgram> and
143C<raw> will be converted to the appropriate C<SOCK_*> constant.
144
145=cut
146
147sub getsocktypebyname
148{
149   shift;
150   my ( $name ) = @_;
151
152   return undef unless defined $name;
153
154   return $name if $name =~ m/^\d+$/;
155
156   return SOCK_STREAM if $name eq "stream";
157   return SOCK_DGRAM  if $name eq "dgram";
158   return SOCK_RAW    if $name eq "raw";
159
160   croak "Unrecognised socktype name '$name'";
161}
162
163# This one isn't documented because it's not really overridable. It's largely
164# here just for completeness
165my $HAVE_IO_SOCKET_IP;
166
167sub socket
168{
169   my $self = shift;
170   my ( $family, $socktype, $proto ) = @_;
171
172   require IO::Socket;
173   defined $HAVE_IO_SOCKET_IP or
174      $HAVE_IO_SOCKET_IP = defined eval { require IO::Socket::IP };
175
176   croak "Cannot create a new socket without a family" unless $family;
177   # PF_UNSPEC and undef are both false
178   $family = $self->getfamilybyname( $family ) || AF_UNIX;
179
180   # SOCK_STREAM is the most likely
181   $socktype = $self->getsocktypebyname( $socktype ) || SOCK_STREAM;
182
183   defined $proto or $proto = 0;
184
185   if( $HAVE_IO_SOCKET_IP and ( $family == AF_INET || $family == AF_INET6() ) ) {
186      return IO::Socket::IP->new->socket( $family, $socktype, $proto );
187   }
188
189   my $sock = eval {
190      IO::Socket->new(
191         Domain => $family,
192         Type   => $socktype,
193         Proto  => $proto,
194      );
195   };
196   return $sock if $sock;
197
198   # That failed. Most likely because the Domain was unrecognised. This
199   # usually happens if getaddrinfo returns an AF_INET6 address but we don't
200   # have a suitable class loaded. In this case we'll return a generic one.
201   # It won't be in the specific subclass but that's the best we can do. And
202   # it will still work as a generic socket.
203   return IO::Socket->new->socket( $family, $socktype, $proto );
204}
205
206=head2 socketpair
207
208   ( $S1, $S2 ) = IO::Async::OS->socketpair( $family, $socktype, $proto )
209
210An abstraction of the C<socketpair(2)> syscall, where any argument may be
211missing (or given as C<undef>).
212
213If C<$family> is not provided, a suitable value will be provided by the OS
214(likely C<AF_UNIX> on POSIX-based platforms). If C<$socktype> is not provided,
215then C<SOCK_STREAM> will be used.
216
217Additionally, this method supports building connected C<SOCK_STREAM> or
218C<SOCK_DGRAM> pairs in the C<AF_INET> family even if the underlying platform's
219C<socketpair(2)> does not, by connecting two normal sockets together.
220
221C<$family> and C<$socktype> may also be given symbolically as defined by
222C<getfamilybyname> and C<getsocktypebyname>.
223
224=cut
225
226sub socketpair
227{
228   my $self = shift;
229   my ( $family, $socktype, $proto ) = @_;
230
231   require IO::Socket;
232
233   # PF_UNSPEC and undef are both false
234   $family = $self->getfamilybyname( $family ) || AF_UNIX;
235
236   # SOCK_STREAM is the most likely
237   $socktype = $self->getsocktypebyname( $socktype ) || SOCK_STREAM;
238
239   $proto ||= 0;
240
241   my ( $S1, $S2 ) = IO::Socket->new->socketpair( $family, $socktype, $proto );
242   return ( $S1, $S2 ) if defined $S1;
243
244   return unless $family == AF_INET and ( $socktype == SOCK_STREAM or $socktype == SOCK_DGRAM );
245
246   # Now lets emulate an AF_INET socketpair call
247
248   my $Stmp = IO::Async::OS->socket( $family, $socktype ) or return;
249   $Stmp->bind( pack_sockaddr_in( 0, INADDR_LOOPBACK ) ) or return;
250
251   $S1 = IO::Async::OS->socket( $family, $socktype ) or return;
252
253   if( $socktype == SOCK_STREAM ) {
254      $Stmp->listen( 1 ) or return;
255      $S1->connect( getsockname $Stmp ) or return;
256      $S2 = $Stmp->accept or return;
257
258      # There's a bug in IO::Socket here, in that $S2 's ->socktype won't
259      # yet be set. We can apply a horribly hacky fix here
260      #   defined $S2->socktype and $S2->socktype == $socktype or
261      #     ${*$S2}{io_socket_type} = $socktype;
262      # But for now we'll skip the test for it instead
263   }
264   else {
265      $S2 = $Stmp;
266      $S1->connect( getsockname $S2 ) or return;
267      $S2->connect( getsockname $S1 ) or return;
268   }
269
270   return ( $S1, $S2 );
271}
272
273=head2 pipepair
274
275   ( $rd, $wr ) = IO::Async::OS->pipepair
276
277An abstraction of the C<pipe(2)> syscall, which returns the two new handles.
278
279=cut
280
281sub pipepair
282{
283   my $self = shift;
284
285   pipe( my ( $rd, $wr ) ) or return;
286   return ( $rd, $wr );
287}
288
289=head2 pipequad
290
291   ( $rdA, $wrA, $rdB, $wrB ) = IO::Async::OS->pipequad
292
293This method is intended for creating two pairs of filehandles that are linked
294together, suitable for passing as the STDIN/STDOUT pair to a child process.
295After this function returns, C<$rdA> and C<$wrA> will be a linked pair, as
296will C<$rdB> and C<$wrB>.
297
298On platforms that support C<socketpair(2)>, this implementation will be
299preferred, in which case C<$rdA> and C<$wrB> will actually be the same
300filehandle, as will C<$rdB> and C<$wrA>. This saves a file descriptor in the
301parent process.
302
303When creating a L<IO::Async::Stream> or subclass of it, the C<read_handle>
304and C<write_handle> parameters should always be used.
305
306   my ( $childRd, $myWr, $myRd, $childWr ) = IO::Async::OS->pipequad;
307
308   $loop->open_process(
309      stdin  => $childRd,
310      stdout => $childWr,
311      ...
312   );
313
314   my $str = IO::Async::Stream->new(
315      read_handle  => $myRd,
316      write_handle => $myWr,
317      ...
318   );
319   $loop->add( $str );
320
321=cut
322
323sub pipequad
324{
325   my $self = shift;
326
327   # Prefer socketpair
328   if( my ( $S1, $S2 ) = $self->socketpair ) {
329      return ( $S1, $S2, $S2, $S1 );
330   }
331
332   # Can't do that, fallback on pipes
333   my ( $rdA, $wrA ) = $self->pipepair or return;
334   my ( $rdB, $wrB ) = $self->pipepair or return;
335
336   return ( $rdA, $wrA, $rdB, $wrB );
337}
338
339=head2 signame2num
340
341   $signum = IO::Async::OS->signame2num( $signame )
342
343This utility method converts a signal name (such as "TERM") into its system-
344specific signal number. This may be useful to pass to C<POSIX::SigSet> or use
345in other places which use numbers instead of symbolic names.
346
347=head2 signum2name
348
349   $signame = IO::Async::OS->signum2name( $signum )
350
351The inverse of L<signame2num>; this method convers signal numbers into
352readable names.
353
354=cut
355
356my %sig_name2num;
357my %sig_num2name;
358
359sub _init_signum
360{
361   my $self = shift;
362
363   require Config;
364
365   $Config::Config{sig_name} and $Config::Config{sig_num} or
366      die "No signals found";
367
368   my @names = split ' ', $Config::Config{sig_name};
369   my @nums  = split ' ', $Config::Config{sig_num};
370
371   @sig_name2num{ @names } = @nums;
372   @sig_num2name{ @nums  } = @names;
373}
374
375sub signame2num
376{
377   my $self = shift;
378   my ( $signame ) = @_;
379
380   %sig_name2num or $self->_init_signum;
381
382   return $sig_name2num{$signame};
383}
384
385sub signum2name
386{
387   my $self = shift;
388   my ( $signum ) = @_;
389
390   %sig_num2name or $self->_init_signum;
391
392   return $sig_num2name{$signum};
393}
394
395=head2 extract_addrinfo
396
397   ( $family, $socktype, $protocol, $addr ) = IO::Async::OS->extract_addrinfo( $ai )
398
399Given an ARRAY or HASH reference value containing an addrinfo, returns a
400family, socktype and protocol argument suitable for a C<socket> call and an
401address suitable for C<connect> or C<bind>.
402
403If given an ARRAY it should be in the following form:
404
405   [ $family, $socktype, $protocol, $addr ]
406
407If given a HASH it should contain the following keys:
408
409   family socktype protocol addr
410
411Each field in the result will be initialised to 0 (or empty string for the
412address) if not defined in the C<$ai> value.
413
414The family type may also be given as a symbolic string as defined by
415C<getfamilybyname>.
416
417The socktype may also be given as a symbolic string; C<stream>, C<dgram> or
418C<raw>; this will be converted to the appropriate C<SOCK_*> constant.
419
420Note that the C<addr> field, if provided, must be a packed socket address,
421such as returned by C<pack_sockaddr_in> or C<pack_sockaddr_un>.
422
423If the HASH form is used, rather than passing a packed socket address in the
424C<addr> field, certain other hash keys may be used instead for convenience on
425certain named families.
426
427=over 4
428
429=cut
430
431use constant ADDRINFO_FAMILY   => 0;
432use constant ADDRINFO_SOCKTYPE => 1;
433use constant ADDRINFO_PROTOCOL => 2;
434use constant ADDRINFO_ADDR     => 3;
435
436sub extract_addrinfo
437{
438   my $self = shift;
439   my ( $ai, $argname ) = @_;
440
441   $argname ||= "addr";
442
443   my @ai;
444
445   if( ref $ai eq "ARRAY" ) {
446      @ai = @$ai;
447   }
448   elsif( ref $ai eq "HASH" ) {
449      $ai = { %$ai }; # copy so we can delete from it
450      @ai = delete @{$ai}{qw( family socktype protocol addr )};
451
452      if( defined $ai[ADDRINFO_FAMILY] and !defined $ai[ADDRINFO_ADDR] ) {
453         my $family = $ai[ADDRINFO_FAMILY];
454         my $method = "_extract_addrinfo_$family";
455         my $code = $self->can( $method ) or croak "Cannot determine addr for extract_addrinfo on family='$family'";
456
457         $ai[ADDRINFO_ADDR] = $code->( $self, $ai );
458
459         keys %$ai and croak "Unrecognised '$family' addrinfo keys: " . join( ", ", keys %$ai );
460      }
461   }
462   else {
463      croak "Expected '$argname' to be an ARRAY or HASH reference";
464   }
465
466   $ai[ADDRINFO_FAMILY]   = $self->getfamilybyname( $ai[ADDRINFO_FAMILY] );
467   $ai[ADDRINFO_SOCKTYPE] = $self->getsocktypebyname( $ai[ADDRINFO_SOCKTYPE] );
468
469   # Make sure all fields are defined
470   $ai[$_] ||= 0 for ADDRINFO_FAMILY, ADDRINFO_SOCKTYPE, ADDRINFO_PROTOCOL;
471   $ai[ADDRINFO_ADDR]  = "" if !defined $ai[ADDRINFO_ADDR];
472
473   return @ai;
474}
475
476=item family => 'inet'
477
478Will pack an IP address and port number from keys called C<ip> and C<port>.
479If C<ip> is missing it will be set to "0.0.0.0". If C<port> is missing it will
480be set to 0.
481
482=cut
483
484sub _extract_addrinfo_inet
485{
486   my $self = shift;
487   my ( $ai ) = @_;
488
489   my $port = delete $ai->{port} || 0;
490   my $ip   = delete $ai->{ip}   || "0.0.0.0";
491
492   return pack_sockaddr_in( $port, inet_aton( $ip ) );
493}
494
495=item family => 'inet6'
496
497Will pack an IP address and port number from keys called C<ip> and C<port>.
498If C<ip> is missing it will be set to "::". If C<port> is missing it will be
499set to 0. Optionally will also include values from C<scopeid> and C<flowinfo>
500keys if provided.
501
502This will only work if a C<pack_sockaddr_in6> function can be found in
503C<Socket>
504
505=cut
506
507sub _extract_addrinfo_inet6
508{
509   my $self = shift;
510   my ( $ai ) = @_;
511
512   my $port     = delete $ai->{port}     || 0;
513   my $ip       = delete $ai->{ip}       || "::";
514   my $scopeid  = delete $ai->{scopeid}  || 0;
515   my $flowinfo = delete $ai->{flowinfo} || 0;
516
517   if( HAVE_SOCKADDR_IN6 ) {
518      return pack_sockaddr_in6( $port, inet_pton( AF_INET6, $ip ), $scopeid, $flowinfo );
519   }
520   else {
521      croak "Cannot pack_sockaddr_in6";
522   }
523}
524
525=item family => 'unix'
526
527Will pack a UNIX socket path from a key called C<path>.
528
529=cut
530
531sub _extract_addrinfo_unix
532{
533   my $self = shift;
534   my ( $ai ) = @_;
535
536   defined( my $path = delete $ai->{path} ) or croak "Expected 'path' for extract_addrinfo on family='unix'";
537
538   return pack_sockaddr_un( $path );
539}
540
541=pod
542
543=back
544
545=cut
546
547=head2 make_addr_for_peer
548
549   $connectaddr = IO::Async::OS->make_addr_for_peer( $family, $listenaddr )
550
551Given the C<sockdomain> and C<sockname> of a listening socket. creates an
552address suitable to C<connect()> to it.
553
554This method will handle specially any C<AF_INET> address bound to
555C<INADDR_ANY> or any C<AF_INET6> address bound to C<IN6ADDR_ANY>, as some OSes
556do not allow C<connect(2)>ing to those and would instead insist on receiving
557C<INADDR_LOOPBACK> or C<IN6ADDR_LOOPBACK> respectively.
558
559This method is used by the C<< ->connect( peer => $sock ) >> parameter of
560handle and loop connect methods.
561
562=cut
563
564sub make_addr_for_peer
565{
566   shift;
567   my ( $p_family, $p_addr ) = @_;
568
569   if( $p_family == Socket::AF_INET ) {
570      my @params = Socket::unpack_sockaddr_in $p_addr;
571      $params[1] = Socket::INADDR_LOOPBACK if $params[1] eq Socket::INADDR_ANY;
572      return Socket::pack_sockaddr_in @params;
573   }
574   if( HAVE_SOCKADDR_IN6 and $p_family == Socket::AF_INET6 ) {
575      my @params = Socket::unpack_sockaddr_in6 $p_addr;
576      $params[1] = Socket::IN6ADDR_LOOPBACK if $params[1] eq Socket::IN6ADDR_ANY;
577      return Socket::pack_sockaddr_in6 @params;
578   }
579
580   # Most other cases should be fine
581   return $p_addr;
582}
583
584=head1 LOOP IMPLEMENTATION METHODS
585
586The following methods are provided on C<IO::Async::OS> because they are likely
587to require OS-specific implementations, but are used by L<IO::Async::Loop> to
588implement its functionality. It can use the HASH reference C<< $loop->{os} >>
589to store other data it requires.
590
591=cut
592
593=head2 loop_watch_signal
594
595=head2 loop_unwatch_signal
596
597   IO::Async::OS->loop_watch_signal( $loop, $signal, $code )
598
599   IO::Async::OS->loop_unwatch_signal( $loop, $signal )
600
601Used to implement the C<watch_signal> / C<unwatch_signal> Loop pair.
602
603=cut
604
605sub _setup_sigpipe
606{
607   my $self = shift;
608   my ( $loop ) = @_;
609
610   require IO::Async::Handle;
611
612   my ( $reader, $sigpipe ) = $self->pipepair or croak "Cannot pipe() - $!";
613   $_->blocking( 0 ) for $reader, $sigpipe;
614
615   $loop->{os}{sigpipe} = $sigpipe;
616
617   my $sigwatch = $loop->{os}{sigwatch};
618
619   $loop->add( $loop->{os}{sigpipe_reader} = IO::Async::Handle->new(
620      notifier_name => "sigpipe",
621      read_handle => $reader,
622      on_read_ready => sub {
623         sysread $reader, my $buffer, 8192 or return;
624         foreach my $signum ( unpack "I*", $buffer ) {
625            $sigwatch->{$signum}->() if $sigwatch->{$signum};
626         }
627      },
628   ) );
629
630   return $sigpipe;
631}
632
633sub loop_watch_signal
634{
635   my $self = shift;
636   my ( $loop, $signal, $code ) = @_;
637
638   exists $SIG{$signal} or croak "Unrecognised signal name $signal";
639   ref $code or croak 'Expected $code as a reference';
640
641   my $signum = $self->signame2num( $signal );
642   my $sigwatch = $loop->{os}{sigwatch} ||= {}; # {$num} = $code
643
644   my $sigpipe = $loop->{os}{sigpipe} // $self->_setup_sigpipe( $loop );
645
646   my $signum_str = pack "I", $signum;
647   $SIG{$signal} = sub { syswrite $sigpipe, $signum_str };
648
649   $sigwatch->{$signum} = $code;
650}
651
652sub loop_unwatch_signal
653{
654   my $self = shift;
655   my ( $loop, $signal ) = @_;
656
657   my $signum = $self->signame2num( $signal );
658   my $sigwatch = $loop->{os}{sigwatch} or return;
659
660   delete $sigwatch->{$signum};
661   undef $SIG{$signal};
662}
663
664=head2 potentially_open_fds
665
666   @fds = IO::Async::OS->potentially_open_fds
667
668Returns a list of filedescriptors which might need closing. By default this
669will return C<0 .. _SC_OPEN_MAX>. OS-specific subclasses may have a better
670guess.
671
672=cut
673
674sub potentially_open_fds
675{
676   return 0 .. OPEN_MAX_FD;
677}
678
679sub post_fork
680{
681   my $self = shift;
682   my ( $loop ) = @_;
683
684   if( $loop->{os}{sigpipe} ) {
685      $loop->remove( $loop->{os}{sigpipe_reader} );
686      undef $loop->{os}{sigpipe};
687
688      my $sigwatch = $loop->{os}{sigwatch};
689
690      foreach my $signal ( keys %SIG ) {
691         my $signum = $self->signame2num( $signal ) or next;
692         my $code = $sigwatch->{$signum} or next;
693
694         $self->loop_watch_signal( $loop, $signal, $code );
695      }
696   }
697}
698
699=head1 AUTHOR
700
701Paul Evans <leonerd@leonerd.org.uk>
702
703=cut
704
7050x55AA;
706