Lines 39-45
typedef struct ws_baton_t {
Link Here
|
39 |
|
39 |
|
40 |
static void proxy_wstunnel_callback(void *b); |
40 |
static void proxy_wstunnel_callback(void *b); |
41 |
|
41 |
|
42 |
static int proxy_wstunnel_pump(ws_baton_t *baton, apr_time_t timeout, int try_poll) { |
42 |
static int proxy_wstunnel_pump(ws_baton_t *baton, apr_time_t timeout, |
|
|
43 |
int try_poll, int *replied) |
44 |
{ |
43 |
request_rec *r = baton->r; |
45 |
request_rec *r = baton->r; |
44 |
conn_rec *c = r->connection; |
46 |
conn_rec *c = r->connection; |
45 |
proxy_conn_rec *conn = baton->proxy_connrec; |
47 |
proxy_conn_rec *conn = baton->proxy_connrec; |
Lines 53-59
static void proxy_wstunnel_callback(void *b);
Link Here
|
53 |
apr_status_t rv; |
55 |
apr_status_t rv; |
54 |
apr_bucket_brigade *bb_i = baton->bb_i; |
56 |
apr_bucket_brigade *bb_i = baton->bb_i; |
55 |
apr_bucket_brigade *bb_o = baton->bb_o; |
57 |
apr_bucket_brigade *bb_o = baton->bb_o; |
56 |
int done = 0, replied = 0; |
58 |
int done = 0; |
57 |
|
59 |
|
58 |
do { |
60 |
do { |
59 |
rv = apr_pollset_poll(pollset, timeout, &pollcnt, &signalled); |
61 |
rv = apr_pollset_poll(pollset, timeout, &pollcnt, &signalled); |
Lines 91-97
static void proxy_wstunnel_callback(void *b);
Link Here
|
91 |
done |= ap_proxy_transfer_between_connections(r, backconn, |
93 |
done |= ap_proxy_transfer_between_connections(r, backconn, |
92 |
c, bb_i, bb_o, |
94 |
c, bb_i, bb_o, |
93 |
"backend", |
95 |
"backend", |
94 |
&replied, |
96 |
replied, |
95 |
AP_IOBUFSIZE, |
97 |
AP_IOBUFSIZE, |
96 |
0) |
98 |
0) |
97 |
!= APR_SUCCESS; |
99 |
!= APR_SUCCESS; |
Lines 100-111
static void proxy_wstunnel_callback(void *b);
Link Here
|
100 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02447) |
102 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02447) |
101 |
"error on backend connection"); |
103 |
"error on backend connection"); |
102 |
backconn->aborted = 1; |
104 |
backconn->aborted = 1; |
103 |
done = 1; |
105 |
return HTTP_INTERNAL_SERVER_ERROR; |
104 |
} |
106 |
} |
105 |
else { |
107 |
else { |
106 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02605) |
108 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02605) |
107 |
"unknown event on backconn %d", pollevent); |
109 |
"unknown event on backconn %d", pollevent); |
108 |
done = 1; |
110 |
return HTTP_INTERNAL_SERVER_ERROR; |
109 |
} |
111 |
} |
110 |
} |
112 |
} |
111 |
else if (cur->desc.s == client_socket) { |
113 |
else if (cur->desc.s == client_socket) { |
Lines 124-141
static void proxy_wstunnel_callback(void *b);
Link Here
|
124 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02607) |
126 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02607) |
125 |
"error on client connection"); |
127 |
"error on client connection"); |
126 |
c->aborted = 1; |
128 |
c->aborted = 1; |
127 |
done = 1; |
129 |
return HTTP_INTERNAL_SERVER_ERROR; |
128 |
} |
130 |
} |
129 |
else { |
131 |
else { |
130 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02606) |
132 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02606) |
131 |
"unknown event on client conn %d", pollevent); |
133 |
"unknown event on client conn %d", pollevent); |
132 |
done = 1; |
134 |
return HTTP_INTERNAL_SERVER_ERROR; |
133 |
} |
135 |
} |
134 |
} |
136 |
} |
135 |
else { |
137 |
else { |
136 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02449) |
138 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02449) |
137 |
"unknown socket in pollset"); |
139 |
"unknown socket in pollset"); |
138 |
done = 1; |
140 |
return HTTP_INTERNAL_SERVER_ERROR; |
139 |
} |
141 |
} |
140 |
|
142 |
|
141 |
} |
143 |
} |
Lines 143-155
static void proxy_wstunnel_callback(void *b);
Link Here
|
143 |
|
145 |
|
144 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
146 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, |
145 |
"finished with poll() - cleaning up"); |
147 |
"finished with poll() - cleaning up"); |
146 |
|
148 |
return OK; |
147 |
if (!replied) { |
|
|
148 |
return HTTP_BAD_GATEWAY; |
149 |
} |
150 |
else { |
151 |
return OK; |
152 |
} |
153 |
} |
149 |
} |
154 |
|
150 |
|
155 |
static void proxy_wstunnel_finish(ws_baton_t *baton) { |
151 |
static void proxy_wstunnel_finish(ws_baton_t *baton) { |
Lines 181-192
static void proxy_wstunnel_cancel_callback(void *b
Link Here
|
181 |
* We don't need the invoke_mtx, since we never put multiple callback events |
177 |
* We don't need the invoke_mtx, since we never put multiple callback events |
182 |
* in the queue. |
178 |
* in the queue. |
183 |
*/ |
179 |
*/ |
184 |
static void proxy_wstunnel_callback(void *b) { |
180 |
static void proxy_wstunnel_callback(void *b) |
|
|
181 |
{ |
185 |
int status; |
182 |
int status; |
186 |
ws_baton_t *baton = (ws_baton_t*)b; |
183 |
ws_baton_t *baton = (ws_baton_t*)b; |
187 |
proxyws_dir_conf *dconf = ap_get_module_config(baton->r->per_dir_config, &proxy_wstunnel_module); |
184 |
proxyws_dir_conf *dconf = ap_get_module_config(baton->r->per_dir_config, &proxy_wstunnel_module); |
188 |
apr_pool_clear(baton->subpool); |
185 |
apr_pool_clear(baton->subpool); |
189 |
status = proxy_wstunnel_pump(baton, dconf->async_delay, dconf->mpm_can_poll); |
186 |
status = proxy_wstunnel_pump(baton, dconf->async_delay, |
|
|
187 |
dconf->mpm_can_poll, NULL); |
190 |
if (status == SUSPENDED) { |
188 |
if (status == SUSPENDED) { |
191 |
apr_pollfd_t *pfd; |
189 |
apr_pollfd_t *pfd; |
192 |
|
190 |
|
Lines 315-320
static int proxy_wstunnel_request(apr_pool_t *p, r
Link Here
|
315 |
int status; |
313 |
int status; |
316 |
proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_wstunnel_module); |
314 |
proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_wstunnel_module); |
317 |
const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : "WebSocket"; |
315 |
const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : "WebSocket"; |
|
|
316 |
ap_filter_t *saved_output_filters, *saved_proto_output_filters; |
317 |
int replied = 0; |
318 |
|
318 |
|
319 |
header_brigade = apr_brigade_create(p, backconn->bucket_alloc); |
319 |
header_brigade = apr_brigade_create(p, backconn->bucket_alloc); |
320 |
|
320 |
|
Lines 367-372
static int proxy_wstunnel_request(apr_pool_t *p, r
Link Here
|
367 |
pollfd.desc.s = client_socket; |
367 |
pollfd.desc.s = client_socket; |
368 |
apr_pollset_add(pollset, &pollfd); |
368 |
apr_pollset_add(pollset, &pollfd); |
369 |
|
369 |
|
|
|
370 |
saved_output_filters = r->output_filters; |
371 |
saved_proto_output_filters = r->proto_output_filters; |
370 |
ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout"); |
372 |
ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout"); |
371 |
|
373 |
|
372 |
r->output_filters = c->output_filters; |
374 |
r->output_filters = c->output_filters; |
Lines 389-398
static int proxy_wstunnel_request(apr_pool_t *p, r
Link Here
|
389 |
apr_pool_create(&baton->subpool, r->pool); |
391 |
apr_pool_create(&baton->subpool, r->pool); |
390 |
|
392 |
|
391 |
if (!dconf->mpm_can_poll) { |
393 |
if (!dconf->mpm_can_poll) { |
392 |
status = proxy_wstunnel_pump(baton, dconf->idle_timeout, dconf->mpm_can_poll); |
394 |
status = proxy_wstunnel_pump(baton, dconf->idle_timeout, |
|
|
395 |
dconf->mpm_can_poll, &replied); |
393 |
} |
396 |
} |
394 |
else { |
397 |
else { |
395 |
status = proxy_wstunnel_pump(baton, dconf->async_delay, dconf->mpm_can_poll); |
398 |
status = proxy_wstunnel_pump(baton, dconf->async_delay, |
|
|
399 |
dconf->mpm_can_poll, &replied); |
396 |
apr_pool_clear(baton->subpool); |
400 |
apr_pool_clear(baton->subpool); |
397 |
if (status == SUSPENDED) { |
401 |
if (status == SUSPENDED) { |
398 |
apr_pollfd_t *pfd; |
402 |
apr_pollfd_t *pfd; |
Lines 420-438
static int proxy_wstunnel_request(apr_pool_t *p, r
Link Here
|
420 |
return SUSPENDED; |
424 |
return SUSPENDED; |
421 |
} |
425 |
} |
422 |
else if (APR_STATUS_IS_ENOTIMPL(rv)) { |
426 |
else if (APR_STATUS_IS_ENOTIMPL(rv)) { |
423 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02544) "No async support"); |
427 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
424 |
status = proxy_wstunnel_pump(baton, dconf->idle_timeout, 0); /* force no async */ |
428 |
APLOGNO(02544) "No async support"); |
|
|
429 |
status = proxy_wstunnel_pump(baton, dconf->idle_timeout, |
430 |
0, /* force no async */ |
431 |
&replied); |
425 |
} |
432 |
} |
426 |
else { |
433 |
else { |
427 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
434 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, |
428 |
APLOGNO(02543) "error creating websockets tunnel"); |
435 |
APLOGNO(02543) "error creating websockets tunnel"); |
429 |
return HTTP_INTERNAL_SERVER_ERROR; |
436 |
status = HTTP_INTERNAL_SERVER_ERROR; |
430 |
} |
437 |
} |
431 |
} |
438 |
} |
432 |
} |
439 |
} |
433 |
|
440 |
|
434 |
if (status != OK) { |
441 |
/* Avoid sending error pages down an upgraded connection */ |
435 |
/* Avoid sending error pages down an upgraded connection */ |
442 |
if (!replied) { |
|
|
443 |
r->output_filters = saved_output_filters; |
444 |
r->proto_output_filters = saved_proto_output_filters; |
445 |
if (status == OK) { |
446 |
status = HTTP_BAD_GATEWAY; |
447 |
} |
448 |
} |
449 |
else if (status != OK) { |
436 |
if (status != HTTP_REQUEST_TIME_OUT) { |
450 |
if (status != HTTP_REQUEST_TIME_OUT) { |
437 |
r->status = status; |
451 |
r->status = status; |
438 |
} |
452 |
} |