You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Jeff Trawick <tr...@gmail.com> on 2014/04/14 01:55:43 UTC
Re: svn commit: r1587075 - in /httpd/httpd/trunk: CHANGES
docs/manual/mod/mod_proxy_wstunnel.xml modules/proxy/mod_proxy_wstunnel.c
On Sun, Apr 13, 2014 at 2:41 PM, <co...@apache.org> wrote:
> Author: covener
> Date: Sun Apr 13 18:41:05 2014
> New Revision: 1587075
>
> URL: http://svn.apache.org/r1587075
> Log:
> several related mod_proxy_wstunnel changes that are tough to pull apart:
>
> * make async websockets tunnel opt-in
> * add config for how long we block a thread in asynch mode
> * add config for a cap on the synchronous path
> * avoid sending error responses down the upgraded tunnel
>
>
> Modified:
> httpd/httpd/trunk/CHANGES
> httpd/httpd/trunk/docs/manual/mod/mod_proxy_wstunnel.xml
> httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c
>
> Modified: httpd/httpd/trunk/CHANGES
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1587075&r1=1587074&r2=1587075&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/CHANGES [utf-8] (original)
> +++ httpd/httpd/trunk/CHANGES [utf-8] Sun Apr 13 18:41:05 2014
> @@ -1,6 +1,17 @@
> -*- coding:
> utf-8 -*-
> Changes with Apache 2.5.0
>
> + *) mod_proxy_wstunnel: Avoid sending error responses down an upgraded
> + websockets connection as it is being close down. [Eric Covener]
> +
> + *) mod_proxy_wstunnel: Allow the administrator to cap the amount
> + of time a synchronous websockets connection stays idle with
> + ProxyWebsocketIdleTimeout. [Eric Covener]
> +
> + *) mod_proxy_wstunnel: Change to opt-in for asynchronous support, adding
> + directives ProxyWebsocketAsynch and ProxyWebsocketAsynchDelay.
>
Should be "Async" instead of "Asynch" IMO... the latter form is rather
uncommon...
> + [Eric Covener]
> +
> *) mod_proxy_wstunnel: Stop leaking websockets backend connections under
> event MPMi (trunk-only). [Eric Covener]
>
>
> Modified: httpd/httpd/trunk/docs/manual/mod/mod_proxy_wstunnel.xml
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_proxy_wstunnel.xml?rev=1587075&r1=1587074&r2=1587075&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/docs/manual/mod/mod_proxy_wstunnel.xml (original)
> +++ httpd/httpd/trunk/docs/manual/mod/mod_proxy_wstunnel.xml Sun Apr 13
> 18:41:05 2014
> @@ -52,4 +52,50 @@ ProxyPass /wss2/ wss://echo.websocket.or
> </summary>
>
> <seealso><module>mod_proxy</module></seealso>
> +
> +<directivesynopsis>
> +<name>ProxyWebsocketAsynch</name>
> +<description>Instructs this module to try to create an asynchronous
> tunnel</description>
> +<syntax>ProxyWebsocketAsynch ON|OFF</syntax>
> +<contextlist><context>server config</context>
> +<context>virtual host</context>
> +</contextlist>
> +
> +<usage>
> + <p>This directive instructs the server to try to create an
> asynchronous tunnel.
> + If the current MPM does not support the necessary features, a
> synchronous
> + tunnel is used.</p>
> +</usage>
> +</directivesynopsis>
> +
> +<directivesynopsis>
> +<name>ProxyWebsocketIdleTimeout</name>
> +<description>Sets the maximum amount of time to wait for data on the
> websockets tunnel</description>
> +<syntax>ProxyWebsocketIdleTimeout <var>num</var>[ms]</syntax>
> +<default>ProxyWebsocketIdleTimeout 0</default>
> +<contextlist><context>server config</context>
> +<context>virtual host</context>
> +</contextlist>
> +
> +<usage>
> + <p>This directive imposes a maximum amount of time for the tunnel to
> be
> + left open while idle. This directive is ignored if
> <directive>ProxyWebsocketAsynch</directive>
> + is enabled and the running MPM supports the necessary features</p>
> +</usage>
> +</directivesynopsis>
> +
> +<directivesynopsis>
> +<name>ProxyWebsocketAsynchDelay</name>
> +<description>Sets the amount of time the tunnel waits synchronously for
> data</description>
> +<syntax>ProxyWebsocketAsynchDelay <var>num</var>[ms]</syntax>
> +<default>ProxyWebsocketAsynchDelay 0</default>
> +<contextlist><context>server config</context>
> +<context>virtual host</context>
> +</contextlist>
> +
> +<usage>
> + <p>If <directive>ProxyWebsocketAsynch</directive> is enabled, this
> directive
> + controls how long the server synchronously waits for more data.</p>
> +</usage>
> +</directivesynopsis>
> </modulesynopsis>
>
> Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c?rev=1587075&r1=1587074&r2=1587075&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c (original)
> +++ httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c Sun Apr 13
> 18:41:05 2014
> @@ -19,6 +19,12 @@
>
> module AP_MODULE_DECLARE_DATA proxy_wstunnel_module;
>
> +typedef struct {
> + signed char is_async;
> + apr_time_t idle_timeout;
> + apr_time_t async_delay;
> +} proxyws_dir_conf;
> +
> typedef struct ws_baton_t {
> request_rec *r;
> proxy_conn_rec *proxy_connrec;
> @@ -34,7 +40,7 @@ typedef struct ws_baton_t {
> static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i,
> conn_rec *c_o,
> apr_bucket_brigade *bb, char *name);
>
> -static int proxy_wstunnel_pump(ws_baton_t *baton, apr_time_t timeout) {
> +static int proxy_wstunnel_pump(ws_baton_t *baton, apr_time_t timeout, int
> try_async) {
> request_rec *r = baton->r;
> conn_rec *c = r->connection;
> proxy_conn_rec *conn = baton->proxy_connrec;
> @@ -49,14 +55,20 @@ static int proxy_wstunnel_pump(ws_baton_
> apr_bucket_brigade *bb = baton->bb;
>
> while(1) {
> + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "poll timeout is
> %"APR_TIME_T_FMT"ms %s", apr_time_as_msec(timeout), try_async ? "async" :
> "sync");
> if ((rv = apr_pollset_poll(pollset, timeout, &pollcnt,
> &signalled))
> != APR_SUCCESS) {
> if (APR_STATUS_IS_EINTR(rv)) {
> continue;
> }
> else if (APR_STATUS_IS_TIMEUP(rv)) {
> - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(02542) "Attempting to go asynch");
> - return SUSPENDED;
> + if (try_async) {
> + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(02542) "Attempting to go asynch");
> + return SUSPENDED;
> + }
> + else {
> + return HTTP_REQUEST_TIME_OUT;
> + }
> }
> else {
> ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
> APLOGNO(02444) "error apr_poll()");
> @@ -128,10 +140,12 @@ static int proxy_wstunnel_pump(ws_baton_
> static void proxy_wstunnel_callback(void *b) {
> int status;
> ws_baton_t *baton = (ws_baton_t*)b;
> + proxyws_dir_conf *dconf =
> ap_get_module_config(baton->r->per_dir_config, &proxy_wstunnel_module);
> +
> apr_socket_t *sockets[3] = {NULL, NULL, NULL};
> apr_thread_mutex_lock(baton->r->invoke_mtx);
> apr_pool_clear(baton->subpool);
> - status = proxy_wstunnel_pump(baton, apr_time_from_sec(5));
> + status = proxy_wstunnel_pump(baton, dconf->async_delay,
> dconf->is_async);
> sockets[0] = baton->client_soc;
> sockets[1] = baton->server_soc;
> if (status == SUSPENDED) {
> @@ -317,6 +331,7 @@ static int ap_proxy_wstunnel_request(apr
> ws_baton_t *baton = apr_pcalloc(r->pool, sizeof(ws_baton_t));
> apr_socket_t *sockets[3] = {NULL, NULL, NULL};
> int status;
> + proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
> &proxy_wstunnel_module);
>
> header_brigade = apr_brigade_create(p, backconn->bucket_alloc);
>
> @@ -374,7 +389,6 @@ static int ap_proxy_wstunnel_request(apr
> * nothing else is attempted on the connection after returning. */
> c->keepalive = AP_CONN_CLOSE;
>
> -
> baton->r = r;
> baton->pollset = pollset;
> baton->client_soc = client_socket;
> @@ -384,25 +398,37 @@ static int ap_proxy_wstunnel_request(apr
> baton->scheme = scheme;
> apr_pool_create(&baton->subpool, r->pool);
>
> - status = proxy_wstunnel_pump(baton, apr_time_from_sec(5));
> - if (status == SUSPENDED) {
> - sockets[0] = baton->client_soc;
> - sockets[1] = baton->server_soc;
> - status = ap_mpm_register_socket_callback(sockets, baton->subpool,
> 1, proxy_wstunnel_callback, baton);
> - if (status == APR_SUCCESS) {
> - return SUSPENDED;
> - }
> - else if (status == APR_ENOTIMPL) {
> - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02544)
> "No asynch support");
> - status = proxy_wstunnel_pump(baton, -1);
> - }
> - else {
> - ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
> - APLOGNO(02543) "error creating websockets
> tunnel");
> - return HTTP_INTERNAL_SERVER_ERROR;
> + if (!dconf->is_async) {
> + status = proxy_wstunnel_pump(baton, dconf->idle_timeout,
> dconf->is_async);
> + }
> + else {
> + status = proxy_wstunnel_pump(baton, dconf->async_delay,
> dconf->is_async);
> + if (status == SUSPENDED) {
> + sockets[0] = baton->client_soc;
> + sockets[1] = baton->server_soc;
> + status = ap_mpm_register_socket_callback(sockets,
> baton->subpool, 1, proxy_wstunnel_callback, baton);
> + if (status == APR_SUCCESS) {
> + return SUSPENDED;
> + }
> + else if (status == APR_ENOTIMPL) {
> + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> APLOGNO(02544) "No asynch support");
> + status = proxy_wstunnel_pump(baton, dconf->idle_timeout,
> 0); /* force no async */
> + }
> + else {
> + ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
> + APLOGNO(02543) "error creating websockets
> tunnel");
> + return HTTP_INTERNAL_SERVER_ERROR;
> + }
> }
> }
>
> + if (status != OK) {
> + /* Avoid sending error pages down an upgraded connection */
> + if (status != HTTP_REQUEST_TIME_OUT) {
> + r->status = status;
> + }
> + status = OK;
> + }
> return status;
> }
>
> @@ -490,6 +516,45 @@ static int proxy_wstunnel_handler(reques
> return status;
> }
>
> +static void *create_proxyws_dir_config(apr_pool_t *p, char *dummy)
> +{
> + proxyws_dir_conf *new =
> + (proxyws_dir_conf *) apr_pcalloc(p, sizeof(proxyws_dir_conf));
> +
> + new->idle_timeout = -1; /* no timeout */
> +
> + return (void *) new;
> +}
> +
> +static const char * proxyws_set_idle(cmd_parms *cmd, void *conf, const
> char *val)
> +{
> + proxyws_dir_conf *dconf = conf;
> + if (ap_timeout_parameter_parse(val, &(dconf->idle_timeout), "s") !=
> APR_SUCCESS)
> + return "ProxyWebsocketIdleTimeout timeout has wrong format";
> + return NULL;
> +}
> +static const char * proxyws_set_aysnch_delay(cmd_parms *cmd, void *conf,
> const char *val)
> +{
> + proxyws_dir_conf *dconf = conf;
> + if (ap_timeout_parameter_parse(val, &(dconf->async_delay), "s") !=
> APR_SUCCESS)
> + return "ProxyWebsocketAsynchDelay timeout has wrong format";
> + return NULL;
> +}
> +
> +static const command_rec ws_proxy_cmds[] =
> +{
> + AP_INIT_FLAG("ProxyWebsocketAsynch", ap_set_flag_slot_char,
> (void*)APR_OFFSETOF(proxyws_dir_conf, is_async),
> + RSRC_CONF|ACCESS_CONF,
> + "on if idle websockets connections should be monitored
> asynchronously"),
> +
> + AP_INIT_TAKE1("ProxyWebsocketIdleTimeout", proxyws_set_idle, NULL,
> RSRC_CONF|ACCESS_CONF,
> + "timeout for activity in either direction, unlimited by
> default. Not currently supported with ProxyWebsocketAsynch"),
> +
> + AP_INIT_TAKE1("ProxyWebsocketAsynchDelay", proxyws_set_aysnch_delay,
> NULL, RSRC_CONF|ACCESS_CONF,
> + "amount of time to poll before going asynchronous"),
> + {NULL}
> +};
> +
> static void ap_proxy_http_register_hook(apr_pool_t *p)
> {
> proxy_hook_scheme_handler(proxy_wstunnel_handler, NULL, NULL,
> APR_HOOK_FIRST);
> @@ -498,10 +563,10 @@ static void ap_proxy_http_register_hook(
>
> AP_DECLARE_MODULE(proxy_wstunnel) = {
> STANDARD20_MODULE_STUFF,
> - NULL, /* create per-directory config structure
> */
> + create_proxyws_dir_config, /* create per-directory config structure
> */
> NULL, /* merge per-directory config structures
> */
> NULL, /* create per-server config structure */
> NULL, /* merge per-server config structures */
> - NULL, /* command apr_table_t */
> + ws_proxy_cmds, /* command apr_table_t */
> ap_proxy_http_register_hook /* register hooks */
> };
>
>
>
--
Born in Roswell... married an alien...
http://emptyhammock.com/
http://edjective.org/
Re: svn commit: r1587075 - in /httpd/httpd/trunk: CHANGES
docs/manual/mod/mod_proxy_wstunnel.xml modules/proxy/mod_proxy_wstunnel.c
Posted by Eric Covener <co...@gmail.com>.
On Sun, Apr 13, 2014 at 7:55 PM, Jeff Trawick <tr...@gmail.com> wrote:
> Should be "Async" instead of "Asynch" IMO... the latter form is rather
> uncommon...
thanks, r1587126.