How to access client socket from a protocol handler

2010-10-22 Thread Alexander Farber
Hello,

I have a simple Perl module (source code at the bottom),
which sends a string to clients connecting to port 843.

It works ok, but I'd like to rewrite it in C because
it seems to use 20m for this simple task at my
CentOS 5.5/64 Linux with httpd-2.2.3-43 and mod_perl-2.0.4:

  PID USER  PR  NI  VIRT  RES  SHR S %CPU %MEMTIME+  COMMAND
10697 apache15   0  261m  20m 4480 S  0.0  0.5   0:07.19 httpd
10699 apache15   0  261m  20m 4300 S  0.0  0.5   0:09.06 httpd
.

Unfortunately there aren't many example for the protocol handlers
on the web or in Nick's book. I've come up with the following,
but don't know how to get the client socket via conn_rec?

#include httpd.h
#include http_protocol.h
#include http_connection.h
#include http_config.h
#include http_log.h

#define POLICY ?xml version=\1.0\?\n \
   !DOCTYPE cross-domain-policy SYSTEM\n \
   \http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\;\n \
   cross-domain-policy\n \
   allow-access-from domain=\*\ to-ports=\8080\/\n \
   /cross-domain-policy\0

static int socket_policy_handler(conn_rec *conn) {

   /* XXX how access socket here? */

ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, conn-base_server,
served socket policy to %s, conn-remote_ip);

return OK;
}

static void register_hooks(apr_pool_t *pool) {
ap_hook_process_connection(socket_policy_handler, NULL, NULL,
APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA socket_policy_module = {
STANDARD20_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
NULL,
register_hooks
};

Thank you
Alex

PS: Here is my current mod_perl-module

package SocketPolicy;

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

use strict;
use warnings FATAL = 'all';
use APR::Const(-compile = 'SO_NONBLOCK');
use APR::Socket();
use Apache2::ServerRec();
use Apache2::Connection();
use Apache2::Const(-compile = qw(OK DECLINED));

use constant POLICY =
qq{?xml version=1.0?
!DOCTYPE cross-domain-policy SYSTEM
http://www.adobe.com/xml/dtds/cross-domain-policy.dtd;

cross-domain-policy
allow-access-from domain=* to-ports=8080/
/cross-domain-policy
\0};

sub handler {
my $conn   = shift;
my $socket = $conn-client_socket();
my $offset = 0;

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

do {
my $nbytes = $socket-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 = $conn-base_server()-log();
$slog-warn('served socket policy to: ', $conn-remote_ip());
return Apache2::Const::OK;
}

1;


Re: How to access client socket from a protocol handler

2010-10-22 Thread Alexander Farber
Hi Ben,

On Fri, Oct 22, 2010 at 11:54 PM, Ben Noordhuis i...@bnoordhuis.nl wrote:
 On Fri, Oct 22, 2010 at 23:08, Alexander Farber
 alexander.far...@gmail.com wrote:
 but don't know how to get the client socket via conn_rec?

 apr_socket_t *client  = ap_get_module_config(conn-conn_config, core_module);

 But note that in most cases direct socket I/O is a bad idea.


are you sure that this is a correct command?
(I'm not experienced with Apache2)

And what do you mean by core_module
in my case (source code below)?

Should I maybe try
apr_socket_t *socket = conn-cs-desc-s
or something similar instead?

And why is direct socket I/O bad idea,
isn't this how protocol handling modules (like mod_ftp, mod_smtp)
are supposed to work?

Greetings from Germany
Alex


#include httpd.h
#include http_protocol.h
#include http_connection.h
#include http_config.h
#include http_log.h

#define POLICY ?xml version=\1.0\?\n \
  !DOCTYPE cross-domain-policy SYSTEM\n \
  \http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\;\n \
  cross-domain-policy\n \
  allow-access-from domain=\*\ to-ports=\8080\/\n \
  /cross-domain-policy\0

static int socket_policy_handler(conn_rec *conn) {

  /* XXX how access socket here? XXX */

   ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, conn-base_server,
   served socket policy to %s, conn-remote_ip);

   return OK;
}

static void register_hooks(apr_pool_t *pool) {
   ap_hook_process_connection(socket_policy_handler, NULL, NULL,
APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA socket_policy_module = {
   STANDARD20_MODULE_STUFF,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
   register_hooks
};


Re: How to access client socket from a protocol handler

2010-10-22 Thread Ben Noordhuis
On Sat, Oct 23, 2010 at 00:01, Mike Meyer
mwm-keyword-apache.b9a...@mired.org wrote:
 I use that to get the socket so I can poll for it to have data in it,
 and do other things while I'm waiting. Is there a better alternative
 for that, or is this an exception?

You could do it through apr_bucket_read(APR_NONBLOCK_READ) but polling
on the socket is probably simpler, especially if you are polling on
more than one fd.

Just don't read or write data directly, that would bypass the filter
chain (and break logging, for starters).


Re: How to access client socket from a protocol handler

2010-10-22 Thread Ben Noordhuis
On Sat, Oct 23, 2010 at 00:15, Alexander Farber
alexander.far...@gmail.com wrote:
 Should I maybe try
 apr_socket_t *socket = conn-cs-desc-s
 or something similar instead?

Probably not, the conn_config solution is most portable across Apache versions.

 And what do you mean by core_module
 in my case (source code below)?

That's the reference to Apache itself, the core is a module too.
Elegant, isn't it?

 And why is direct socket I/O bad idea,
 isn't this how protocol handling modules (like mod_ftp, mod_smtp)
 are supposed to work?

There is no yes or no to this question, mostly it depends.

You should strive to use what is already in place, if only because it
will make your life easier down the road. Upsides to using the bucket
brigade and the filter chain:

* cross-platform
* published and supported APIs (will work with future releases of Apache)
* fairly straight-forward and transparent SSL/TLS integration

Downsides:

* overhead (slower)
* higher learning curve

So consider the pros and cons and pick the best solution. And don't
hesitate to ask questions if you have them. :)