Exemplo n.º 1
0
int h2_h2_process_conn(conn_rec* c)
{
    h2_ctx *ctx = h2_ctx_get(c, 0);
    
    if (ctx) {
        if (h2_ctx_is_task(c)) {
            // This should not happend, as we install our own filters
            // in h2_h2_pre_connection in such cases, so the normal
            // connection hooks get bypassed.
            return DECLINED;
        }
        else if (!h2_ctx_is_negotiated(c)) {
            // Let the client/server hellos fly and ALPN call us back.
            apr_bucket_brigade* temp_brigade = apr_brigade_create(
                c->pool, c->bucket_alloc);
            ap_get_brigade(c->input_filters, temp_brigade,
                AP_MODE_SPECULATIVE, APR_BLOCK_READ, 1);
            apr_brigade_destroy(temp_brigade);
        }
        check_sni_host(c);
    }
    
    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "h2_h2, connection, start");
    if (h2_ctx_is_active(c)) {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
                      "h2_h2, connection, h2 active");
        
        return h2_conn_main(c);
    }
    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
                  "h2_h2, connection, declined");
    return DECLINED;
}
Exemplo n.º 2
0
static int h2_alt_svc_handler(request_rec *r)
{
    h2_ctx *ctx;
    h2_config *cfg;
    int i;
    
    if (r->connection->keepalives > 0) {
        /* Only announce Alt-Svc on the first response */
        return DECLINED;
    }
    
    ctx = h2_ctx_rget(r);
    if (h2_ctx_is_active(ctx) || h2_ctx_is_task(ctx)) {
        return DECLINED;
    }
    
    cfg = h2_config_rget(r);
    if (r->hostname && cfg && cfg->alt_svcs && cfg->alt_svcs->nelts > 0) {
        const char *alt_svc_used = apr_table_get(r->headers_in, "Alt-Svc-Used");
        if (!alt_svc_used) {
            /* We have alt-svcs defined and client is not already using
             * one, announce the services that were configured and match. 
             * The security of this connection determines if we allow
             * other host names or ports only.
             */
            const char *alt_svc = "";
            const char *svc_ma = "";
            int secure = h2_h2_is_tls(r->connection);
            int ma = h2_config_geti(cfg, H2_CONF_ALT_SVC_MAX_AGE);
            if (ma >= 0) {
                svc_ma = apr_psprintf(r->pool, "; ma=%d", ma);
            }
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                          "h2_alt_svc: announce %s for %s:%d", 
                          (secure? "secure" : "insecure"), 
                          r->hostname, (int)r->server->port);
            for (i = 0; i < cfg->alt_svcs->nelts; ++i) {
                h2_alt_svc *as = h2_alt_svc_IDX(cfg->alt_svcs, i);
                const char *ahost = as->host;
                if (ahost && !apr_strnatcasecmp(ahost, r->hostname)) {
                    ahost = NULL;
                }
                if (secure || !ahost) {
                    alt_svc = apr_psprintf(r->pool, "%s%s%s=\"%s:%d\"%s", 
                                           alt_svc,
                                           (*alt_svc? ", " : ""), as->alpn,
                                           ahost? ahost : "", as->port,
                                           svc_ma);
                }
            }
            if (*alt_svc) {
                apr_table_set(r->headers_out, "Alt-Svc", alt_svc);
            }
        }
    }
    
    return DECLINED;
}
Exemplo n.º 3
0
static int h2_h2_remove_timeout(conn_rec* c)
{
    h2_ctx *ctx = h2_ctx_get(c);
    
    if (h2_ctx_is_active(ctx) && !h2_ctx_is_task(ctx)) {
        /* cleanup on master h2 connections */
        ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout");
    }
    
    return DECLINED;
}
Exemplo n.º 4
0
int h2_h2_process_conn(conn_rec* c)
{
    h2_ctx *ctx = h2_ctx_get(c);
    
    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, process_conn");
    if (h2_ctx_is_task(ctx)) {
        /* our stream pseudo connection */
        return DECLINED;
    }

    if (h2_ctx_protocol_get(c)) {
        /* Something has been negotiated */
    }
    else if (!strcmp(AP_PROTOCOL_HTTP1, ap_get_protocol(c))
             && h2_allows_h2_direct(c) 
             && h2_is_acceptable_connection(c, 1)) {
        /* connection still is on http/1.1 and H2Direct is enabled. 
         * Otherwise connection is in a fully acceptable state.
         * -> peek at the first 24 incoming bytes
         */
        apr_bucket_brigade *temp;
        apr_status_t status;
        char *s = NULL;
        apr_size_t slen;
        
        temp = apr_brigade_create(c->pool, c->bucket_alloc);
        status = ap_get_brigade(c->input_filters, temp,
                                AP_MODE_SPECULATIVE, APR_BLOCK_READ, 24);
        
        if (status != APR_SUCCESS) {
            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c,
                          "h2_h2, error reading 24 bytes speculative");
            apr_brigade_destroy(temp);
            return DECLINED;
        }
        
        apr_brigade_pflatten(temp, &s, &slen, c->pool);
        if ((slen >= 24) && !memcmp(H2_MAGIC_TOKEN, s, 24)) {
            ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                          "h2_h2, direct mode detected");
            h2_ctx_protocol_set(ctx, h2_h2_is_tls(c)? "h2" : "h2c");
        }
        else {
            ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
                          "h2_h2, not detected in %d bytes: %s", 
                          (int)slen, s);
        }
        
        apr_brigade_destroy(temp);
    }
    else {
        /* the connection is not HTTP/1.1 or not for us, don't touch it */
        return DECLINED;
    }

    /* If "h2" was selected as protocol (by whatever mechanism), take over
     * the connection.
     */
    if (h2_ctx_is_active(ctx)) {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                      "h2_h2, connection, h2 active");
        
        return h2_conn_process(c, NULL, ctx->server);
    }
    
    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, declined");
    return DECLINED;
}