How to access client socket from a protocol handler
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
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
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
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. :)