/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include <assert.h>
#include <stdio.h>

#include <apr_strings.h>

#include <httpd.h>
#include <http_core.h>
#include <http_log.h>
#include <util_time.h>

#include <nghttp2/nghttp2.h>

#include "h2_private.h"
#include "h2_h2.h"
#include "h2_config.h"
#include "h2_util.h"
#include "h2_request.h"
#include "h2_headers.h"


static int is_unsafe(server_rec *s) 
{
    core_server_config *conf = ap_get_core_module_config(s->module_config);
    return (conf->http_conformance == AP_HTTP_CONFORMANCE_UNSAFE);
}

typedef struct {
    apr_bucket_refcount refcount;
    h2_headers *headers;
} h2_bucket_headers;
 
static apr_status_t bucket_read(apr_bucket *b, const char **str,
                                apr_size_t *len, apr_read_type_e block)
{
    (void)b;
    (void)block;
    *str = NULL;
    *len = 0;
    return APR_SUCCESS;
}

apr_bucket * h2_bucket_headers_make(apr_bucket *b, h2_headers *r)
{
    h2_bucket_headers *br;

    br = apr_bucket_alloc(sizeof(*br), b->list);
    br->headers = r;

    b = apr_bucket_shared_make(b, br, 0, 0);
    b->type = &h2_bucket_type_headers;
    
    return b;
} 

apr_bucket * h2_bucket_headers_create(apr_bucket_alloc_t *list, 
                                       h2_headers *r)
{
    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);

    APR_BUCKET_INIT(b);
    b->free = apr_bucket_free;
    b->list = list;
    b = h2_bucket_headers_make(b, r);
    return b;
}
                                       
h2_headers *h2_bucket_headers_get(apr_bucket *b)
{
    if (H2_BUCKET_IS_HEADERS(b)) {
        return ((h2_bucket_headers *)b->data)->headers;
    }
    return NULL;
}

const apr_bucket_type_t h2_bucket_type_headers = {
    "H2HEADERS", 5, APR_BUCKET_METADATA,
    apr_bucket_destroy_noop,
    bucket_read,
    apr_bucket_setaside_noop,
    apr_bucket_split_notimpl,
    apr_bucket_shared_copy
};

apr_bucket *h2_bucket_headers_beam(struct h2_bucket_beam *beam,
                                    apr_bucket_brigade *dest,
                                    const apr_bucket *src)
{
    if (H2_BUCKET_IS_HEADERS(src)) {
        h2_headers *src_headers = ((h2_bucket_headers *)src->data)->headers;
        apr_bucket *b = h2_bucket_headers_create(dest->bucket_alloc, 
                                                 h2_headers_clone(dest->p, src_headers));
        APR_BRIGADE_INSERT_TAIL(dest, b);
        return b;
    }
    return NULL;
}


h2_headers *h2_headers_create(int status, apr_table_t *headers_in, 
                                apr_table_t *notes, apr_off_t raw_bytes,
                                apr_pool_t *pool)
{
    h2_headers *headers = apr_pcalloc(pool, sizeof(h2_headers));
    headers->status    = status;
    headers->headers   = (headers_in? apr_table_clone(pool, headers_in)
                           : apr_table_make(pool, 5));
    headers->notes     = (notes? apr_table_clone(pool, notes)
                           : apr_table_make(pool, 5));
    return headers;
}

h2_headers *h2_headers_rcreate(request_rec *r, int status,
                                 apr_table_t *header, apr_pool_t *pool)
{
    h2_headers *headers = h2_headers_create(status, header, r->notes, 0, pool);
    if (headers->status == HTTP_FORBIDDEN) {
        request_rec *r_prev;
        for (r_prev = r; r_prev != NULL; r_prev = r_prev->prev) {
            const char *cause = apr_table_get(r_prev->notes, "ssl-renegotiate-forbidden");
            if (cause) {
                /* This request triggered a TLS renegotiation that is not allowed
                 * in HTTP/2. Tell the client that it should use HTTP/1.1 for this.
                 */
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, headers->status, r,
                              APLOGNO(03061)
                              "h2_headers(%ld): renegotiate forbidden, cause: %s",
                              (long)r->connection->id, cause);
                headers->status = H2_ERR_HTTP_1_1_REQUIRED;
                break;
            }
        }
    }
    if (is_unsafe(r->server)) {
        apr_table_setn(headers->notes, H2_HDR_CONFORMANCE, H2_HDR_CONFORMANCE_UNSAFE);
    }
    if (h2_config_rgeti(r, H2_CONF_PUSH) == 0 && h2_config_sgeti(r->server, H2_CONF_PUSH) != 0) {
        apr_table_setn(headers->notes, H2_PUSH_MODE_NOTE, "0");
    }
    return headers;
}

h2_headers *h2_headers_copy(apr_pool_t *pool, h2_headers *h)
{
    return h2_headers_create(h->status, apr_table_copy(pool, h->headers), 
                             apr_table_copy(pool, h->notes), h->raw_bytes, pool);
}

h2_headers *h2_headers_clone(apr_pool_t *pool, h2_headers *h)
{
    return h2_headers_create(h->status, apr_table_clone(pool, h->headers), 
                             apr_table_clone(pool, h->notes), h->raw_bytes, pool);
}

h2_headers *h2_headers_die(apr_status_t type,
                             const h2_request *req, apr_pool_t *pool)
{
    h2_headers *headers;
    char *date;
    
    headers = apr_pcalloc(pool, sizeof(h2_headers));
    headers->status    = (type >= 200 && type < 600)? type : 500;
    headers->headers        = apr_table_make(pool, 5);
    headers->notes          = apr_table_make(pool, 5);

    date = apr_palloc(pool, APR_RFC822_DATE_LEN);
    ap_recent_rfc822_date(date, req? req->request_time : apr_time_now());
    apr_table_setn(headers->headers, "Date", date);
    apr_table_setn(headers->headers, "Server", ap_get_server_banner());
    
    return headers;
}

int h2_headers_are_response(h2_headers *headers)
{
    return headers->status >= 200;
}

