1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

mod_http2: more const goodiness and checks on h2 request creation, less NULL checking while processing

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1759547 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stefan Eissing
2016-09-07 06:44:16 +00:00
parent 8b562b9331
commit 08df710604
13 changed files with 188 additions and 175 deletions

View File

@@ -370,7 +370,6 @@ $(OBJDIR)/mod_http2.imp : NWGNUmod_http2
@echo $(DL) h2_headers_add_h1,$(DL) >> $@ @echo $(DL) h2_headers_add_h1,$(DL) >> $@
@echo $(DL) h2_req_create,$(DL) >> $@ @echo $(DL) h2_req_create,$(DL) >> $@
@echo $(DL) h2_req_createn,$(DL) >> $@ @echo $(DL) h2_req_createn,$(DL) >> $@
@echo $(DL) h2_req_make,$(DL) >> $@
@echo $(DL) h2_util_camel_case_header,$(DL) >> $@ @echo $(DL) h2_util_camel_case_header,$(DL) >> $@
@echo $(DL) h2_util_frame_print,$(DL) >> $@ @echo $(DL) h2_util_frame_print,$(DL) >> $@
@echo $(DL) h2_util_ngheader_make_req,$(DL) >> $@ @echo $(DL) h2_util_ngheader_make_req,$(DL) >> $@

View File

@@ -130,7 +130,6 @@ struct h2_request {
apr_off_t content_length; apr_off_t content_length;
unsigned int chunked : 1; /* iff requst body needs to be forwarded as chunked */ unsigned int chunked : 1; /* iff requst body needs to be forwarded as chunked */
unsigned int eoh : 1; /* iff end-of-headers has been seen and request is complete */
unsigned int body : 1; /* iff this request has a body */ unsigned int body : 1; /* iff this request has a body */
unsigned int serialize : 1; /* iff this request is written in HTTP/1.1 serialization */ unsigned int serialize : 1; /* iff this request is written in HTTP/1.1 serialization */
unsigned int push_policy; /* which push policy to use for this request */ unsigned int push_policy; /* which push policy to use for this request */

View File

@@ -512,7 +512,7 @@ static int task_print(void *ctx, void *val)
h2_mplx *m = ctx; h2_mplx *m = ctx;
h2_task *task = val; h2_task *task = val;
if (task && task->request) { if (task) {
h2_stream *stream = h2_ihash_get(m->streams, task->stream_id); h2_stream *stream = h2_ihash_get(m->streams, task->stream_id);
ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, /* NO APLOGNO */ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, /* NO APLOGNO */

View File

@@ -346,7 +346,7 @@ static int add_push(link_ctx *ctx)
} }
headers = apr_table_make(ctx->pool, 5); headers = apr_table_make(ctx->pool, 5);
apr_table_do(set_push_header, headers, ctx->req->headers, NULL); apr_table_do(set_push_header, headers, ctx->req->headers, NULL);
req = h2_req_createn(0, ctx->pool, method, ctx->req->scheme, req = h2_req_create(0, ctx->pool, method, ctx->req->scheme,
ctx->req->authority, path, headers, ctx->req->authority, path, headers,
ctx->req->serialize); ctx->req->serialize);
/* atm, we do not push on pushes */ /* atm, we do not push on pushes */

View File

@@ -30,6 +30,7 @@
#include <scoreboard.h> #include <scoreboard.h>
#include "h2_private.h" #include "h2_private.h"
#include "h2_config.h"
#include "h2_push.h" #include "h2_push.h"
#include "h2_request.h" #include "h2_request.h"
#include "h2_util.h" #include "h2_util.h"
@@ -42,15 +43,39 @@ static apr_status_t inspect_clen(h2_request *req, const char *s)
return (s == end)? APR_EINVAL : APR_SUCCESS; return (s == end)? APR_EINVAL : APR_SUCCESS;
} }
apr_status_t h2_request_rwrite(h2_request *req, apr_pool_t *pool, typedef struct {
apr_table_t *headers;
apr_pool_t *pool;
} h1_ctx;
static int set_h1_header(void *ctx, const char *key, const char *value)
{
h1_ctx *x = ctx;
size_t klen = strlen(key);
if (!h2_req_ignore_header(key, klen)) {
h2_headers_add_h1(x->headers, x->pool, key, klen, value, strlen(value));
}
return 1;
}
apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
int stream_id, int initiated_on,
request_rec *r) request_rec *r)
{ {
apr_status_t status; h2_request *req;
const char *scheme, *authority; const char *scheme, *authority, *path;
h1_ctx x;
*preq = NULL;
scheme = apr_pstrdup(pool, r->parsed_uri.scheme? r->parsed_uri.scheme scheme = apr_pstrdup(pool, r->parsed_uri.scheme? r->parsed_uri.scheme
: ap_http_scheme(r)); : ap_http_scheme(r));
authority = (r->hostname ? apr_pstrdup(pool, r->hostname) : ""); authority = apr_pstrdup(pool, r->hostname);
path = apr_uri_unparse(pool, &r->parsed_uri, APR_URI_UNP_OMITSITEPART);
if (!r->method || !scheme || !r->hostname || !path) {
return APR_EINVAL;
}
if (!ap_strchr_c(authority, ':') && r->server && r->server->port) { if (!ap_strchr_c(authority, ':') && r->server && r->server->port) {
apr_port_t defport = apr_uri_port_of_scheme(scheme); apr_port_t defport = apr_uri_port_of_scheme(scheme);
if (defport != r->server->port) { if (defport != r->server->port) {
@@ -60,11 +85,25 @@ apr_status_t h2_request_rwrite(h2_request *req, apr_pool_t *pool,
} }
} }
status = h2_req_make(req, pool, apr_pstrdup(pool, r->method), scheme, req = apr_pcalloc(pool, sizeof(*req));
authority, apr_uri_unparse(pool, &r->parsed_uri, req->id = stream_id;
APR_URI_UNP_OMITSITEPART), req->initiated_on = initiated_on;
r->headers_in); req->method = apr_pstrdup(pool, r->method);
return status; req->scheme = scheme;
req->authority = authority;
req->path = path;
req->headers = apr_table_make(pool, 10);
if (r->server) {
req->serialize = h2_config_geti(h2_config_sget(r->server),
H2_CONF_SER_HEADERS);
}
x.pool = pool;
x.headers = req->headers;
apr_table_do(set_h1_header, &x, r->headers_in, NULL);
*preq = req;
return APR_SUCCESS;
} }
apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool, apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool,
@@ -126,11 +165,6 @@ apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool,
{ {
const char *s; const char *s;
if (req->eoh) {
/* already done */
return APR_SUCCESS;
}
/* rfc7540, ch. 8.1.2.3: /* rfc7540, ch. 8.1.2.3:
* - if we have :authority, it overrides any Host header * - if we have :authority, it overrides any Host header
* - :authority MUST be ommited when converting h1->h2, so we * - :authority MUST be ommited when converting h1->h2, so we
@@ -155,11 +189,13 @@ apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool,
req->id, s); req->id, s);
return APR_EINVAL; return APR_EINVAL;
} }
req->body = 1;
} }
else { else {
/* no content-length given */ /* no content-length given */
req->content_length = -1; req->content_length = -1;
if (!eos) { req->body = !eos;
if (req->body) {
/* We have not seen a content-length and have no eos, /* We have not seen a content-length and have no eos,
* simulate a chunked encoding for our HTTP/1.1 infrastructure, * simulate a chunked encoding for our HTTP/1.1 infrastructure,
* in case we have "H2SerializeHeaders on" here * in case we have "H2SerializeHeaders on" here
@@ -175,7 +211,6 @@ apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool,
} }
} }
req->eoh = 1;
h2_push_policy_determine(req, pool, push); h2_push_policy_determine(req, pool, push);
/* In the presence of trailers, force behaviour of chunked encoding */ /* In the presence of trailers, force behaviour of chunked encoding */

View File

@@ -18,7 +18,8 @@
#include "h2.h" #include "h2.h"
apr_status_t h2_request_rwrite(h2_request *req, apr_pool_t *pool, apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
int stream_id, int initiated_on,
request_rec *r); request_rec *r);
apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool, apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool,

View File

@@ -174,7 +174,7 @@ h2_response *h2_response_die(int stream_id, apr_status_t type,
int status = (type >= 200 && type < 600)? type : 500; int status = (type >= 200 && type < 600)? type : 500;
date = apr_palloc(pool, APR_RFC822_DATE_LEN); date = apr_palloc(pool, APR_RFC822_DATE_LEN);
ap_recent_rfc822_date(date, req->request_time); ap_recent_rfc822_date(date, req? req->request_time : apr_time_now());
apr_table_setn(headers, "Date", date); apr_table_setn(headers, "Date", date);
apr_table_setn(headers, "Server", ap_get_server_banner()); apr_table_setn(headers, "Server", ap_get_server_banner());

View File

@@ -143,10 +143,14 @@ h2_stream *h2_session_open_stream(h2_session *session, int stream_id,
apr_pool_tag(stream_pool, "h2_stream"); apr_pool_tag(stream_pool, "h2_stream");
stream = h2_stream_open(stream_id, stream_pool, session, stream = h2_stream_open(stream_id, stream_pool, session,
initiated_on, req); initiated_on);
nghttp2_session_set_stream_user_data(session->ngh2, stream_id, stream); nghttp2_session_set_stream_user_data(session->ngh2, stream_id, stream);
h2_ihash_add(session->streams, stream); h2_ihash_add(session->streams, stream);
if (req) {
h2_stream_set_request(stream, req);
}
if (H2_STREAM_CLIENT_INITIATED(stream_id)) { if (H2_STREAM_CLIENT_INITIATED(stream_id)) {
if (stream_id > session->remote.emitted_max) { if (stream_id > session->remote.emitted_max) {
++session->remote.emitted_count; ++session->remote.emitted_count;
@@ -500,7 +504,7 @@ static int on_frame_recv_cb(nghttp2_session *ng2s,
session->id, (int)frame->hd.stream_id, session->id, (int)frame->hd.stream_id,
(int)frame->rst_stream.error_code); (int)frame->rst_stream.error_code);
stream = get_stream(session, frame->hd.stream_id); stream = get_stream(session, frame->hd.stream_id);
if (stream && stream->request && stream->request->initiated_on) { if (stream && stream->initiated_on) {
++session->pushes_reset; ++session->pushes_reset;
} }
else { else {
@@ -1078,7 +1082,7 @@ static apr_status_t h2_session_start(h2_session *session, int *rv)
return status; return status;
} }
status = h2_stream_set_request(stream, session->r); status = h2_stream_set_request_rec(stream, session->r);
if (status != APR_SUCCESS) { if (status != APR_SUCCESS) {
return status; return status;
} }
@@ -1508,8 +1512,7 @@ static apr_status_t on_stream_response(void *ctx, int stream_id)
* as the client, having this resource in its cache, might * as the client, having this resource in its cache, might
* also have the pushed ones as well. * also have the pushed ones as well.
*/ */
if (stream->request if (!stream->initiated_on
&& !stream->request->initiated_on
&& h2_response_is_final(response) && h2_response_is_final(response)
&& H2_HTTP_2XX(response->http_status) && H2_HTTP_2XX(response->http_status)
&& h2_session_push_enabled(session)) { && h2_session_push_enabled(session)) {
@@ -1529,7 +1532,7 @@ static apr_status_t on_stream_response(void *ctx, int stream_id)
stream->submitted = h2_response_is_final(response); stream->submitted = h2_response_is_final(response);
session->have_written = 1; session->have_written = 1;
if (stream->request && stream->request->initiated_on) { if (stream->initiated_on) {
++session->pushes_submitted; ++session->pushes_submitted;
} }
else { else {

View File

@@ -175,30 +175,18 @@ static apr_status_t stream_pool_cleanup(void *ctx)
} }
h2_stream *h2_stream_open(int id, apr_pool_t *pool, h2_session *session, h2_stream *h2_stream_open(int id, apr_pool_t *pool, h2_session *session,
int initiated_on, const h2_request *creq) int initiated_on)
{ {
h2_request *req;
h2_stream *stream = apr_pcalloc(pool, sizeof(h2_stream)); h2_stream *stream = apr_pcalloc(pool, sizeof(h2_stream));
stream->id = id; stream->id = id;
stream->initiated_on = initiated_on;
stream->created = apr_time_now(); stream->created = apr_time_now();
stream->state = H2_STREAM_ST_IDLE; stream->state = H2_STREAM_ST_IDLE;
stream->pool = pool; stream->pool = pool;
stream->session = session; stream->session = session;
set_state(stream, H2_STREAM_ST_OPEN); set_state(stream, H2_STREAM_ST_OPEN);
if (creq) {
/* take it into out pool and assure correct id's */
req = h2_request_clone(pool, creq);
req->id = id;
req->initiated_on = initiated_on;
}
else {
req = h2_req_create(id, pool,
h2_config_geti(session->config, H2_CONF_SER_HEADERS));
}
stream->request = req;
apr_pool_cleanup_register(pool, stream, stream_pool_cleanup, apr_pool_cleanup_register(pool, stream, stream_pool_cleanup,
apr_pool_cleanup_null); apr_pool_cleanup_null);
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03082) ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(03082)
@@ -276,31 +264,40 @@ struct h2_response *h2_stream_get_unsent_response(h2_stream *stream)
return unsent; return unsent;
} }
apr_status_t h2_stream_set_request(h2_stream *stream, request_rec *r) apr_status_t h2_stream_set_request_rec(h2_stream *stream, request_rec *r)
{ {
h2_request *req;
apr_status_t status; apr_status_t status;
AP_DEBUG_ASSERT(stream);
ap_assert(stream->request == NULL);
ap_assert(stream->rtmp == NULL);
if (stream->rst_error) { if (stream->rst_error) {
return APR_ECONNRESET; return APR_ECONNRESET;
} }
set_state(stream, H2_STREAM_ST_OPEN); status = h2_request_rcreate(&req, stream->pool, stream->id,
status = h2_request_rwrite(stream->request, stream->pool, r); stream->initiated_on, r);
stream->request->serialize = h2_config_geti(h2_config_sget(r->server),
H2_CONF_SER_HEADERS);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, APLOGNO(03058) ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, APLOGNO(03058)
"h2_request(%d): rwrite %s host=%s://%s%s", "h2_request(%d): set_request_rec %s host=%s://%s%s",
stream->request->id, stream->request->method, stream->id, req->method, req->scheme, req->authority,
stream->request->scheme, stream->request->authority, req->path);
stream->request->path); stream->rtmp = req;
return status; return status;
} }
apr_status_t h2_stream_set_request(h2_stream *stream, const h2_request *r)
{
ap_assert(stream->request == NULL);
ap_assert(stream->rtmp == NULL);
stream->rtmp = h2_request_clone(stream->pool, r);
return APR_SUCCESS;
}
apr_status_t h2_stream_add_header(h2_stream *stream, apr_status_t h2_stream_add_header(h2_stream *stream,
const char *name, size_t nlen, const char *name, size_t nlen,
const char *value, size_t vlen) const char *value, size_t vlen)
{ {
AP_DEBUG_ASSERT(stream); AP_DEBUG_ASSERT(stream);
if (!stream->response) { if (!stream->response) {
if (name[0] == ':') { if (name[0] == ':') {
if ((vlen) > stream->session->s->limit_req_line) { if ((vlen) > stream->session->s->limit_req_line) {
@@ -336,14 +333,20 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
} }
if (h2_stream_is_scheduled(stream)) { if (h2_stream_is_scheduled(stream)) {
return h2_request_add_trailer(stream->request, stream->pool, /* FIXME: this is not clean. we modify a struct that is being processed
* by another thread potentially. */
return h2_request_add_trailer((h2_request*)stream->request, stream->pool,
name, nlen, value, vlen); name, nlen, value, vlen);
} }
else { else {
if (!input_open(stream)) { if (!stream->rtmp) {
stream->rtmp = h2_req_create(stream->id, stream->pool,
NULL, NULL, NULL, NULL, NULL, 0);
}
if (stream->state != H2_STREAM_ST_OPEN) {
return APR_ECONNRESET; return APR_ECONNRESET;
} }
return h2_request_add_header(stream->request, stream->pool, return h2_request_add_header(stream->rtmp, stream->pool,
name, nlen, value, vlen); name, nlen, value, vlen);
} }
} }
@@ -351,17 +354,12 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
apr_status_t h2_stream_schedule(h2_stream *stream, int eos, int push_enabled, apr_status_t h2_stream_schedule(h2_stream *stream, int eos, int push_enabled,
h2_stream_pri_cmp *cmp, void *ctx) h2_stream_pri_cmp *cmp, void *ctx)
{ {
apr_status_t status; apr_status_t status = APR_EINVAL;
AP_DEBUG_ASSERT(stream); AP_DEBUG_ASSERT(stream);
AP_DEBUG_ASSERT(stream->session); AP_DEBUG_ASSERT(stream->session);
AP_DEBUG_ASSERT(stream->session->mplx); AP_DEBUG_ASSERT(stream->session->mplx);
if (!output_open(stream)) { if (!stream->scheduled) {
return APR_ECONNRESET;
}
if (stream->scheduled) {
return APR_EINVAL;
}
if (eos) { if (eos) {
close_input(stream); close_input(stream);
} }
@@ -370,33 +368,45 @@ apr_status_t h2_stream_schedule(h2_stream *stream, int eos, int push_enabled,
/* already have a resonse, probably a HTTP error code */ /* already have a resonse, probably a HTTP error code */
return h2_mplx_process(stream->session->mplx, stream, cmp, ctx); return h2_mplx_process(stream->session->mplx, stream, cmp, ctx);
} }
else if (!stream->request && stream->rtmp) {
/* Seeing the end-of-headers, we have everything we need to /* This is the common case: a h2_request was being assembled, now
* start processing it. * it gets finalized and checked for completness */
*/ status = h2_request_end_headers(stream->rtmp, stream->pool,
status = h2_request_end_headers(stream->request, stream->pool,
eos, push_enabled); eos, push_enabled);
if (status == APR_SUCCESS) { if (status == APR_SUCCESS) {
stream->request->body = !eos; stream->rtmp->id = stream->id;
stream->rtmp->initiated_on = stream->initiated_on;
stream->rtmp->serialize = h2_config_geti(stream->session->config,
H2_CONF_SER_HEADERS);
stream->request = stream->rtmp;
stream->rtmp = NULL;
stream->scheduled = 1; stream->scheduled = 1;
stream->input_remaining = stream->request->content_length; stream->input_remaining = stream->request->content_length;
status = h2_mplx_process(stream->session->mplx, stream, cmp, ctx); status = h2_mplx_process(stream->session->mplx, stream, cmp, ctx);
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c, ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
"h2_stream(%ld-%d): scheduled %s %s://%s%s", "h2_stream(%ld-%d): scheduled %s %s://%s%s "
"clen=%ld, body=%d, chunked=%d",
stream->session->id, stream->id, stream->session->id, stream->id,
stream->request->method, stream->request->scheme, stream->request->method, stream->request->scheme,
stream->request->authority, stream->request->path); stream->request->authority, stream->request->path,
(long)stream->request->content_length,
stream->request->body, stream->request->chunked);
return status;
}
} }
else { else {
status = APR_ECONNRESET;
}
}
h2_stream_rst(stream, H2_ERR_INTERNAL_ERROR); h2_stream_rst(stream, H2_ERR_INTERNAL_ERROR);
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, stream->session->c, ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, stream->session->c,
"h2_stream(%ld-%d): RST=2 (internal err) %s %s://%s%s", "h2_stream(%ld-%d): RST=2 (internal err) %s %s://%s%s",
stream->session->id, stream->id, stream->session->id, stream->id,
stream->request->method, stream->request->scheme, stream->request->method, stream->request->scheme,
stream->request->authority, stream->request->path); stream->request->authority, stream->request->path);
}
return status; return status;
} }
@@ -435,11 +445,11 @@ apr_status_t h2_stream_write_data(h2_stream *stream,
if (!stream->input) { if (!stream->input) {
return APR_EOF; return APR_EOF;
} }
if (input_closed(stream) || !stream->request->eoh) { if (input_closed(stream) || !stream->request) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
"h2_stream(%ld-%d): writing denied, closed=%d, eoh=%d", "h2_stream(%ld-%d): writing denied, closed=%d, eoh=%d",
stream->session->id, stream->id, input_closed(stream), stream->session->id, stream->id, input_closed(stream),
stream->request->eoh); stream->request != NULL);
return APR_EINVAL; return APR_EINVAL;
} }
@@ -583,8 +593,12 @@ apr_status_t h2_stream_set_error(h2_stream *stream, int http_status)
if (stream->submitted) { if (stream->submitted) {
return APR_EINVAL; return APR_EINVAL;
} }
response = h2_response_die(stream->id, http_status, stream->request, if (stream->rtmp) {
stream->pool); stream->request = stream->rtmp;
stream->rtmp = NULL;
}
response = h2_response_die(stream->id, http_status,
stream->request, stream->pool);
return h2_stream_add_response(stream, response, NULL); return h2_stream_add_response(stream, response, NULL);
} }
@@ -714,7 +728,7 @@ apr_table_t *h2_stream_get_trailers(h2_stream *stream)
const h2_priority *h2_stream_get_priority(h2_stream *stream) const h2_priority *h2_stream_get_priority(h2_stream *stream)
{ {
if (stream->response && stream->request && stream->request->initiated_on) { if (stream->response && stream->initiated_on) {
const char *ctype = apr_table_get(stream->response->headers, "content-type"); const char *ctype = apr_table_get(stream->response->headers, "content-type");
if (ctype) { if (ctype) {
/* FIXME: Not good enough, config needs to come from request->server */ /* FIXME: Not good enough, config needs to come from request->server */

View File

@@ -43,12 +43,14 @@ typedef struct h2_stream h2_stream;
struct h2_stream { struct h2_stream {
int id; /* http2 stream id */ int id; /* http2 stream id */
int initiated_on; /* initiating stream id (PUSH) or 0 */
apr_time_t created; /* when stream was created */ apr_time_t created; /* when stream was created */
h2_stream_state_t state; /* http/2 state of this stream */ h2_stream_state_t state; /* http/2 state of this stream */
struct h2_session *session; /* the session this stream belongs to */ struct h2_session *session; /* the session this stream belongs to */
apr_pool_t *pool; /* the memory pool for this stream */ apr_pool_t *pool; /* the memory pool for this stream */
struct h2_request *request; /* the request made in this stream */ const struct h2_request *request; /* the request made in this stream */
struct h2_request *rtmp; /* request being assembled */
struct h2_bucket_beam *input; struct h2_bucket_beam *input;
int request_headers_added; /* number of request headers added */ int request_headers_added; /* number of request headers added */
@@ -83,7 +85,7 @@ struct h2_stream {
* @return the newly opened stream * @return the newly opened stream
*/ */
h2_stream *h2_stream_open(int id, apr_pool_t *pool, struct h2_session *session, h2_stream *h2_stream_open(int id, apr_pool_t *pool, struct h2_session *session,
int initiated_on, const struct h2_request *req); int initiated_on);
/** /**
* Cleanup any resources still held by the stream, called by last bucket. * Cleanup any resources still held by the stream, called by last bucket.
@@ -111,6 +113,13 @@ void h2_stream_cleanup(h2_stream *stream);
*/ */
apr_pool_t *h2_stream_detach_pool(h2_stream *stream); apr_pool_t *h2_stream_detach_pool(h2_stream *stream);
/**
* Initialize stream->request with the given h2_request.
*
* @param stream stream to write request to
* @param r the request with all the meta data
*/
apr_status_t h2_stream_set_request(h2_stream *stream, const h2_request *r);
/** /**
* Initialize stream->request with the given request_rec. * Initialize stream->request with the given request_rec.
@@ -118,7 +127,7 @@ apr_pool_t *h2_stream_detach_pool(h2_stream *stream);
* @param stream stream to write request to * @param stream stream to write request to
* @param r the request with all the meta data * @param r the request with all the meta data
*/ */
apr_status_t h2_stream_set_request(h2_stream *stream, request_rec *r); apr_status_t h2_stream_set_request_rec(h2_stream *stream, request_rec *r);
/* /*
* Add a HTTP/2 header (including pseudo headers) or trailer * Add a HTTP/2 header (including pseudo headers) or trailer

View File

@@ -89,7 +89,7 @@ static apr_status_t input_handle_eos(h2_task *task, request_rec *r,
{ {
apr_status_t status = APR_SUCCESS; apr_status_t status = APR_SUCCESS;
apr_bucket_brigade *bb = task->input.bb; apr_bucket_brigade *bb = task->input.bb;
apr_table_t *t = task->request? task->request->trailers : NULL; apr_table_t *t = task->request->trailers;
if (task->input.chunked) { if (task->input.chunked) {
apr_bucket_brigade *tmp = apr_brigade_split_ex(bb, b, NULL); apr_bucket_brigade *tmp = apr_brigade_split_ex(bb, b, NULL);
@@ -116,7 +116,7 @@ static apr_status_t input_append_eos(h2_task *task, request_rec *r)
{ {
apr_status_t status = APR_SUCCESS; apr_status_t status = APR_SUCCESS;
apr_bucket_brigade *bb = task->input.bb; apr_bucket_brigade *bb = task->input.bb;
apr_table_t *t = task->request? task->request->trailers : NULL; apr_table_t *t = task->request->trailers;
if (task->input.chunked) { if (task->input.chunked) {
if (t && !apr_is_empty_table(t)) { if (t && !apr_is_empty_table(t)) {
@@ -153,7 +153,7 @@ static apr_status_t input_read(h2_task *task, ap_filter_t* f,
return ap_get_brigade(f->c->input_filters, bb, mode, block, readbytes); return ap_get_brigade(f->c->input_filters, bb, mode, block, readbytes);
} }
if (f->c->aborted || !task->request) { if (f->c->aborted) {
return APR_ECONNABORTED; return APR_ECONNABORTED;
} }
@@ -578,8 +578,7 @@ apr_status_t h2_task_add_response(h2_task *task, h2_response *response)
int h2_task_can_redo(h2_task *task) { int h2_task_can_redo(h2_task *task) {
if (task->response_sent if (task->response_sent
|| (task->input.beam && h2_beam_was_received(task->input.beam)) || (task->input.beam && h2_beam_was_received(task->input.beam))) {
|| !task->request) {
/* cannot repeat that. */ /* cannot repeat that. */
return 0; return 0;
} }
@@ -683,6 +682,10 @@ h2_task *h2_task_create(conn_rec *c, const h2_request *req,
apr_pool_t *pool; apr_pool_t *pool;
h2_task *task; h2_task *task;
ap_assert(mplx);
ap_assert(c);
ap_assert(req);
apr_pool_create(&pool, c->pool); apr_pool_create(&pool, c->pool);
task = apr_pcalloc(pool, sizeof(h2_task)); task = apr_pcalloc(pool, sizeof(h2_task));
if (task == NULL) { if (task == NULL) {
@@ -691,7 +694,6 @@ h2_task *h2_task_create(conn_rec *c, const h2_request *req,
c->id, req->id); c->id, req->id);
return NULL; return NULL;
} }
task->id = apr_psprintf(pool, "%ld-%d", c->id, req->id); task->id = apr_psprintf(pool, "%ld-%d", c->id, req->id);
task->stream_id = req->id; task->stream_id = req->id;
task->c = c; task->c = c;

View File

@@ -1276,7 +1276,7 @@ apr_status_t h2_headers_add_h1(apr_table_t *headers, apr_pool_t *pool,
* h2 request handling * h2 request handling
******************************************************************************/ ******************************************************************************/
h2_request *h2_req_createn(int id, apr_pool_t *pool, const char *method, h2_request *h2_req_create(int id, apr_pool_t *pool, const char *method,
const char *scheme, const char *authority, const char *scheme, const char *authority,
const char *path, apr_table_t *header, int serialize) const char *path, apr_table_t *header, int serialize)
{ {
@@ -1294,49 +1294,6 @@ h2_request *h2_req_createn(int id, apr_pool_t *pool, const char *method,
return req; return req;
} }
h2_request *h2_req_create(int id, apr_pool_t *pool, int serialize)
{
return h2_req_createn(id, pool, NULL, NULL, NULL, NULL, NULL, serialize);
}
typedef struct {
apr_table_t *headers;
apr_pool_t *pool;
} h1_ctx;
static int set_h1_header(void *ctx, const char *key, const char *value)
{
h1_ctx *x = ctx;
size_t klen = strlen(key);
if (!h2_req_ignore_header(key, klen)) {
h2_headers_add_h1(x->headers, x->pool, key, klen, value, strlen(value));
}
return 1;
}
apr_status_t h2_req_make(h2_request *req, apr_pool_t *pool,
const char *method, const char *scheme,
const char *authority, const char *path,
apr_table_t *headers)
{
h1_ctx x;
req->method = method;
req->scheme = scheme;
req->authority = authority;
req->path = path;
AP_DEBUG_ASSERT(req->scheme);
AP_DEBUG_ASSERT(req->authority);
AP_DEBUG_ASSERT(req->path);
AP_DEBUG_ASSERT(req->method);
x.pool = pool;
x.headers = req->headers;
apr_table_do(set_h1_header, &x, headers, NULL);
return APR_SUCCESS;
}
/******************************************************************************* /*******************************************************************************
* frame logging * frame logging
******************************************************************************/ ******************************************************************************/

View File

@@ -261,16 +261,10 @@ apr_status_t h2_headers_add_h1(apr_table_t *headers, apr_pool_t *pool,
* h2_request helpers * h2_request helpers
******************************************************************************/ ******************************************************************************/
struct h2_request *h2_req_createn(int id, apr_pool_t *pool, const char *method, struct h2_request *h2_req_create(int id, apr_pool_t *pool, const char *method,
const char *scheme, const char *authority, const char *scheme, const char *authority,
const char *path, apr_table_t *header, const char *path, apr_table_t *header,
int serialize); int serialize);
struct h2_request *h2_req_create(int id, apr_pool_t *pool, int serialize);
apr_status_t h2_req_make(struct h2_request *req, apr_pool_t *pool,
const char *method, const char *scheme,
const char *authority, const char *path,
apr_table_t *headers);
/******************************************************************************* /*******************************************************************************
* apr brigade helpers * apr brigade helpers