Exemple #1
0
apr_status_t h2_to_h1_add_data(h2_to_h1 *to_h1,
                               const char *data, size_t len)
{
    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, h2_mplx_get_conn(to_h1->m),
                  "h2_to_h1(%ld-%d): add %ld data bytes", 
                  h2_mplx_get_id(to_h1->m), to_h1->stream_id, (long)len);
    
    if (to_h1->chunked) {
        /* if input may have a body and we have not seen any
         * content-length header, we need to chunk the input data.
         */
        apr_status_t status = apr_brigade_printf(to_h1->bb, NULL, NULL,
                                                 "%lx\r\n", len);
        if (status == APR_SUCCESS) {
            status = h2_to_h1_add_data_raw(to_h1, data, len);
            if (status == APR_SUCCESS) {
                status = apr_brigade_puts(to_h1->bb, NULL, NULL, "\r\n");
            }
        }
        return status;
    }
    else {
        to_h1->remain_len -= len;
        if (to_h1->remain_len < 0) {
            ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, 
                          h2_mplx_get_conn(to_h1->m),
                          "h2_to_h1(%ld-%d): got %ld more content bytes than announced "
                          "in content-length header: %ld", 
                          h2_mplx_get_id(to_h1->m),
                          to_h1->stream_id, (long)to_h1->content_len,
                          -(long)to_h1->remain_len);
        }
        return h2_to_h1_add_data_raw(to_h1, data, len);
    }
}
Exemple #2
0
apr_status_t h2_to_h1_end_headers(h2_to_h1 *to_h1, h2_task *task, int eos)
{
    conn_rec *c = h2_mplx_get_conn(to_h1->m);
    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                  "h2_to_h1(%ld-%d): end headers", 
                  h2_mplx_get_id(to_h1->m), to_h1->stream_id);
    
    if (to_h1->eoh) {
        return APR_EINVAL;
    }
    
    if (!to_h1->seen_host) {
        /* Need to add a "Host" header if not already there to
         * make virtual hosts work correctly. */
        if (!to_h1->authority) {
            return APR_BADARG;
        }
        apr_table_set(to_h1->headers, "Host", to_h1->authority);
    }

    if (eos && to_h1->chunked) {
        /* We had chunking figured out, but the EOS is already there.
         * unmark chunking and set a definitive content-length.
         */
        to_h1->chunked = 0;
        apr_table_setn(to_h1->headers, "Content-Length", "0");
    }
    else if (to_h1->chunked) {
        /* We have not seen a content-length. We therefore must
         * pass any request content in chunked form.
         */
        apr_table_mergen(to_h1->headers, "Transfer-Encoding", "chunked");
    }
    
    h2_task_set_request(task, to_h1->method, to_h1->path, 
                        to_h1->authority, to_h1->headers, eos);
    to_h1->eoh = 1;
    
    if (eos) {
        apr_status_t status = h2_to_h1_close(to_h1);
        if (status != APR_SUCCESS) {
            ap_log_cerror(APLOG_MARK, APLOG_WARNING, status, c,
                          "h2_to_h1(%ld-%d): end headers, eos=%d", 
                          h2_mplx_get_id(to_h1->m), to_h1->stream_id, eos);
        }
        return status;
    }
    return APR_SUCCESS;
}
Exemple #3
0
apr_status_t h2_to_h1_flush(h2_to_h1 *to_h1)
{
    apr_status_t status = APR_SUCCESS;
    if (!APR_BRIGADE_EMPTY(to_h1->bb)) {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, h2_mplx_get_conn(to_h1->m),
                      "h2_to_h1(%ld-%d): flush request bytes", 
                      h2_mplx_get_id(to_h1->m), to_h1->stream_id);
        
        status = h2_mplx_in_write(to_h1->m, to_h1->stream_id, to_h1->bb);
        if (status != APR_SUCCESS) {
            ap_log_cerror(APLOG_MARK, APLOG_ERR, status,
                          h2_mplx_get_conn(to_h1->m),
                          "h2_request(%d): pushing request data",
                          to_h1->stream_id);
        }
    }
    return status;
}
Exemple #4
0
static h2_stream *resume_on_data(void *ctx, h2_stream *stream) {
    h2_session *session = (h2_session *)ctx;
    assert(session);
    assert(stream);
    
    if (h2_stream_is_suspended(stream)) {
        ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, stream->pool,
                      "h2_stream(%ld-%d): suspended, checking for DATA",
                      h2_mplx_get_id(stream->m), stream->id);
        if (h2_mplx_out_has_data_for(stream->m, h2_stream_get_id(stream))) {
            h2_stream_set_suspended(stream, 0);
            int rv = nghttp2_session_resume_data(session->ngh2,
                                                 h2_stream_get_id(stream));
            ap_log_cerror(APLOG_MARK, nghttp2_is_fatal(rv)?
                          APLOG_ERR : APLOG_DEBUG, 0, session->c,
                          "h2_stream(%ld-%d): resuming stream %s",
                          session->id, stream->id, nghttp2_strerror(rv));
        }
    }
    return NULL;
}