Path to my module and APR::Socket::send() usage

Path to my module and APR::Socket::send() usage

am 21.10.2010 14:35:00 von Alexander Farber

Hello mod_perl 2 users,

I have 3 questions please:

1) How do you specify the path to your custom module,
so that Apache 2 can load it at the startup?

I'm using mod_perl-2.0.4-6.el5 with CentOS Linux 5.5 and
have the following lines in /etc/httpd/conf.d/perl.conf:

LoadModule perl_module modules/mod_perl.so
.......
Listen 843

PerlModule SocketPolicy
PerlProcessConnectionHandler SocketPolicy


but this works only if I put my SocketPolicy.pm
under /etc/httpd. Otherwise it isn't found in @INC.

2) The "perldoc APR:Socket" suggests an example:

# read from/write to the socket (w/o handling possible failures)
my $wanted = 1024;
while ($sock->recv(my $buffer, $wanted)) {
$sock->send($buffer);
}

and later it also says the mod_perl will handle errors for you.

Shouldn't return values from send() be checked in
a loop for the cases, that it wasn't able to write the
complete buffer in 1 pass? Or does send($buffer)
alsways write the complete $buffer to the blocking socket?

And what does it mean "mod_perl will handle errors for you"?
Does it catch exception coming from send()/recv()
and print it to error_log or is is something else?

3) And the 3rd question is optional (because I'll probably find
this in the docs soon), but maybe someone can tell me, how
to log the IP of the socket peer in my module to access_log?

Thank you and below is my module
Alex

# cat /etc/httpd/SocketPolicy.pm
package SocketPolicy;

# Run: semanage port -a -t http_port_t -p tcp 843
# And add following lines to the httpd.conf
# Listen 843
#
# PerlModule SocketPolicy
# PerlProcessConnectionHandler SocketPolicy
#


use strict;
use warnings FATAL => 'all';

use Apache2::Connection();
use APR::Socket();

use Apache2::Const(-compile => 'OK');
use APR::Const(-compile => 'SO_NONBLOCK');

use constant POLICY =>
qq{
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">




\0};

sub handler {
my $c = shift;
my $sock = $c->client_socket;

# set the socket to the blocking mode
$sock->opt_set(APR::Const::SO_NONBLOCK => 0);

$sock->send(POLICY);

Apache2::Const::OK;
}

1;

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 15:21:37 von Alexander Farber

For 3) I unfortunately get:

[error] Can't locate object method "log" via package
"Apache2::ServerRec" at /etc/httpd/SocketPolicy.pm line 39.\n

when I try:

sub handler {
my $c =3D shift;
my $sock =3D $c->client_socket;

# set the socket to the blocking mode
$sock->opt_set(APR::Const::SO_NONBLOCK =3D> 0);

$sock->send(POLICY);

my $slog =3D $c->base_server()->log();
$slog->info('served socket policy to: ', $c->remote_ip());

Apache2::Const::OK;
}

Regards
Alex


On Thu, Oct 21, 2010 at 2:35 PM, Alexander Farber
wrote:
> 1) How do you specify the path to your custom module,
> =A0 =A0so that Apache 2 can load it at the startup?
>
> =A0 =A0I'm using mod_perl-2.0.4-6.el5 with CentOS Linux 5.5 and
> =A0 =A0have the following lines in /etc/httpd/conf.d/perl.conf:
>
> =A0 =A0LoadModule perl_module modules/mod_perl.so
> =A0 =A0.......
> =A0 =A0Listen 843
> =A0 =A0
> =A0 =A0 =A0 =A0PerlModule =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 SocketPolic=
y
> =A0 =A0 =A0 =A0PerlProcessConnectionHandler SocketPolicy
> =A0 =A0

>
> =A0 =A0but this works only if I put my SocketPolicy.pm
> =A0 =A0under /etc/httpd. Otherwise it isn't found in @INC.
>
> 2) The "perldoc APR:Socket" suggests an example:
>
> =A0 =A0 =A0 =A0 # read from/write to the socket (w/o handling possible fa=
ilures)
> =A0 =A0 =A0 =A0 my $wanted =3D 1024;
> =A0 =A0 =A0 =A0 while ($sock->recv(my $buffer, $wanted)) {
> =A0 =A0 =A0 =A0 =A0 =A0 $sock->send($buffer);
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0and later it also says the mod_perl will handle errors for you.
>
> =A0 =A0Shouldn't return values from send() be checked in
> =A0 =A0a loop for the cases, that it wasn't able to write the
> =A0 =A0complete buffer in 1 pass? Or does send($buffer)
> =A0 =A0alsways write the complete $buffer to the blocking socket?
>
> =A0 =A0And what does it mean "mod_perl will handle errors for you"?
> =A0 =A0Does it catch exception coming from send()/recv()
> =A0 =A0and print it to error_log or is is something else?
>
> 3) And the 3rd question is optional (because I'll probably find
> =A0 =A0this in the docs soon), but maybe someone can tell me, how
> =A0 =A0to log the IP of the socket peer in my module to access_log?
>
> Thank you and below is my module
> Alex
>
> # cat /etc/httpd/SocketPolicy.pm
> package SocketPolicy;
>
> # Run: semanage port -a -t http_port_t -p tcp 843
> # And add following lines to the httpd.conf
> # Listen 843
> #
> # =A0 =A0 =A0 PerlModule =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 SocketPolicy
> # =A0 =A0 =A0 PerlProcessConnectionHandler SocketPolicy
> #

>
> use strict;
> use warnings FATAL =3D> 'all';
>
> use Apache2::Connection();
> use APR::Socket();
>
> use Apache2::Const(-compile =3D> 'OK');
> use APR::Const(-compile =3D> 'SO_NONBLOCK');
>
> use constant POLICY =3D>
> qq{
> > "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
>
>
>
>

> \0};
>
> sub handler {
> =A0 =A0 =A0 =A0my $c =3D shift;
> =A0 =A0 =A0 =A0my $sock =3D $c->client_socket;
>
> =A0 =A0 =A0 =A0# set the socket to the blocking mode
> =A0 =A0 =A0 =A0$sock->opt_set(APR::Const::SO_NONBLOCK =3D> 0);
>
> =A0 =A0 =A0 =A0$sock->send(POLICY);
>
> =A0 =A0 =A0 =A0Apache2::Const::OK;
> }
>
> 1;
>

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 15:32:21 von torsten.foertsch

On Thursday, October 21, 2010 15:21:37 Alexander Farber wrote:
> [error] Can't locate object method "log" via package
> "Apache2::ServerRec" at /etc/httpd/SocketPolicy.pm line 39.\n

you probably miss a "use Apache2::ServerRec ()" and perhaps a
"use Apache2::Log ()" in your code.

=46urther to your 1st question, have a look at PerlSwitches in the docs,
e.g.:

PerlSwitches -I /path/to/my/INC

Torsten Förtsch

=2D-=20
Need professional modperl support? Hire me! (http://foertsch.name)

Like fantasy? http://kabatinte.net

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 16:49:21 von Ryan Gies

On 10/21/2010 08:35 AM, Alexander Farber wrote:
> Hello mod_perl 2 users,
>
> I have 3 questions please:
>
> 1) How do you specify the path to your custom module,
> so that Apache 2 can load it at the startup?
>
To adjust @INC at start-up:


PerlSwitches -I /my/perl/lib


Or, you can run a perl script at startup (which contains the "use lib
'/my/perl/lib';"):


PerlRequire /my/startup.pl


See also:
http://perl.apache.org/docs/2.0/user/config/config.html#Adju sting_C__INC_

>
> 2) The "perldoc APR:Socket" suggests an example:
>
> # read from/write to the socket (w/o handling possible failures)
> my $wanted = 1024;
> while ($sock->recv(my $buffer, $wanted)) {
> $sock->send($buffer);
> }
>
> and later it also says the mod_perl will handle errors for you.
>
> Shouldn't return values from send() be checked in
> a loop for the cases, that it wasn't able to write the
> complete buffer in 1 pass? Or does send($buffer)
> alsways write the complete $buffer to the blocking socket?
>
No idea...
> And what does it mean "mod_perl will handle errors for you"?
> Does it catch exception coming from send()/recv()
> and print it to error_log or is is something else?
>
Something else: if your module dies, mod_perl will send an error
document and set the status code for the response.
> 3) And the 3rd question is optional (because I'll probably find
> this in the docs soon), but maybe someone can tell me, how
> to log the IP of the socket peer in my module to access_log?
>
> Thank you and below is my module
> Alex
>
> # cat /etc/httpd/SocketPolicy.pm
> package SocketPolicy;
>
> # Run: semanage port -a -t http_port_t -p tcp 843
> # And add following lines to the httpd.conf
> # Listen 843
> #
> # PerlModule SocketPolicy
> # PerlProcessConnectionHandler SocketPolicy
> #

>
> use strict;
> use warnings FATAL => 'all';
>
> use Apache2::Connection();
> use APR::Socket();
>
> use Apache2::Const(-compile => 'OK');
> use APR::Const(-compile => 'SO_NONBLOCK');
>
> use constant POLICY =>
> qq{
> > "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
>
>
>
>

> \0};
>
> sub handler {
> my $c = shift;
> my $sock = $c->client_socket;
>
> # set the socket to the blocking mode
> $sock->opt_set(APR::Const::SO_NONBLOCK => 0);
>
> $sock->send(POLICY);
>
> Apache2::Const::OK;
> }
>
> 1;
>

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 17:20:52 von Alexander Farber

Thanks Ryan and Torsten -

2010/10/21 Torsten Förtsch :
> On Thursday, October 21, 2010 15:21:37 Alexander Farber wrote:
>> =A0[error] Can't locate object method "log" via package
>> "Apache2::ServerRec" at /etc/httpd/SocketPolicy.pm line 39.\n
>
> you probably miss a "use Apache2::ServerRec ()" and perhaps a
> "use Apache2::Log ()" in your code.

3) that has helped. I've ended up with

my $slog =3D $c->base_server()->log();
$slog->warn('served socket policy to: ', $c->remote_ip(), ',
bytes: ', $nbytes);

- I had to take warn() because don't want to increase LogLevel.
But actually I would prefer printing to access_log and not error_log.
Is there a way for that?

2) I've looked at
http://svn.apache.org/viewvc/apr/apr/trunk/network_io/unix/s endrecv.c?view=
=3Dmarkup
If APR::Socket::send() is autogenerated from apr_socket_send()
then the loop is already there and I don't need it in my Perl code.

Regards
Alex

PS: My current code:

package SocketPolicy;

# Run: semanage port -a -t http_port_t -p tcp 843
# And add following lines to the httpd.conf
# Listen 843
#
# PerlModule SocketPolicy
# PerlProcessConnectionHandler SocketPolicy
#


use strict;
use warnings FATAL =3D> 'all';

use Apache2::Connection();
use APR::Socket();
use Apache2::ServerRec();

use Apache2::Const(-compile =3D> 'OK');
use APR::Const(-compile =3D> 'SO_NONBLOCK');

use constant POLICY =3D>
qq{
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">




\0};

sub handler {
my $c =3D shift;
my $sock =3D $c->client_socket;

# set the socket to the blocking mode
$sock->opt_set(APR::Const::SO_NONBLOCK =3D> 0);

my $nbytes =3D $sock->send(POLICY);

my $slog =3D $c->base_server()->log();
$slog->warn('served socket policy to: ', $c->remote_ip(), ',
bytes: ', $nbytes);

Apache2::Const::OK;
}

1;

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 17:39:45 von Alexander Farber

Or maybe I've looked wrong and you do need to loop in Perl?

On Thu, Oct 21, 2010 at 5:20 PM, Alexander Farber
wrote:
> 2) I've looked at
> http://svn.apache.org/viewvc/apr/apr/trunk/network_io/unix/s endrecv.c?vie=
w=3Dmarkup
> =A0If APR::Socket::send() is autogenerated from apr_socket_send()
> =A0then the loop is already there and I don't need it in my Perl code.

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 18:38:06 von Alexander Farber

Even though my logs show that 1 send-call usually suffices
(I have a site with 1 visitor/3 min), I've updated my script.

Not sure if returning DECLINED is a good idea.

And if you know a way to log into access_log
instead of error_log, please tell me.

Thank you
Alex


package SocketPolicy;

use strict;
use warnings FATAL => 'all';

use Apache2::Connection();
use APR::Socket();
use Apache2::ServerRec();

use Apache2::Const(-compile => 'OK');
use APR::Const(-compile => 'SO_NONBLOCK');

use constant POLICY =>
qq{
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">




\0};

sub handler {
my $c = shift;
my $sock = $c->client_socket;
my $offset = 0;

# set the socket to the blocking mode
$sock->opt_set(APR::Const::SO_NONBLOCK => 0);

do {
my $nbytes = $sock->send(substr(POLICY, $offset),
length(POLICY) - $offset);
# client connection closed or interrupted
return Apache2::Const::DECLINED unless $nbytes;
$offset += $nbytes;
} while ($offset < length(POLICY));

my $slog = $c->base_server()->log();
$slog->warn('served socket policy to: ', $c->remote_ip());

return Apache2::Const::OK;
}

1;

Re: Path to my module and APR::Socket::send() usage

am 21.10.2010 19:46:57 von aw

Alexander Farber wrote:
> Even though my logs show that 1 send-call usually suffices
> (I have a site with 1 visitor/3 min), I've updated my script.
>
> Not sure if returning DECLINED is a good idea.
>
> And if you know a way to log into access_log
> instead of error_log, please tell me.

No. I have been looking into that too, without success so far.
About the "warn" : you can use "notice" instead, which will log no matter what the
LogLevel is.

Also about logging : you can use your own PerlLogHandler, to log wherever you want.
return DECLINED from it to have Apache log normally.

An example I just created :

PerlSetVar StatsLogPath "/var/log/apache2/stats.log"
PerlLogHandler my::package->logger


package my::package;
....
sub logger {
my ($self, $r) = @_;
my $debug = $r->dir_config("Debug") || 0;
my $logger = $r->log;
my $pnotes = $r->pnotes;
my $stats = $pnotes->{'stats'}; # set previously by another handler
unless (defined($stats) && ($stats ne '')) {
return DECLINED;
}

my $log_path = $r->dir_config('StatsLogPath');
unless (defined($log_path) && ($log_path ne '')) {
$logger->error("config error : StatsLogPath is not defined !");
return SERVER_ERROR;
}
my $fh;
unless (open($fh,'>>:utf8',$log_path)) {
$logger->error("cannot open [$log_path] : $!");
return SERVER_ERROR;
}
flock $fh, LOCK_EX;
print $fh "[GETOBJ] $stats \n";
close $fh;

return OK;

}