File Coverage

blib/lib/Net/Gen.pm
Criterion Covered Total %
statement 578 767 75.3
branch 199 452 44.0
condition 102 281 36.3
subroutine 65 73 89.0
pod 37 40 92.5
total 981 1613 60.8


line stmt bran cond sub pod time code
1             # Copyright 1995,2002 Spider Boardman.
2             # All rights reserved.
3             #
4             # Automatic licensing for this software is available. This software
5             # can be copied and used under the terms of the GNU Public License,
6             # version 1 or (at your option) any later version, or under the
7             # terms of the Artistic license. Both of these can be found with
8             # the Perl distribution, which this software is intended to augment.
9             #
10             # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
11             # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
12             # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13              
14             # rcsid: "@(#) $Id: Gen.dat,v 1.44 2002/04/10 11:27:18 spider Exp $"
15              
16              
17             package Net::Gen;
18 2     2   9640 use 5.004_04; # new minimum Perl version for this package
  2         7  
  2         80  
19              
20 2     2   11 use strict;
  2         3  
  2         73  
21             #use Carp; # no! just require Carp when we want to croak.
22 2         244 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS
23 2     2   10 %_missing $AUTOLOAD $adebug);
  2         9  
24              
25             BEGIN {
26 2     2   13 $VERSION = '1.011';
27 2         141 eval "sub Version () { __PACKAGE__ . ' v$VERSION' }";
28             }
29              
30             #use Socket qw(!/pack_sockaddr/ !/^MSG_OOB$/ !SOMAXCONN);
31 2     2   2596 use Socket ();
  2         10472  
  2         77  
32 2     2   9478 use AutoLoader;
  2         1881  
  2         17  
33 2     2   62 use Exporter ();
  2         4  
  2         28  
34 2     2   19 use DynaLoader ();
  2         5  
  2         40  
35 2     2   2262 use Symbol qw(gensym);
  2         2143  
  2         154  
36 2     2   2303 use SelectSaver ();
  2         569  
  2         44  
37 2     2   1991 use IO::Handle ();
  2         10407  
  2         730  
38              
39             # Special wart for new_from_f{d,h}, since only the _fh flavour's already
40             # known to AutoLoader.
41             sub new_from_fd; *new_from_fd = \&new_from_fh;
42              
43             BEGIN {
44 2     2   61 @ISA = qw(IO::Handle Exporter DynaLoader);
45              
46 2         4 @EXPORT = ();
47              
48 2         38 @EXPORT_OK = qw(pack_sockaddr
49             unpack_sockaddr
50             VAL_O_NONBLOCK
51             VAL_EAGAIN
52             RD_NODATA
53             EOF_NONBLOCK
54             EINPROGRESS EALREADY ENOTSOCK EDESTADDRREQ
55             EMSGSIZE EPROTOTYPE ENOPROTOOPT EPROTONOSUPPORT
56             ESOCKTNOSUPPORT EOPNOTSUPP EPFNOSUPPORT EAFNOSUPPORT
57             EADDRINUSE EADDRNOTAVAIL ENETDOWN ENETUNREACH ENETRESET
58             ECONNABORTED ECONNRESET ENOBUFS EISCONN ENOTCONN
59             ESHUTDOWN ETOOMANYREFS ETIMEDOUT
60             ECONNREFUSED EHOSTDOWN EHOSTUNREACH
61             ENOSR ETIME EBADMSG EPROTO ENODATA ENOSTR
62             EAGAIN EWOULDBLOCK
63             ENOENT EINVAL EBADF
64             SHUT_RD SHUT_WR SHUT_RDWR
65             SOL_SOCKET
66             SOMAXCONN
67             SO_ACCEPTCONN SO_BROADCAST SO_DEBUG SO_DONTROUTE
68             SO_ERROR SO_EXPANDED_RIGHTS SO_FAMILY SO_KEEPALIVE
69             SO_LINGER SO_OOBINLINE SO_PAIRABLE SO_RCVBUF
70             SO_RCVLOWAT SO_RCVTIMEO SO_REUSEADDR SO_REUSEPORT
71             SO_SNDBUF SO_SNDLOWAT SO_SNDTIMEO SO_STATE SO_TYPE
72             SO_USELOOPBACK SO_XSE
73             SOCK_STREAM SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET
74             AF_UNSPEC AF_UNIX AF_INET AF_IMPLINK AF_PUP AF_CHAOS
75             AF_NS AF_ISO AF_OSI AF_ECMA AF_DATAKIT AF_CCITT AF_SNA
76             AF_DECnet AF_DLI AF_LAT AF_HYLINK AF_APPLETALK AF_ROUTE
77             AF_LINK AF_NETMAN AF_X25 AF_CTF AF_WAN AF_USER AF_LAST
78             PF_UNSPEC PF_UNIX PF_INET PF_IMPLINK PF_PUP PF_CHAOS
79             PF_NS PF_ISO PF_OSI PF_ECMA PF_DATAKIT PF_CCITT PF_SNA
80             PF_DECnet PF_DLI PF_LAT PF_HYLINK PF_APPLETALK PF_ROUTE
81             PF_LINK PF_NETMAN PF_X25 PF_CTF PF_WAN PF_USER PF_LAST
82             AF_LOCAL PF_LOCAL
83             );
84              
85 2         121 %EXPORT_TAGS = (
86             NonBlockVals => [qw(EOF_NONBLOCK RD_NODATA VAL_EAGAIN VAL_O_NONBLOCK)],
87             routines => [qw(pack_sockaddr unpack_sockaddr)],
88             errnos => [qw(EINPROGRESS EALREADY ENOTSOCK EDESTADDRREQ
89             EMSGSIZE EPROTOTYPE ENOPROTOOPT EPROTONOSUPPORT
90             ESOCKTNOSUPPORT EOPNOTSUPP EPFNOSUPPORT EAFNOSUPPORT
91             EADDRINUSE EADDRNOTAVAIL ENETDOWN ENETUNREACH ENETRESET
92             ECONNABORTED ECONNRESET ENOBUFS EISCONN ENOTCONN
93             ESHUTDOWN ETOOMANYREFS ETIMEDOUT
94             ECONNREFUSED EHOSTDOWN EHOSTUNREACH
95             ENOSR ETIME EBADMSG EPROTO ENODATA ENOSTR
96             EAGAIN EWOULDBLOCK
97             ENOENT EINVAL EBADF
98             )],
99             shutflags => [qw(SHUT_RD SHUT_WR SHUT_RDWR)],
100             sockopts => [qw(SO_ACCEPTCONN SO_BROADCAST SO_DEBUG SO_DONTROUTE
101             SO_ERROR SO_EXPANDED_RIGHTS SO_FAMILY SO_KEEPALIVE
102             SO_LINGER SO_OOBINLINE SO_PAIRABLE SO_RCVBUF
103             SO_RCVLOWAT SO_RCVTIMEO SO_REUSEADDR SO_REUSEPORT
104             SO_SNDBUF SO_SNDLOWAT SO_SNDTIMEO SO_STATE SO_TYPE
105             SO_USELOOPBACK SO_XSE
106             )],
107             sockvals => [qw(SOL_SOCKET
108             SOCK_STREAM SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET
109             )],
110             af => [qw(AF_UNSPEC AF_UNIX AF_INET AF_IMPLINK AF_PUP AF_CHAOS
111             AF_NS AF_ISO AF_OSI AF_ECMA AF_DATAKIT AF_CCITT AF_SNA
112             AF_DECnet AF_DLI AF_LAT AF_HYLINK AF_APPLETALK AF_ROUTE
113             AF_LINK AF_NETMAN AF_X25 AF_CTF AF_WAN AF_USER AF_LAST
114             AF_LOCAL
115             )],
116             pf => [qw(PF_UNSPEC PF_UNIX PF_INET PF_IMPLINK PF_PUP PF_CHAOS
117             PF_NS PF_ISO PF_OSI PF_ECMA PF_DATAKIT PF_CCITT PF_SNA
118             PF_DECnet PF_DLI PF_LAT PF_HYLINK PF_APPLETALK PF_ROUTE
119             PF_LINK PF_NETMAN PF_X25 PF_CTF PF_WAN PF_USER PF_LAST
120             PF_LOCAL
121             )],
122             ALL => [@EXPORT, @EXPORT_OK],
123             );
124 2         7 $EXPORT_TAGS{'non_block_vals'} = $EXPORT_TAGS{'NonBlockVals'};
125 2         10 $EXPORT_TAGS{'families'} = [@{$EXPORT_TAGS{'af'}}, @{$EXPORT_TAGS{'pf'}}];
  2         14  
  2         887  
126             }
127              
128             my %loaded;
129              
130              
131             # dummies for the Carp:: routines, which we'll re-invoke if we get called.
132              
133             sub croak
134             {
135 0     0 0 0 require Carp;
136 0         0 goto &Carp::croak;
137             }
138              
139             sub carp
140             {
141 0     0 0 0 require Carp;
142 0         0 goto &Carp::carp;
143             }
144              
145              
146             my $nullsub = sub {}; # handy null warning handler
147             # If the warning handler is this exact code ref, don't bother calling
148             # croak in the AUTOLOAD constant section, since we're being called from
149             # inside the eval in initsockopts().
150              
151             sub AUTOLOAD : locked
152             {
153             # This AUTOLOAD is used to validate possible missing constants from
154             # the XS code, or to auto-create get/setattr subs.
155             # The defined constants are already available as XSUBs, and the same
156             # XS code which handles that also sets up the %_missing hash to note
157             # which names were known but are undefined.
158             # If the name is in %_missing, we'll croak as a normal AUTOLOAD with
159             # a constant() XS function (except for when $nullsub is the die handler).
160             # If the name isn't known to %_missing, but it is known
161             # as a key for setparams/getparams, it will be simulated via _accessor().
162             # Otherwise, control will be passed to the AUTOLOAD in AutoLoader.
163              
164             # use attrs 'locked'; # modifies the symbol table and abuses a global
165              
166 12     12   892 my ($constname,$callpkg);
167             { # block to preserve $1,$2,et al.
168 12         15 ($callpkg,$constname) = $AUTOLOAD =~ /^(.*)::(.*)$/;
  12         91  
169             }
170 12 50       56 if (exists $_missing{$AUTOLOAD}) {
171 0         0 my $wh = $SIG{__WARN__};
172 0 0 0     0 die "\n"
      0        
173             if ($wh and (ref($wh) eq 'CODE') and $wh == $nullsub);
174 0         0 croak "Your vendor has not defined $callpkg macro $constname, used";
175             }
176 12 50 33     110 if (@_ && ref $_[0] && @_ < 3 && exists $ {*{$_[0]}}{Keys}{$constname}) {
  8   66     11  
  8   66     54  
177 2     2   19 no strict 'refs'; # allow us to define the sub
  2         4  
  2         399  
178 0         0 my $what = $constname; # don't tie up $constname for closures
179 0 0       0 warn "Auto-generating accessor $AUTOLOAD\n" if $adebug;
180             *$AUTOLOAD = sub {
181 0     0   0 splice @_, 1, 0, $what;
182 0         0 goto &_accessor;
183 0         0 };
184 0         0 goto &$AUTOLOAD;
185             }
186 12 50       30 warn "Autoloading $AUTOLOAD\n" if $adebug;
187 12         26 $AutoLoader::AUTOLOAD = $AUTOLOAD;
188 12         51 goto &AutoLoader::AUTOLOAD;
189             }
190              
191             BEGIN {
192             # do this now so the constant XSUBs really are
193 2     2   24450 __PACKAGE__->DynaLoader::bootstrap($VERSION);
194             }
195              
196              
197             # Preloaded methods go here. Autoload methods go after __END__, and are
198             # processed by the autosplit program.
199              
200              
201             # This package has the core 'generic' routines for fiddling with
202             # sockets.
203              
204              
205             # initsockopts - Set up the socket options of a class using this module.
206             # The structure of a sockopt hash is like this:
207             # %sockopts = ( OPTION => ['pack_string', $option_number, $option_level,
208             # $number_of_elements], ... );
209             # The option level and number are for calling [gs]etsockopt, and
210             # the number of elements is for some (weak) consistency checking.
211             # The pack/unpack template is used by $obj->getsopt and setsopt.
212             # Only the pack template is set on input to this routine. On exit,
213             # it will have deleted any entries which cannot be resolved, and will
214             # have filled in the ones which can. It will also have duplicated
215             # the entries to be indexed by option value as well as by option name.
216              
217             my %evalopts; # avoid compiling an eval per sockopt
218              
219             #& initsockopts($class, $level+0, \%sockopts) : void
220             sub initsockopts : locked
221             {
222 4     4 1 13 my ($class,$level,$opts) = @_;
223 4 50 33     52 croak "Invalid arguments to " . __PACKAGE__ . "::initsockopts, called"
224             if @_ != 3 or ref $opts ne 'HASH';
225 4         12 $level += 0; # force numeric
226 4         11 my($opt,$oval,@oval,$esub);
227 4         8 my $nullwarn = $nullsub; # a handy __WARN__ handler
228             # The above has to be there, since the file-scope 'my' won't be seen
229             # in the generated closure.
230 4 50       16 $class = ref $class if ref $class;
231 2   33 2   21 $evalopts{$class} ||= eval "package $class; no strict 'refs';" .
  2     1   5  
  2     1   187  
  1         11  
  1         2  
  1         89  
  1         8  
  1         3  
  1         76  
  4         400  
232             'sub ($) {local($SIG{__WARN__})=$nullwarn;local($SIG{__DIE__});' .
233             '&{$_[0]}()}';
234 4         13 $esub = $evalopts{$class};
235 4         51 foreach $opt (keys %$opts) {
236 62 100       224 delete $$opts{$opt}, next if exists $_missing{"${class}::$opt"};
237 48         56 $oval = eval {&$esub($opt)};
  48         1326  
238 48 50 33     321 delete $$opts{$opt}, next if $@ or !defined($oval) or $oval eq '';
      33        
239 48         54 $oval += 0; # force numeric
240 48         54 push(@{$$opts{$opt}}, $oval, $level);
  48         126  
241 48         146 $$opts{$oval} = $$opts{$opt};
242 48         294 $oval = $$opts{$opt}[0];
243 48         200 @oval = unpack($oval, pack($oval, 0));
244 48         167 $$opts{$opt}[3] = scalar @oval;
245             }
246             }
247              
248              
249             my %sockopts;
250              
251             # The known socket options (from Socket.pm)
252              
253             %sockopts = (
254             # First, the simple flag options
255              
256             'SO_ACCEPTCONN' => [ 'I' ],
257             'SO_BROADCAST' => [ 'I' ],
258             'SO_DEBUG' => [ 'I' ],
259             'SO_DONTROUTE' => [ 'I' ],
260             'SO_ERROR' => [ 'I' ],
261             'SO_EXPANDED_RIGHTS' => [ 'I' ],
262             'SO_KEEPALIVE' => [ 'I' ],
263             'SO_OOBINLINE' => [ 'I' ],
264             'SO_PAIRABLE' => [ 'I' ],
265             'SO_REUSEADDR' => [ 'I' ],
266             'SO_REUSEPORT' => [ 'I' ],
267             'SO_USELOOPBACK' => [ 'I' ],
268             'SO_XSE' => [ 'I' ],
269              
270             # Simple integer options
271              
272             'SO_RCVBUF' => [ 'I' ],
273             'SO_SNDBUF' => [ 'I' ],
274             'SO_RCVTIMEO' => [ 'I' ],
275             'SO_SNDTIMEO' => [ 'I' ],
276             'SO_RCVLOWAT' => [ 'I' ],
277             'SO_SNDLOWAT' => [ 'I' ],
278             'SO_TYPE' => [ 'I' ],
279             'SO_STATE' => [ 'I' ],
280             'SO_FAMILY' => [ 'I' ],
281              
282             # Finally, one which is a struct
283              
284             'SO_LINGER' => [ 'II' ],
285              
286             # Out of known socket options
287             );
288              
289             __PACKAGE__->initsockopts( SOL_SOCKET(), \%sockopts );
290              
291              
292             #& _genfh() : returns orphan globref with HV slot.
293             sub _genfh ()
294             {
295 7     7   41 my $rval = gensym;
296 7         174 *{$rval} = {}; # initialise a hash slot
  7         20  
297 7         17 $rval;
298             }
299              
300             my $debug = 0; # module-wide debug hack -- don't use
301              
302             # On the other hand, per-object debugging isn't so bad....
303              
304             # can update $debug file variable
305             #& _debug($this [, $newval]) : oldval
306             sub _debug : locked
307             {
308 0     0   0 my ($this,$newval) = @_;
309 0 0       0 return $this->debug($newval) if ref $this;
310             # class method here
311 0         0 my $oldval = $debug;
312 0 0       0 $debug = 0+$newval if defined $newval;
313 0         0 $oldval;
314             }
315              
316             #& debug($self [, $newval]) : oldval
317             sub debug : locked method
318             {
319 347     347 0 491 my ($self,$newval) = @_;
320 347 50       697 my $oldval = $ {*$self}{Parms}{'debug'} if defined wantarray;
  347         904  
321 347 50       970 $self->setparams({'debug'=>$newval}) if defined $newval;
322 347         1281 $oldval;
323             }
324              
325             #& _trace($this, \@args, minlevel, [$moretext]) : void
326             sub _trace
327             {
328 191     191   339 my ($this,$aref,$level,$msg) = @_;
329 191         1229 my $rtn = (caller(1))[3];
330             # local $^W=0; # keep the arglist interpolation from carping
331 191 100       1010 $msg = '' unless defined $msg;
332 191 0 33     897 print STDERR "${rtn}(@{$aref||[]})${msg}\n"
  0 50       0  
333             if $level and $this->_debug >= $level;
334 191         815 ${rtn};
335             }
336              
337             #& _setdebug($self, $name, $newval) : {'' | "carp string"}
338             sub _setdebug
339             {
340 8     8   14 my ($self,$what,$val) = @_;
341 8 50       20 return '' unless defined $val;
342 8 50 33     69 return "$self->{$what} parameter ($val) must be non-negative integer"
343             if $val eq '' or $val =~ /\D/;
344 8         13 $_[2] += 0; # force numeric
345 8         19 ''; # return goodness
346             }
347              
348             # try to work even in places where Fcntl.xs doesn't.
349              
350 2     2   12 my ($F_GETFL,$F_SETFL) =
  2         4  
  2         170  
351             eval 'use Fcntl qw(F_GETFL F_SETFL);(F_GETFL,F_SETFL)';
352             my $nonblock_flag = eval 'pack("I",VAL_O_NONBLOCK)';
353             my $eagain = eval 'VAL_EAGAIN';
354              
355             #& _accessor($self, $what [, $newval]) : oldvalue
356             sub _accessor : locked method
357             {
358 0     0   0 my ($self, $what, $newval) = @_;
359 0 0       0 croak "Usage: \$sock->$what or \$sock->$what(\$newvalue),"
360             if @_ > 3;
361 0 0       0 my $oldval = $self->getparam($what) if defined wantarray;
362 0 0       0 $self->setparams({$what=>$newval}) if @_ > 2;
363 0         0 $oldval;
364             }
365              
366             #& _setblocking($self, $name, $newval) : {'' | "carp string"}
367             sub _setblocking
368             {
369 19     19   34 my ($self,$what,$newval) = @_;
370 19 50       52 $newval = 1 unless defined $newval;
371             # default previous value, just in case
372 0         0 $ {*$self}{Parms}{$what} = 1 unless
  19         87  
373 19 50       22 defined $ {*$self}{Parms}{$what};
374 19 100       42 if ($newval) {
375 17         28 $_[2] = 1; # canonicalise the new value
376 17 100 33     156 if (defined $F_GETFL and defined $F_SETFL and
      33        
      66        
377             defined $nonblock_flag and $self->isopen)
378             {
379 9 100       68 if ((CORE::fcntl($self, $F_GETFL, 0) & VAL_O_NONBLOCK) ==
380             VAL_O_NONBLOCK)
381             {
382 2         4 $ {*$self}{Parms}{$what} = 0; # note previous status
  2         7  
383 2         17 return 'Failed to clear non-blocking status'
384 2 50       5 unless eval {CORE::fcntl($self, $F_SETFL,
385             CORE::fcntl($self, $F_GETFL, 0) &
386             ~VAL_O_NONBLOCK)};
387             }
388             }
389             }
390             else {
391 2         5 $_[2] = 0; # canonicalise the new value
392 2 50 33     20 unless (defined $F_GETFL and defined $F_SETFL and
      33        
393             defined $nonblock_flag)
394             {
395 0         0 return 'Non-blocking sockets unavailable in this configuration';
396             }
397 2 50       8 if ($self->isopen) {
398 2 50       20 if ((CORE::fcntl($self, $F_GETFL, 0) & VAL_O_NONBLOCK) !=
399             VAL_O_NONBLOCK)
400             {
401 2         5 $ {*$self}{Parms}{$what} = 1; # note previous state
  2         7  
402 2         20 return 'Failed to set non-blocking status'
403 2 50       6 unless eval {CORE::fcntl($self, $F_SETFL,
404             CORE::fcntl($self, $F_GETFL, 0) |
405             VAL_O_NONBLOCK)};
406             }
407             }
408             }
409 19         57 ''; # return goodness if got this far
410             }
411              
412             #& blocking($self [, $newval]) : canonical_oldval
413             sub blocking : locked method
414             {
415 1     1 1 3 my ($self, $newval) = @_;
416 1 50       6 croak 'Usage: $sock->blocking or $sock->blocking(0|1),'
417             if @_ > 2;
418 1 50       7 my $oldval = $self->getparam('blocking', 1, 1) if defined wantarray;
419 1 50       6 $self->setparams({'blocking'=>$newval}) if @_ > 1;
420 1         6 $oldval;
421             }
422              
423             #& _settimeout($self, $what, $newval) : {'' | "carp string"}
424             sub _settimeout
425             {
426 3     3   7 my ($self,$what,$newval) = @_;
427 3 50       11 unless (defined $newval) {
428 0         0 return ''; # It's always OK to delete a timeout.
429             }
430 3 50 33     49 if (!length($newval) or $newval =~ /\D/) {
431 0         0 "Parameter $what must be a non-negative integer or undefined";
432             }
433             else {
434 3         9 '';
435             }
436             }
437              
438             my @Keys = qw(PF AF type proto dstaddr dstaddrlist srcaddr srcaddrlist
439             maxqueue reuseaddr netgen_fakeconnect reuseport);
440             my %Codekeys = (
441             'debug' => \&_setdebug,
442             'blocking' => \&_setblocking,
443             'timeout' => \&_settimeout,
444             );
445             # This hash remembers the original {Keys} settings after the first time.
446             my %Keys;
447              
448             # This hash remembers the original socket option settings after the first time.
449             my %Opts;
450              
451             #& register_param_keys($self, \@keys)
452             sub register_param_keys : locked method
453             {
454 5     5 1 10 my ($self, $names) = @_;
455 5         14 my $whoami = $self->_trace(\@_,3);
456 5 50 33     45 croak "Invalid arguments to ${whoami}(@_), called"
457             if @_ != 2 or ref $names ne 'ARRAY';
458 5         7 @{$ {*$self}{Keys}}{@$names} =
  5         71  
  5         24  
459 5         9 @{$ {*$self}{Keys}}{@$names}; # remember the names
  5         7  
460             # this form doesn't clobber pre-existing register_param_handlers values
461             }
462              
463             sub registerParamKeys; # helps with -w
464             *registerParamKeys = \®ister_param_keys; # alias form preferred by many
465              
466             #& register_param_handlers($self, \@keys, [\]@handlers)
467             #& -or- ($self, \%key-handlers)
468             sub register_param_handlers : locked method
469             {
470 5     5 1 9 my ($self, $names, @handlers, $handlers) = @_;
471 5         16 my $whoami = $self->_trace(\@_,3);
472 5 50       18 if (ref $names eq 'HASH') {
473 5 50       20 croak "Invalid parameters to ${whoami}(@_), called"
474             if @_ != 2;
475 5         25 $handlers = [values %$names];
476 5         82 $names = [keys %$names];
477             }
478             else {
479 0 0 0     0 croak "Invalid parameters to ${whoami}(@_), called"
480             if @_ < 3 or ref $names ne 'ARRAY';
481 0         0 $handlers = \@handlers; # in case passed as a list
482 0 0 0     0 $handlers = $_[2] if @_ == 3 and ref($_[2]) eq 'ARRAY';
483             }
484 5 50 33     43 croak "Invalid handlers in ${whoami}(@_), called"
485             if @$handlers != @$names or grep(ref $_ ne 'CODE', @$handlers);
486             # finally, all is validated, so set the bloody things
487 5         16 @{$ {*$self}{Keys}}{@$names} = @$handlers;
  5         7  
  5         38  
488             }
489              
490             sub registerParamHandlers; # helps with -w
491             *registerParamHandlers = \®ister_param_handlers; # alias other form
492              
493             #& register_options($self, $levelname, $level, \%options)
494             sub register_options : locked method
495             {
496 3     3 1 7 my ($self, $levname, $level, $opts) = @_;
497 3         13 my $whoami = $self->_trace(\@_,3);
498 3 50       20 croak "Invalid arguments to ${whoami}(@_), called"
499             if ref $opts ne 'HASH';
500 3         5 $ {*$self}{Sockopts}{$levname} = $opts;
  3         20  
501 3         21 $ {*$self}{Sockopts}{$level+0} = $opts;
  3         17  
502             }
503              
504             sub registerOptions; # helps with -w
505             *registerOptions = \®ister_options; # alias form preferred by many
506              
507             # pseudo-subclass for saving parameters (ParamSaver, inspired by SelectSaver)
508             #& param_saver($self, @params) : restoration_object
509             sub param_saver : locked method
510             {
511 2     2 1 8 my ($self, @params) = @_;
512 2         12 my @delparams =
513             # map { exists $ {*$self}{Parms}{$_} ? () : ($_) } @params;
514 2         5 grep {!exists $ {*$self}{Parms}{$_}} @params;
  2         3  
515 2         7 my %setparams = $self->getparams(\@params);
516 2         50 bless [$self, \%setparams, \@delparams], 'Net::Gen::ParamSaver';
517             }
518              
519             sub paramSaver; # aliases
520             *paramSaver = \¶m_saver;
521             sub ParamSaver;
522             *ParamSaver = \¶m_saver;
523              
524             sub Net::Gen::ParamSaver::DESTROY
525             {
526 2     2   22 local $!; # just to be sure we don't clobber it
527 2         19 $_[0]->[0]->setparams($_[0]->[1]);
528 2         10 $_[0]->[0]->delparams($_[0]->[2]);
529             }
530              
531             #& new(classname [, \%params]) : {$self | undef}
532             #& -or- $classname [, @ignored]
533             sub new
534             {
535 7     7 1 35 my $whoami = $_[0]->_trace(\@_,1);
536 7         18 my($pack,$parms) = @_;
537 7         14 my %parms;
538 7 100 100     53 %parms = ( %$parms ) if $parms and ref $parms eq 'HASH';
539 7 50       39 $parms{'debug'} = $pack->_debug unless defined $parms{'debug'};
540 7 50       33 $parms{'blocking'} = 1 unless defined $parms{'blocking'};
541 7 50 66     135 if (@_ > 2 and $parms and ref $parms eq 'HASH') {
      66        
542 0         0 croak "Invalid argument format to ${whoami}(@_), called";
543             }
544 7   66     35 my $class = ref $pack || $pack;
545 7         26 my $self = _genfh;
546 7         31 bless $self,$class;
547 7         90 $pack->_trace(\@_,2,", self=$self after bless");
548 7         12 $ {*$self}{Parms} = \%parms;
  7         30  
549 7 100       29 if (%Keys) {
550 5         80 $ {*$self}{Keys} = { %Keys };
  5         20  
551 5         29 $ {*$self}{Sockopts} = { %Opts };
  5         16  
552             }
553             else {
554 2         18 $self->register_param_keys(\@Keys); # register our keys
555 2         26 $self->register_param_handlers(\%Codekeys);
556 2         23 $self->register_options('SOL_SOCKET', SOL_SOCKET(), \%sockopts);
557 2         3 %Keys = %{$ {*$self}{Keys}};
  2         5  
  2         19  
558 2         6 %Opts = %{$ {*$self}{Sockopts}};
  2         9  
  2         10  
559             }
560 7 50       29 if ($class eq __PACKAGE__) {
561 0 0       0 unless ($self->init) {
562 0         0 local $!; # preserve errno
563 0         0 undef $self; # against the side-effects of this
564 0         0 undef $self; # another statement needed for unwinding
565             }
566             }
567 7 50 33     37 if (($self || $pack)->_debug) {
568 0 0       0 if (defined $self) {
569 0         0 print STDERR "${whoami} returning self=$self\n";
570             }
571             else {
572 0         0 print STDERR "${whoami} returning undef\n";
573             }
574             }
575 7         30 $self;
576             }
577              
578             #& setparams($this, \%newparams [, $newonly [, $check]]) : boolean
579             sub setparams : locked method
580             {
581 60     60 1 1221 my ($self,$newparams,$newonly,$check) = @_;
582 60         72 my $errs = 0;
583              
584 60 50 33     312 croak "Bad arguments to " . __PACKAGE__ . "::setparams, called"
585             unless @_ > 1 and ref $newparams eq 'HASH';
586 60 50       126 carp "Excess arguments to " . __PACKAGE__ . "::setparams ignored"
587             if @_ > 4;
588              
589 60   100     174 $newonly ||= 0; # undefined or zero is equiv now (-w problem)
590 60         67 my ($parm,$newval,$pslot);
591 60         228 while (($parm,$newval) = each %$newparams) {
592 167 0       377 print STDERR __PACKAGE__ . "::setparams $self $parm" .
    50          
593             (defined $newval ? " $newval" : "") . "\n"
594             if $self->debug;
595 167         482 (carp "Unknown parameter type $parm for a " . (ref $self) . " object")
596             , $errs++, next
597 167 50       194 unless exists $ {*$self}{Keys}{$parm};
598 167         207 $pslot = \$ {*$self}{Parms}{$parm};
  167         358  
599 167 100 100     562 next if $newonly < 0 && defined $$pslot;
600 162 100       457 if (!$check)
601             {
602             # this ungodly construct brought to you by -w
603             next if
604 83 100 66     531 defined($$pslot) eq defined($newval)
      66        
605             and
606             !defined($newval) ||
607             $$pslot eq $newval ||
608             $$pslot !~ /\D/ &&
609             $newval !~ /\D/ &&
610             length($newval) &&
611             length($$pslot) &&
612             $$pslot == $newval
613             ;
614             }
615 160 50 33     367 carp("Overwrite of $parm parameter for ".(ref $self)." object ignored")
616             , $errs++, next
617             if $newonly > 0 && defined $$pslot;
618 160 100 66     144 if (defined($ {*$self}{Keys}{$parm}) and
  160         560  
  43         185  
619             (ref($ {*$self}{Keys}{$parm}) eq 'CODE'))
620             {
621 43         60 my $rval = &{$ {*$self}{Keys}{$parm}}($self,$parm,$newval);
  43         46  
  43         169  
622 43 50       130 (carp $rval), $errs++, next if $rval;
623             }
624             # not using $$pslot here in case {Parms} hash re-generated
625 160         205 $ {*$self}{Parms}{$parm} = $newval;
  160         710  
626             }
627              
628 60 50       363 $errs ? undef : 1;
629             }
630            
631              
632             #& delparams($self, \@paramnames) : boolean
633             sub delparams : locked method
634             {
635 8     8 1 25 $_[0]->_trace(\@_,1);
636 8         15 my($self,$keysref) = @_;
637 8         10 my(@k,%k);
638 8         20 @k = grep(exists $ {*$self}{Parms}{$_}, @$keysref);
  12         41  
639 8 100       60 return 1 unless @k; # if no keys need deleting, succeed vacuously
640 5         40 @k{@k} = (); # a hash of undefs for the following
641 5 50       16 return undef unless $self->setparams(\%k); # see whether undef is allowed
642 5         10 delete @{$ {*$self}{Parms}}{@k};
  5         6  
  5         20  
643 5         20 1; # return goodness
644             }
645              
646             #& checkparams($self) : boolean
647             sub checkparams : locked method
648             {
649 8     8 1 36 my $whoami = $_[0]->_trace(\@_,1);
650 8         15 my $self = shift;
651 8 50       30 carp "Excess arguments to ${whoami} ignored"
652             if @_;
653 8         16 my $curparms = $ {*$self}{Parms};
  8         20  
654 8 50       29 $curparms = {} unless ref $curparms eq 'HASH';
655             # make sure only the valid ones are set when we're done
656 8         12 $ {*$self}{Parms} = {};
  8         18  
657 8         37 my(@valkeys) = grep(exists $ {*$self}{Keys}{$_}, keys %$curparms);
  71         511  
658             # this assignment allows for inter-key dependencies to be evaluated
659 8         10 @{$ {*$self}{Parms}}{@valkeys} =
  8         55  
  8         22  
660 8         20 @{$curparms}{@valkeys};
661             # validate all current against the defined keys
662 8         33 $self->setparams($curparms, 0, 1);
663             }
664              
665             #& init($self) : {$self | undef}
666             sub init
667             {
668 7     7 1 31 $_[0]->_trace(\@_,1);
669 7         16 my($self) = @_;
670 7 50       43 $self->checkparams ? $self : undef;
671             }
672              
673             #& getparam($self, $key [, $default [, $defaultifundef]]) : param_value
674             sub getparam : locked method
675             {
676 36     36 1 833 my $whoami = $_[0]->_trace(\@_,2);
677 36         76 my($self,$key,$defval,$noundef) = @_;
678 36 50       170 carp "Excess arguments to ${whoami}($self) ignored"
679             if @_ > 4;
680 36 100       68 if ($noundef) {
681 16 100       18 return $defval unless defined($ {*$self}{Parms}{$key});
  16         89  
682             }
683             else {
684 20 100       28 return $defval unless exists($ {*$self}{Parms}{$key});
  20         135  
685             }
686 31         51 $ {*$self}{Parms}{$key};
  31         1425  
687             }
688              
689             #& getparams($self, \@keys [, $noundef]) : (%hash)
690             sub getparams : locked method
691             {
692 17     17 1 59 my $whoami = $_[0]->_trace(\@_,2);
693 17         37 my ($self,$aref,$noundef) = @_;
694 17 50 33     148 croak "Insufficient arguments to ${whoami}($self), called"
      33        
695             if @_ < 2 || !ref $self || ref $aref ne 'ARRAY';
696 17 50       47 carp "Excess arguments to ${whoami}($self) ignored"
697             if @_ > 3;
698 17 50       59 return unless defined wantarray;
699 17 100       38 if (wantarray) {
700             # the actual list is wanted -- see which way to do it
701 2 50       7 if ($noundef) {
702 0         0 map {defined $ {*$self}{Parms}{$_} ?
  0         0  
  0         0  
703 0 0       0 ($_, $ {*$self}{Parms}{$_}) :
704             ()
705             } @$aref;
706             }
707             else {
708 2         4 map {exists $ {*$self}{Parms}{$_} ?
  2         10  
  2         17  
709 2 50       4 ($_, $ {*$self}{Parms}{$_}) :
710             ()
711             } @$aref;
712             }
713             }
714             else {
715             # the list count is wanted -- see which way to do it
716 15 50       35 if ($noundef) {
717 15         28 2 * grep {defined $ {*$self}{Parms}{$_}} @$aref;
  40         45  
  40         213  
718             }
719             else {
720 0         0 2 * grep {exists $ {*$self}{Parms}{$_}} @$aref;
  0         0  
  0         0  
721             }
722             }
723             # my @ret;
724             # foreach (@$aref) {
725             # push(@ret, $_, $ {*$self}{Parms}{$_})
726             # if exists($ {*$self}{Parms}{$_}) and
727             # !$noundef || defined($ {*$self}{Parms}{$_});
728             # }
729             # wantarray ? @ret : 0+@ret;
730             }
731            
732              
733             #& condition($self)
734             sub condition : locked method
735             {
736 7     7 1 17 my $self = $_[0];
737 7         68 my $sel = SelectSaver->new;
738 7         113 CORE::select($self);
739 7         38 $| = 1;
740             # $\ = "\015\012";
741 7         24 binmode($self);
742 7         13 vec($ {*$self}{FHVec} = '', CORE::fileno($self), 1) = 1;
  7         131  
743 7         35 $self->setparams({'blocking'=>$self->getparam('blocking',1,1)},0,1);
744             }
745              
746             #& open($self [, @ignore]) : boolean
747             sub open : locked method
748             {
749 6     6 1 34 $_[0]->_trace(\@_,2);
750 6         12 my $self = shift;
751 6 50       17 $self->stopio if $self->isopen;
752 6         16 my($pf,$af,$type,$proto) = \@{$ {*$self}{Parms}}{qw(PF AF type proto)};
  6         10  
  6         29  
753 6 50       22 $$pf = PF_UNSPEC unless defined $$pf;
754 6 50       17 $$af = AF_UNSPEC unless defined $$af;
755 6 50       102 $$type = 0 unless defined $$type;
756 6 100       18 $$proto = 0 unless defined $$proto;
757 6 50 33     87 if (($$pf == PF_UNSPEC) && ($$af != AF_UNSPEC)) {
    50 33        
758 0         0 $$pf = $$af;
759             }
760             elsif (($$af == AF_UNSPEC) && ($$pf != PF_UNSPEC)) {
761 0         0 $$af = $$pf;
762             }
763 6 50       280 if ($ {*$self}{'isopen'} = socket($self,$$pf,$$type,$$proto)) {
  6         35  
764             # keep stdio output buffers out of my way
765 6         40 $self->condition;
766             }
767 6         74 $self->isopen;
768             }
769              
770             # sub listen - autoloaded
771              
772             # hashes for async. connect error values
773             my %connok = ( EISCONN,1 );
774             my %connip = ( EWOULDBLOCK,1 , EINPROGRESS,1 , EAGAIN,1 , EALREADY,1 );
775              
776             #& _valconnect($self, $addr, $timeout) : boolean
777             sub _valconnect
778             {
779 0     0   0 my ($self,$addr,$timeout) = @_;
780 0         0 my ($fhvec,$rdvec,$wrvec,$nfound) = $ {*$self}{FHVec};
  0         0  
781             # don't block if socket is non-blocking
782 0         0 $timeout = 0 if
783 0 0 0     0 !defined $timeout && !$ {*$self}{Parms}{'blocking'};
784             # assume caller checked for ->isconnecting
785 0         0 $rdvec = $wrvec = $fhvec;
786 0         0 $nfound = CORE::select($rdvec, $wrvec, undef, $timeout);
787             # If socket is 'ready', then the connect is complete (possibly failed).
788 0 0       0 $ {*$self}{'isconnecting'} = 0 if $nfound;
  0         0  
789             # If we don't think the connect has finished, just try to invent a
790             # reasonable error and bug out.
791 0 0       0 if (!$nfound) {
792 0         0 $! = EINPROGRESS || EWOULDBLOCK || EALREADY || EAGAIN;
793 0         0 return;
794             }
795 0         0 my $rval;
796             # If we can try to find out with SO_ERROR, give it a shot.
797             # This won't give valid results with SOCKS. Tough.
798 0 0       0 if ($ {*$self}{Sockopts}{'SOL_SOCKET'}{'SO_ERROR'}) {
  0         0  
799             # Don't try the getsockopt if the connect is still pending!
800             # Solaris 2.5.1 (at least) hangs the getsockopt in that case.
801             # The connect is complete -- figure out whether we believe
802             # the status.
803 0         0 $rval = getsockopt($self,SOL_SOCKET,SO_ERROR);
804 0 0       0 return unless defined $rval;
805 0         0 $rval = unpack("I", $rval);
806 0 0       0 if ($rval) {
807 0         0 $! = $rval;
808 0         0 return;
809             }
810 0 0       0 return unless defined getpeername($self);
811 0         0 return 1;
812             }
813             # Here, we can't use SO_ERROR (it's not available).
814             # The canonical test for success here involves a read() attempt, but
815             # we can't use that unless we have a stream socket. SOCK_SEQPACKET and
816             # real datagram services would lose their initial transmission to a
817             # read check. So, we try it here only if we think we are SOCK_STREAM.
818 0         0 my $type = $ {*$self}{Parms}{'type'};
  0         0  
819 0 0 0     0 if ($type && $type==SOCK_STREAM) {
820 0         0 my $buf = "";
821 0         0 $rval = sysread($self,$buf,0);
822 0 0       0 return unless defined $rval;
823             # It succeeded. Should it have? If getpeername says so,
824             # we still can't be sure, and we'll have to use a second connect().
825             }
826 0 0       0 return unless defined getpeername($self);
827 0         0 $rval = CORE::connect($self,$addr);
828 0 0       0 return $rval if $rval;
829 0 0       0 return 1 if $connok{0+$!};
830 0         0 $rval;
831             }
832              
833             #& _tryconnect($self, $addr, $timeout) : boolean
834             sub _tryconnect
835             {
836 2     2   5 my ($self,$addr,$timeout) = @_;
837 2 50       3 if ($ {*$self}{'isconnecting'}) {
  2         9  
838 0 0 0     0 if ($ {*$self}{Parms}{'dstaddr'} and
  0         0  
  0         0  
839             ($ {*$self}{Parms}{'dstaddr'} ne $addr))
840             {
841 0         0 carp "$self->_tryconnect: different destination address while ->isconnecting!"
842 0 0       0 if $ {*$self}{Parms}{'debug'} > 2;
843 0         0 $self->stopio;
844 0 0       0 return undef unless $self->open;
845 0 0 0     0 if ($self->getparam('srcaddr') || $self->getparam('srcaddrlist')
      0        
846             and !$self->isbound)
847             {
848 0 0       0 return undef unless $self->bind;
849             }
850             }
851             }
852             # Apparently, some versions of Solaris don't like a second connect.
853             # So, if we're retrying a non-blocking connect, check by other means
854             # before trying to use a second connect to get the status.
855             # Warning: This will not work with SOCKS.
856 2 50       4 unless ($ {*$self}{'isconnecting'}) {
  2         8  
857             # For Solaris, if datagram socket, don't connect if not bound.
858 2 100       3 if ($ {*$self}{Parms}{netgen_fakeconnect}) {
  2         11  
859 1 50       7 if (!$self->isbound) {
860 1         1 $ {*$self}{Parms}{'dstaddr'} = $addr;
  1         4  
861 1         10 return 1;
862             }
863             else {
864 0         0 $self->delparams(['netgen_fakeconnect']);
865             }
866             }
867 1         42 my $rval = CORE::connect($self,$addr);
868 1 50       7 return $rval if $rval;
869 0 0       0 return 1 if $connok{0+$!};
870 0 0       0 return $rval unless $connip{0+$!};
871 0         0 $ {*$self}{'isconnecting'} = 1;
  0         0  
872 0         0 $ {*$self}{Parms}{'dstaddr'} = $addr;
  0         0  
873 0 0       0 return $rval unless defined $timeout;
874             }
875 0         0 &_valconnect;
876             }
877              
878             #& connect($self, [@ignored]) : boolean
879             sub connect : locked method
880             {
881 2     2 1 9 $_[0]->_trace(\@_,2);
882 2         4 my $self = shift;
883 2         7 my $hval = *$self{HASH};
884 2         4 my $parms = $hval->{Parms};
885 2 50 33     29 $self->close if
      33        
886             $hval->{'isconnected'} ||
887             (!$hval->{'isconnecting'} && $hval->{'wasconnected'});
888 2 50 66     6 return undef unless $self->isopen or $self->open;
889 2 0 33     16 if ($parms->{'srcaddr'} || $parms->{'srcaddrlist'}
      33        
      33        
890             and !$hval->{'isconnecting'} and !$self->isbound)
891             {
892 0 0       0 return undef unless $self->bind;
893             }
894 2         3 my $rval;
895 2         3 my $error = 0; # errno to propagate if failing
896             {
897 2         4 my ($saveblocking,$timeout);
  2         3  
898 2 100 66     18 if (defined ($timeout = $parms->{'timeout'}) && $self->blocking) {
899 1         9 $saveblocking = $self->param_saver('blocking');
900 1 50       8 $self->setparams({'blocking'=>0}) or undef $timeout;
901             }
902 2         7 my $dlist = $parms->{dstaddrlist};
903 2 50 33     20 if (defined($dlist) and
      33        
904             ref($dlist) eq 'ARRAY' and
905             !$hval->{'isconnecting'})
906             {
907 2         4 my $tryaddr;
908 2         10 foreach $tryaddr (@{$dlist}) {
  2         5  
909 2         9 $rval = _tryconnect($self, $tryaddr, $timeout);
910 2 50       19 $parms->{dstaddr} = $tryaddr if $rval;
911 2 50 0     9 last if $rval or
      0        
      33        
912             defined $timeout && !$timeout
913             and $connip{0+$!};
914             }
915             }
916             else {
917 0         0 $rval = _tryconnect($self, $parms->{dstaddr}, $timeout);
918             }
919 2 50       18 $error = $!+0 unless $rval;
920             }
921 2         7 $hval->{'isconnected'} = $rval;
922 2         5 $hval->{'wasconnected'} = '0 but true';
923 2 50       5 if (!$rval) {
924 0         0 $! = $error;
925 0         0 return $rval;
926             }
927 2         11 $self->getsockinfo;
928 2         17 $self->isconnected;
929             }
930              
931             #& getsockinfo($self, [@ignored]) : ?dest sockaddr?
932             sub getsockinfo : locked method
933             {
934 7     7 1 30 $_[0]->_trace(\@_,4);
935 7         14 my $self = shift;
936 7         12 my ($sad,$dad);
937              
938 7 100       83 $self->setparams({dstaddr => $dad}) if defined($dad = getpeername($self));
939 7 50       88 $self->setparams({srcaddr => $sad}) if defined($sad = getsockname($self));
940             wantarray ?
941 7 50 33     124 ((defined($sad) || defined($dad)) ? ($sad, $dad) : ()) :
    100 33        
942             $sad && $dad;
943             }
944              
945             # 'static' hashes for translating between SHUT_* values and the traditional
946             # (but off-by-one) 1-3. Used for marking shutdown progress. The connect
947             # code helps in the conspiracy by setting '0 but true' rather than '0'.
948              
949             my %to_shut_flags = (SHUT_RD,1, SHUT_WR,2, SHUT_RDWR,3);
950              
951             #& shutdown($self [, $how=SHUT_RDWR]) : boolean
952             sub shutdown : locked method
953             {
954 5     5 1 13 $_[0]->_trace(\@_,3);
955 5         7 my $self = shift;
956 5 100 66     13 return 1 unless $self->isconnected or $self->isconnecting;
957 3         8 my $how = shift;
958 3 0 33     19 $how = SHUT_RDWR unless defined $how and $how !~ m/\D/ and length $how;
      33        
959 3         5 $how += 0;
960 3         8 my $xhow = $to_shut_flags{$how};
961 3 50       8 ($how = SHUT_RDWR), ($xhow = 3)
962             unless $xhow;
963 3         5 my $was = ($ {*$self}{'wasconnected'} |= $xhow);
  3         12  
964 3         22 my $rval = CORE::shutdown($self, $how);
965 3         15 local $!; # preserve shutdown()'s errno
966 3         10 $ {*$self}{'isconnecting'} = $ {*$self}{'isconnected'} = 0 if
  3         7  
  0         0  
967             $was == 3 or
968 3 50 0     14 (!defined(getpeername($self)) && ($ {*$self}{'wasconnected'} = 3));
      33        
969 3         10 $rval;
970             }
971              
972              
973             my @CloseVars = qw(FHVec isopen isbound didlisten wasconnected isconnected
974             isconnecting);
975             my @CloseKeys = qw(srcaddr dstaddr);
976              
977             #& close($self [, @ignored]) : boolean
978             sub close : locked method
979             {
980 5     5 1 789 $_[0]->_trace(\@_,3);
981 5         10 my $self = shift;
982 5 50       15 $self->shutdown if $self->isopen;
983 5         25 $self->stopio;
984             }
985              
986             sub CLOSE;
987             *CLOSE = \&close;
988              
989             #& stopio($self [, @ignored]) : boolean
990             sub stopio : locked method
991             {
992 6     6 1 20 $_[0]->_trace(\@_,4);
993 6         11 my $self = shift;
994 6         13 my $wasopen = $self->isopen;
995 6         15 @{*$self}{@CloseVars} = (); # these flags no longer true
  6         32  
996 6         30 $self->delparams(\@CloseKeys); # connection values now invalid
997 6 100       41 return 1 unless $wasopen;
998 5         155 CORE::close($self);
999             }
1000              
1001             # I/O enries
1002              
1003             # Warning! No intercepting of SIGPIPE is done, so the output routines
1004             # can abort the program.
1005              
1006             # Note that (at least) Solaris 2.5.1 doesn't like connect() on datagram
1007             # sockets, at least not if they're not bound. So, we fake it here.
1008              
1009             #& send($self, $buf, [$flags, [$where]]) : boolean
1010             sub send
1011             {
1012 6     6 1 7849 my $whoami = $_[0]->_trace(\@_,3);
1013 6         18 my($self,$buf,$flags,$whither) = @_;
1014 6 50 33     45 croak "Invalid args to ${whoami}, called"
1015             if @_ < 2 or !ref $self;
1016 6 100       18 $flags = 0 unless defined $flags;
1017 6 50       18 carp "Excess arguments to ${whoami} ignored" if @_ > 4;
1018             # send(2) requires connect(2)
1019 6 100 100     39 if (!(defined $whither or $self->isconnected)) {
  3 100 100     16  
1020 2 50       16 if ($self->getparams([qw(dstaddrlist dstaddr)],1) > 0) {
1021 0 0       0 return undef unless $self->connect;
1022 0 0       0 if ($ {*$self}{Parms}{netgen_fakeconnect}) {
  0         0  
1023 0         0 $whither = $ {*$self}{Parms}{'dstaddr'};
  0         0  
1024             }
1025             }
1026             else {
1027 2 50       9 if ($flags & MSG_OOB) {
1028 0         0 $whither = $ {*$self}{lastOOBFrom};
  0         0  
1029             }
1030             else {
1031 2         3 $whither = $ {*$self}{lastRegFrom};
  2         9  
1032             }
1033             # Can't short-circuit this--need to get the right errno value.
1034             # return undef unless defined $whither or $self->connect;
1035             }
1036             }
1037             elsif ($self->isconnected && $ {*$self}{Parms}{netgen_fakeconnect}) {
1038 1 50       5 if (defined $whither) {
1039             # *sigh* -- what errno should I return?
1040 0         0 $! = EISCONN || EINVAL;
1041 0         0 return undef;
1042             }
1043 1         2 $whither = $ {*$self}{Parms}{'dstaddr'};
  1         4  
1044             }
1045 6 50       30 return getsockopt($self,SOL_SOCKET,SO_TYPE) unless
1046             $self->isopen; # generate EBADF return if not open
1047 6 100       268 defined $whither
1048             ? CORE::send($self, $buf, $flags, $whither)
1049             : CORE::send($self, $buf, $flags);
1050             }
1051              
1052             sub SEND;
1053             *SEND = \&send;
1054              
1055             #& put($self, @stuff) : boolean
1056             sub put
1057             {
1058 0     0 1 0 $_[0]->_trace(\@_,3);
1059 0         0 my($self,@args) = @_;
1060 0         0 print {$self} @args;
  0         0  
1061             }
1062              
1063             sub PRINT; # avoid -w error
1064             *PRINT = \&put; # alias that may someday be used for tied FH
1065             sub print; # avoid -w error
1066             *print = \&put; # maybe-useful alias
1067              
1068             #& ckeof($self) : boolean
1069             sub ckeof : locked method
1070             {
1071 0     0 1 0 my $saverr = $!+0;
1072 0         0 local $!; # preserve this over fcntl() and such
1073 0         0 my $whoami = $_[0]->_trace(\@_,3);
1074 0         0 my($self) = @_;
1075 0 0 0     0 croak "Invalid args to ${whoami}, called"
1076             if !@_ or !ref $self;
1077             # Bug out if we shouldn't have been called.
1078 0         0 return 1 if EOF_NONBLOCK or $saverr != $eagain;
1079             # Bug out early if not a socket where EOF is possible.
1080 0 0       0 return 0
1081             unless unpack('I',getsockopt($self,SOL_SOCKET,SO_TYPE)) == SOCK_STREAM;
1082             # See whether need to test for non-blocking status.
1083 0 0       0 my $flags = ($F_GETFL ? CORE::fcntl($self,$F_GETFL,0+0) : undef);
1084 0 0 0     0 if ((defined($flags) && defined($nonblock_flag))
    0          
1085             ? ($flags & VAL_O_NONBLOCK)
1086             : 1)
1087             {
1088             # *sigh* -- no way to tell, here
1089 0         0 return 0;
1090             }
1091 0         0 1; # wrong errno or blocking
1092             }
1093              
1094             #& recv($self, [$maxlen, [$flags, [$from]]]) : {$buf | undef}
1095             sub recv : locked method
1096             {
1097 5     5 1 1262 my $whoami = $_[0]->_trace(\@_,3);
1098 5         14 my($self,$maxlen,$flags) = @_;
1099 5         13 my($buf,$from,$xfrom) = '';
1100 5 50 33     33 croak "Invalid args to ${whoami}, called"
1101             if !@_ or !ref $self;
1102 5 50       16 carp "Excess arguments to ${whoami} ignored"
1103             if @_ > 4;
1104 5 50 33     18 return getsockopt($self,SOL_SOCKET,SO_TYPE) unless
1105             $self->isopen or $self->open; # generate EBADF return if not open
1106 5 100 50     48 $maxlen = unpack('I',getsockopt($self,SOL_SOCKET,SO_RCVBUF)) ||
1107             (stat $self)[11] || 8192
1108             unless $maxlen;
1109 5 100       16 $flags = 0 unless defined $flags;
1110 5 50 33     9 if (defined($ {*$self}{sockLineBuf}) && !$flags) {
  5         28  
1111 0         0 $buf = $ {*$self}{sockLineBuf};
  0         0  
1112 0 0       0 if (length($buf) > $maxlen) {
1113 0         0 $ {*$self}{sockLineBuf} = substr($buf, $maxlen);
  0         0  
1114 0         0 substr($buf, $maxlen) = '';
1115             }
1116             else {
1117 0         0 undef $ {*$self}{sockLineBuf};
  0         0  
1118             }
1119 0 0       0 $_[3] = $ {*$self}{lastRegFrom} if @_ > 3;
  0         0  
1120 0         0 return $buf;
1121             }
1122 5         15 $! = 0; # ease EOF checking
1123 5         105 $xfrom = $from = CORE::recv($self,$buf,$maxlen,$flags);
1124 5         16 my $errnum = $!+0; # preserve possible recv failure
1125 5 100 66     54 $xfrom = getpeername($self) if defined($from) and $from eq '';
1126 5 100 100     58 $from = $xfrom if defined($xfrom) and $from eq '' and $xfrom ne '';
      66        
1127 5         8 $ {*$self}{lastFrom} = $from;
  5         18  
1128 5 100       19 $_[3] = $from if @_ > 3;
1129 5 50       17 if ($flags & MSG_OOB) {
1130 0         0 $ {*$self}{lastOOBFrom} = $from;
  0         0  
1131             }
1132             else {
1133 5         11 $ {*$self}{lastRegFrom} = $from;
  5         17  
1134             }
1135 5         14 $! = $errnum; # restore possible failure in case we return
1136 5 50 50     23 return undef if !defined $from and (EOF_NONBLOCK or $errnum != $eagain);
1137 5 50       29 return $buf if length $buf;
1138             # At this point, we had a 0-length read with no error (or EAGAIN).
1139             # Especially for a SOCK_STREAM connection, this may mean EOF.
1140 0         0 $! = $errnum; # restore possible failure just in case
1141 0 0       0 unless ($self->ckeof) {
1142 0 0       0 return defined($from) ? $buf : undef;
1143             }
1144 0         0 $self->shutdown(SHUT_RD); # make sure I know about this EOF
1145 0         0 $! = 0; # no error for EOF
1146 0         0 undef; # no buffer, either, though
1147             }
1148              
1149             sub get; # (helps with -w)
1150             *get = \&recv; # a name that works for indirect references
1151              
1152             #& getline($self) : like scalar(<$fhandle>)
1153             sub getline : locked method
1154             {
1155 2     2 1 783 my $whoami = $_[0]->_trace(\@_,4);
1156 2 50       12 carp "Excess arguments to ${whoami} ignored"
1157             if @_ > 1;
1158 2         3 my ($self) = @_;
1159 2 50 33     14 croak "Invalid arguments to ${whoami}, called"
1160             if !@_ or !ref($self);
1161 2         3 my ($rval, $buf, $tbuf);
1162 2         2 $buf = $ {*$self}{sockLineBuf};
  2         10  
1163 2         5 undef $ {*$self}{sockLineBuf}; # keep get from returning this again
  2         8  
1164 2 50       11 if (!defined($/)) {
1165 0         0 $rval = <$self>; # return all of the input
1166             # what about non-blocking sockets here?!?
1167             # $self->shutdown(SHUT_RD); # keep track of EOF
1168             # Above removed because ->recv does it on real EOF already.
1169 0 0 0     0 if (defined($buf) and defined($rval)) {
1170 0         0 return $buf . $rval
1171             }
1172 0 0       0 if (defined($buf)) {
1173 0         0 return $buf
1174             }
1175 0         0 return $rval
1176             }
1177 2         4 my $sep = $/; # get the current separator
1178 2 50       8 $sep = "\n\n" if $sep eq ''; # account for paragraph mode
1179 2   66     9 while (!defined($buf) or $buf !~ /\Q$sep/) {
1180 2         15 $rval = $self->get;
1181 2 50       6 last unless defined $rval;
1182 2 50       16 if (defined $buf) {
1183 0         0 $buf .= $rval;
1184             }
1185             else {
1186 2         37 $buf = $rval;
1187             }
1188             }
1189 2 50 33     16 if (defined($buf) and ($tbuf = index($buf, $sep)) >= 0) {
1190 2         7 $rval = substr($buf, 0, $tbuf + length($sep));
1191 2         6 $tbuf = substr($buf, length($rval));
1192             # duplicate annoyance of paragraph mode
1193 2 50       7 $tbuf =~ s/^\n+//s if $/ eq '';
1194 2 50       6 $ {*$self}{sockLineBuf} = $tbuf if length($tbuf);
  0         0  
1195 2         10 return $rval;
1196             }
1197             else {
1198 0         0 return $buf;
1199             }
1200             }
1201              
1202             sub gets; # an alias for FileHandle:: or POSIX:: compat.
1203             *gets = \&getline;
1204              
1205             sub DESTROY
1206             {
1207 4     4   409 $_[0]->_trace(\@_,1);
1208             }
1209              
1210             #& isopen($self [, @ignored]) : boolean
1211             sub isopen
1212             {
1213             #$_[0]->_trace(\@_,4," - ".($ {*{$_[0]}}{'isopen'} ? "yes" : "no"));
1214 64     64 1 118 $ {*{$_[0]}}{'isopen'};
  64         62  
  64         556  
1215             }
1216              
1217             #& isconnected($self [, @ignored]) : boolean
1218             sub isconnected
1219             {
1220             #$_[0]->_trace(\@_,4," - ".($ {*{$_[0]}}{'isconnected'} ? "yes" : "no"));
1221 23     23 1 35 $ {*{$_[0]}}{'isconnected'};
  23         33  
  23         423  
1222             }
1223              
1224             #& isconnecting($self [, @ignored]) : boolean
1225             sub isconnecting
1226             {
1227             #$_[0]->_trace(\@_,4," - ".($ {*{$_[0]}}{'isconnecting'} ? "yes" : "no"));
1228 5     5 1 9 $ {*{$_[0]}}{'isconnecting'};
  5         7  
  5         109  
1229             }
1230              
1231             #& wasconnected($self [, @ignored]) : boolean
1232             sub wasconnected
1233             {
1234             #$_[0]->_trace(\@_,4," - ".($ {*{$_[0]}}{'wasconnected'} ? "yes" : "no"));
1235 3     3 1 7 $ {*{$_[0]}}{'wasconnected'};
  3         5  
  3         102  
1236             }
1237              
1238             #& isbound($self [, @ignored]) : boolean
1239             sub isbound
1240             {
1241             #$_[0]->_trace(\@_,4," - ".($ {*{$_[0]}}{'isbound'} ? "yes" : "no"));
1242 15     15 1 28 $ {*{$_[0]}}{'isbound'};
  15         20  
  15         262  
1243             }
1244              
1245             1;
1246              
1247             # autoloaded methods go after the END clause (& pod) below
1248              
1249             __END__