On Wed, Aug 18, 2004 at 02:09:53PM -0700, Stas Bekman wrote:
> Glenn Strauss wrote:
> >On Wed, Aug 18, 2004 at 12:59:51PM -0700, Ken Simpson wrote:
> >
> >>>the APR::Socket object is an opaque one, so it can't interoperate with
> >>>any other perl modules. Have you looked if there is some C api to get
> >>>the native socket object? There could be one (as they have for file
> >>>objects), I didn't check.
> >>
> >>I looked through apr_network_io.h, which seemed like the logical
> >>place, and couldn't find an API that returns the native socket
> >>object. But I'm pretty unfamiliar with the Apache code base, so
> >>someone else would probably have better luck.
> >
> >
> >This is what we'd need bound to the Perl API:
> >
> >apr_os_sock_t fd;
> >apr_os_sock_get((apr_os_sock_t *) &fd, (apr_socket_t *) client_socket);
> >
> >On Unix-type platforms, apr_os_sock_t is an int -- the file descriptor,
> >which you can use with select() or IO::Select() or anything you
> >like in Perl to poll the descriptor:
>
> and what do you do with socket fd to get it to work with IO::Select?
>
> >$rin = '';
> >vec($rin, $fd) = 1; ## $fd directly instead of fileno(STDIN) or
> >fileno($FH)
> >...
> >$nfound = select($rout=$rin, undef, undef, $timeout);
> >
> >
> >(On other platforms, like Windows, I don't know what apr_os_sock_t is;
> > check the headers files. :)
>
> I'd rather not expose OS specific bits if they won't work with all perl
> modules. APR provides the API that should (hopefully) work on all
> platforms, so why not use that?
>
> >To get the client socket for a connection, you can obtain the
> >(apr_socket_t *) with the incantation:
> >
> >apr_socket_t *client_socket =
> > ap_get_module_config(r->connection->conn_config, &core_module);
> >
> >and then use apr_os_sock_get() to get the fd.
>
> Yup, we already have that one.
>
>
Currently we use the following hacky solution to make the fd work with
IO::Select and Core::select
use constant MAGIC_FILENO => 7;
use ex::override
GLOBAL_select => sub {
if (@_ == 1) {
my $sh = shift;
unless (ref($sh)) {
my $caller = caller();
$sh = \*{$caller .'::'. $sh};
}
return CORE::select();
}
elsif (@_ == 4) {
my $rin = vec($_[0],MAGIC_FILENO,1) if $_[0];
my $win = vec($_[1],MAGIC_FILENO,1) if $_[1];
my $ein = vec($_[2],MAGIC_FILENO,1) if $_[2];
if ($rin or $win or $ein) {
#magic fileno do something special
#should poll the socket for data here,
#but that doesn't work yet, so fake it
return wantarray ? (1,$_[3]) : 1;
}
else {
return
CORE::select($_[0],$_[1],$_[2],$_[3]);
}
}
else {
die "WTF ?";
}
};
In the latest incarnation of TieBucketBrigade we do the following
sub FILENO {
#returns magic fileno which select and fdopen will do something special with
shift;
return MAGIC_FILENO;
}
Provided you don't need fd 7 anywhere else, this should work. Ideally we
should get the real fd and use it instead.
So all we need to make IO::Select, select and everything else work, is the
ability to poll for data on the socket, which we'll just stick in the
overridden select at the appropriate point above.
mock
--
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html