You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modules-dev@httpd.apache.org by bronto <br...@noip.sk> on 2006/10/24 17:52:35 UTC

Re: dropping a connection abruptly

Hello experts,
I think i can give you some point to go to with this socket thing. We 
are on project, where we have to get the socket descriptor out of the 
apache thus we can use it with external libraries. In one time I've 
found myself with grep and apache sources, google and a lot of coffee ;)
We are on Linux (64 bit architecture).
here's how to get socket from apache in module:

static int my_post_read_request(request_rec *r)
{
    conn_rec *conn = r->connection;
    apr_socket_t *csd = ((core_net_rec 
*)conn->input_filters->ctx)->client_socket;
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "mod_my_download: 
client socket file descriptor: %d",csd->socketdes);
    return OK;
}

static void my_register_hooks(apr_pool_t *p)
{

ap_hook_post_read_request(my_post_read_request, NULL, NULL, 
APR_HOOK_REALLY_FIRST);

}

module AP_MODULE_DECLARE_DATA my_download_module =
{
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    my_register_hooks
};


so in my_post_read_request(..) you will have csd->socketdes at one 
point. This is fully functional socket descriptor. I really believe this 
is not the way apache team would like mod developers to play with 
sockets...I believe they don't want it at all (i guess, that's the point 
of storing apr_socket as (void) pointer in input_filters->ctx :) ). If 
you know any cleaner (better), way how to do this, I would appreciate 
any comments.
I'll be glad, if this helps.

Anyway, why i got interested in your mail Roy. You mention there some 
approach to mark a connection as aborted. If one _marks_ a connection as 
aborted, will:
  - apache close this connection right after return from module ?
      - if yes, is there a way to preserve this socket?
  - apache send anything to the (appropriate) socket (connection)?

In general, I want to read headers and check the URL. If it's in certain 
namespace, I would like to:
  - tell apache to forget about this connection (mark as aborted?)
  - pass socket from this connection to 'worker' (my own thread inside 
apache, which will know what to do)
  - return from module, and rely on apache to let this connection as is 
(no data, no further read() from socket, no other modules touch it etc.)

If I'm confusing about something, reply please and I will 
extend(explain) my thoughts.


Best regards,
Stefan


On Oct 23, 2006, at 2:22 PM, Brian McQueen wrote:
> This is sounding good.  How do I gain the level of control that you
> are describing here?  The request_rec has a conn_rec, but I don't see
> how to get beyond that.  If I've successfully read 4096 bytes, how do
> I then stop any further transactions on the socket?  I don't know how
> to grab the socket in order to close it!

There is a (at least one) way to mark the connection as aborted
after the read.  I'd explain, but have too much on my plate right
now (flight to switzerland in the morning).  Search for "aborted"
in the code and see what others do.

....Roy

Re: dropping a connection abruptly

Posted by Nick Kew <ni...@webthing.com>.
On Tuesday 24 October 2006 17:25, Brian McQueen wrote:

> 1) a input filter that creates an eos bucket and passes it on as the
> brigade 2) mark the connection as aborted
> 3) set keepalive to AP_CONN_CLOSE
> 4) flush the req
> 5) flush the connection
> 6) finalize the protocol
> 7) discard the request body
>
> I bet the order of these isn't quite right, but this batch of things
> shuts it down promptly upon return.

Looks like you've made a good start on it.  I'll be interested to hear
how this works out with real clients.  This set me thinking:

(1) You're really working at the network level.  That sits uneasily
with a request-level filter.
(2) But you need the protocol, because that's what tells you you're
going to reject the request based on length.

So maybe this input filter isn't what you want.

> I thought I'd add something about why this entire procedure is bad.
> In addition to the HTTP compliance issue that I mentioned before,

On which you have reassuring feedback from Roy Fielding, the man
whose name heads the HTTP spec:-)

> fiddling with the socket is bad because module writers should assume
> they are writing a module that can get along with other unspecifed
> modules.  Having a module get to the socket and mess with the
> connection will alter the basic environment that module writers
> assume.  Modules that follow may not be designed to run well with a
> dead socket.  It is usually not part of a module writer's concern.

That's right.

Basically you need to break this off after reading the headers but
before reading the entire body, and bearing in mind you do want to
get a response back to the client.  So what you probably want to do
is move checking of content-length to a header-parser hook (or
even a post-read-request if the maximum size doesn't need to be 
configurable).  That can then return 413 to generate a standard
error document.  OK, now that's the easy bit dealt with.

Now, since you're detecting the condition in an ordinary hook,
you can move your filter - which is doing basically the right thing -
right up the chain to the network level.  It would either be something
close to a clone of the core input filter, but with additional checks
for a flag your hook has set, or sit immediately behind the core filter.
On encountering that flag, it winds up gracefully.  And the key point is: 
you're now in the right place to be playing with the socket.

Details left as an exercise for the reader, 'cos I haven't exactly
worked through it :-)

-- 
Nick Kew

Application Development with Apache - the Apache Modules Book
http://www.apachetutor.org/

Re: dropping a connection abruptly

Posted by Brian McQueen <mc...@gmail.com>.
That's interesting, and ripe for exploitation!  Thanks for adding your
comments.  I'm finding that I can now get the connection to shutdown
promptly by doing several things, probably not all of them are
required or even right, but at this point I am just trying to get the
behaviour I need.  I'll fix the general design after I better
understand the solution.  So far I've taken things from mod_ssl, and
other comments and now I do get the socket to close, quite promptly.
I've done:

1) a input filter that creates an eos bucket and passes it on as the brigade
2) mark the connection as aborted
3) set keepalive to AP_CONN_CLOSE
4) flush the req
5) flush the connection
6) finalize the protocol
7) discard the request body

I bet the order of these isn't quite right, but this batch of things
shuts it down promptly upon return.

I thought I'd add something about why this entire procedure is bad.
In addition to the HTTP compliance issue that I mentioned before,
fiddling with the socket is bad because module writers should assume
they are writing a module that can get along with other unspecifed
modules.  Having a module get to the socket and mess with the
connection will alter the basic environment that module writers
assume.  Modules that follow may not be designed to run well with a
dead socket.  It is usually not part of a module writer's concern.

On 10/24/06, bronto <br...@noip.sk> wrote:
> Hello experts,
> I think i can give you some point to go to with this socket thing. We
> are on project, where we have to get the socket descriptor out of the
> apache thus we can use it with external libraries. In one time I've
> found myself with grep and apache sources, google and a lot of coffee ;)
> We are on Linux (64 bit architecture).
> here's how to get socket from apache in module:
>
> static int my_post_read_request(request_rec *r)
> {
>     conn_rec *conn = r->connection;
>     apr_socket_t *csd = ((core_net_rec
> *)conn->input_filters->ctx)->client_socket;
>     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "mod_my_download:
> client socket file descriptor: %d",csd->socketdes);
>     return OK;
> }
>
> static void my_register_hooks(apr_pool_t *p)
> {
>
> ap_hook_post_read_request(my_post_read_request, NULL, NULL,
> APR_HOOK_REALLY_FIRST);
>
> }
>
> module AP_MODULE_DECLARE_DATA my_download_module =
> {
>     STANDARD20_MODULE_STUFF,
>     NULL,
>     NULL,
>     NULL,
>     NULL,
>     NULL,
>     my_register_hooks
> };
>
>
> so in my_post_read_request(..) you will have csd->socketdes at one
> point. This is fully functional socket descriptor. I really believe this
> is not the way apache team would like mod developers to play with
> sockets...I believe they don't want it at all (i guess, that's the point
> of storing apr_socket as (void) pointer in input_filters->ctx :) ). If
> you know any cleaner (better), way how to do this, I would appreciate
> any comments.
> I'll be glad, if this helps.
>
> Anyway, why i got interested in your mail Roy. You mention there some
> approach to mark a connection as aborted. If one _marks_ a connection as
> aborted, will:
>   - apache close this connection right after return from module ?
>       - if yes, is there a way to preserve this socket?
>   - apache send anything to the (appropriate) socket (connection)?
>
> In general, I want to read headers and check the URL. If it's in certain
> namespace, I would like to:
>   - tell apache to forget about this connection (mark as aborted?)
>   - pass socket from this connection to 'worker' (my own thread inside
> apache, which will know what to do)
>   - return from module, and rely on apache to let this connection as is
> (no data, no further read() from socket, no other modules touch it etc.)
>
> If I'm confusing about something, reply please and I will
> extend(explain) my thoughts.
>
>
> Best regards,
> Stefan
>
>
> On Oct 23, 2006, at 2:22 PM, Brian McQueen wrote:
> > This is sounding good.  How do I gain the level of control that you
> > are describing here?  The request_rec has a conn_rec, but I don't see
> > how to get beyond that.  If I've successfully read 4096 bytes, how do
> > I then stop any further transactions on the socket?  I don't know how
> > to grab the socket in order to close it!
>
> There is a (at least one) way to mark the connection as aborted
> after the read.  I'd explain, but have too much on my plate right
> now (flight to switzerland in the morning).  Search for "aborted"
> in the code and see what others do.
>
> ....Roy
>