static h2_mpm_type_t mpm_type = H2_MPM_UNKNOWN;
static module *mpm_module;
-static module *ssl_module;
static int checked;
static void check_modules(void)
mpm_type = H2_MPM_PREFORK;
mpm_module = m;
}
- else if (!strcmp("mod_ssl.c", m->name)) {
- ssl_module = m;
- }
}
checked = 1;
}
mpm_type = H2_MPM_PREFORK;
mpm_module = m;
}
- else if (!strcmp("mod_ssl.c", m->name)) {
- ssl_module = m;
- }
}
if (minw <= 0) {
env->c.conn_config = ap_create_conn_config(env->pool);
env->c.notes = apr_table_make(env->pool, 5);
+ /* In order to do this in 2.4.x, we need to add a member to conn_rec */
+ env->c.master = master;
+
ap_set_module_config(env->c.conn_config, &core_module,
h2_worker_get_socket(worker));
- /* If we serve http:// requests over a TLS connection, we do
- * not want any mod_ssl vars to be visible.
- */
- if (ssl_module && (!env->scheme || strcmp("http", env->scheme))) {
- /* See #19, there is a range of SSL variables to be gotten from
- * the main connection that should be available in request handlers
- */
- void *sslcfg = ap_get_module_config(master->conn_config, ssl_module);
- if (sslcfg) {
- ap_set_module_config(env->c.conn_config, ssl_module, sslcfg);
- }
- }
-
/* This works for mpm_worker so far. Other mpm modules have
* different needs, unfortunately. The most interesting one
* being mpm_event...
static apr_status_t make_h2_headers(h2_from_h1 *from_h1, request_rec *r)
{
- from_h1->response = h2_response_create(from_h1->stream_id,
- from_h1->status, from_h1->hlines,
- from_h1->pool);
+ from_h1->response = h2_response_create(from_h1->stream_id, 0,
+ from_h1->status, from_h1->hlines,
+ from_h1->pool);
if (from_h1->response == NULL) {
ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EINVAL, r->connection,
APLOGNO(02915)
return opt_ssl_is_https && opt_ssl_is_https(c);
}
-int h2_tls_disable(conn_rec *c)
-{
- if (opt_ssl_engine_disable) {
- return opt_ssl_engine_disable(c);
- }
- return 0;
-}
-
int h2_is_acceptable_connection(conn_rec *c, int require_all)
{
int is_tls = h2_h2_is_tls(c);
*/
extern const char *H2_MAGIC_TOKEN;
+#define H2_ERR_NO_ERROR (0x00)
+#define H2_ERR_PROTOCOL_ERROR (0x01)
+#define H2_ERR_INTERNAL_ERROR (0x02)
+#define H2_ERR_FLOW_CONTROL_ERROR (0x03)
+#define H2_ERR_SETTINGS_TIMEOUT (0x04)
+#define H2_ERR_STREAM_CLOSED (0x05)
+#define H2_ERR_FRAME_SIZE_ERROR (0x06)
+#define H2_ERR_REFUSED_STREAM (0x07)
+#define H2_ERR_CANCEL (0x08)
+#define H2_ERR_COMPRESSION_ERROR (0x09)
+#define H2_ERR_CONNECT_ERROR (0x0a)
+#define H2_ERR_ENHANCE_YOUR_CALM (0x0b)
+#define H2_ERR_INADEQUATE_SECURITY (0x0c)
+#define H2_ERR_HTTP_1_1_REQUIRED (0x0d)
+
/*
* One time, post config intialization.
*/
*/
int h2_h2_is_tls(conn_rec *c);
-/* Disable SSL for this connection, can only be invoked in a pre-
- * connection hook before mod_ssl.
- * @return != 0 iff disable worked
- */
-int h2_tls_disable(conn_rec *c);
-
/* Register apache hooks for h2 protocol
*/
void h2_h2_register_hooks(void);
h2_io_cleanup(io);
}
+void h2_io_set_response(h2_io *io, h2_response *response)
+{
+ AP_DEBUG_ASSERT(response);
+ AP_DEBUG_ASSERT(!io->response);
+ io->response = h2_response_copy(io->pool, response);
+ if (response->rst_error) {
+ h2_io_rst(io, response->rst_error);
+ }
+}
+
+
void h2_io_rst(h2_io *io, int error)
{
io->rst_error = error;
*/
void h2_io_destroy(h2_io *io);
+/**
+ * Set the response of this stream.
+ */
+void h2_io_set_response(h2_io *io, struct h2_response *response);
+
/**
* Reset the stream with the given error code.
*/
m->id, stream_id, response->status);
}
- io->response = h2_response_copy(io->pool, response);
- AP_DEBUG_ASSERT(io->response);
+ h2_io_set_response(io, response);
h2_io_set_add(m->ready_ios, io);
if (bb) {
status = out_write(m, io, f, bb, iowait);
* insert an error one so that our streams can properly
* reset.
*/
- h2_response *r = h2_response_create(stream_id,
+ h2_response *r = h2_response_create(stream_id, 0,
"500", NULL, m->pool);
status = out_open(m, stream_id, r, NULL, NULL, NULL);
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, m->c,
#include <nghttp2/nghttp2.h>
#include "h2_private.h"
+#include "h2_h2.h"
#include "h2_util.h"
#include "h2_response.h"
}
h2_response *h2_response_create(int stream_id,
+ int rst_error,
const char *http_status,
apr_array_header_t *hlines,
apr_pool_t *pool)
}
response->stream_id = stream_id;
- response->status = http_status;
+ response->rst_error = rst_error;
+ response->status = http_status? http_status : "500";
response->content_length = -1;
if (hlines) {
response->status = apr_psprintf(pool, "%d", r->status);
response->content_length = -1;
response->rheader = header;
+
+ if (r->status == HTTP_FORBIDDEN) {
+ const char *cause = apr_table_get(r->notes, "ssl-renegotiate-forbidden");
+ if (cause) {
+ /* This request triggered a TLS renegotiation that is now allowed
+ * in HTTP/2. Tell the client that it should use HTTP/1.1 for this.
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r->status, r,
+ "h2_response(%ld-%d): renegotiate forbidden, cause: %s",
+ (long)r->connection->id, stream_id, cause);
+ response->rst_error = H2_ERR_HTTP_1_1_REQUIRED;
+ }
+ }
return response;
}
typedef struct h2_response {
int stream_id;
+ int rst_error;
const char *status;
apr_off_t content_length;
apr_table_t *rheader;
} h2_response;
h2_response *h2_response_create(int stream_id,
- const char *http_status,
- apr_array_header_t *hlines,
- apr_pool_t *pool);
+ int rst_error,
+ const char *http_status,
+ apr_array_header_t *hlines,
+ apr_pool_t *pool);
h2_response *h2_response_rcreate(int stream_id, request_rec *r,
apr_table_t *header, apr_pool_t *pool);
if (h2_ctx_is_task(ctx)) {
h2_task_env *env = h2_ctx_get_task(ctx);
- /* This connection is a pseudo-connection used for a h2_task.
- * Since we read/write directly from it ourselves, we need
- * to disable a possible ssl connection filter.
- */
- h2_tls_disable(c);
-
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
"h2_h2, pre_connection, found stream task");