Blame modules/http2/h2_proxy_util.h

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
#ifndef __mod_h2__h2_proxy_util__
Packit 90a5c9
#define __mod_h2__h2_proxy_util__
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * some debugging/format helpers
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
struct h2_proxy_request;
Packit 90a5c9
struct nghttp2_frame;
Packit 90a5c9
Packit 90a5c9
int h2_proxy_util_frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * ihash - hash for structs with int identifier
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
typedef struct h2_proxy_ihash_t h2_proxy_ihash_t;
Packit 90a5c9
typedef int h2_proxy_ihash_iter_t(void *ctx, void *val);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Create a hash for structures that have an identifying int member.
Packit 90a5c9
 * @param pool the pool to use
Packit 90a5c9
 * @param offset_of_int the offsetof() the int member in the struct
Packit 90a5c9
 */
Packit 90a5c9
h2_proxy_ihash_t *h2_proxy_ihash_create(apr_pool_t *pool, size_t offset_of_int);
Packit 90a5c9
Packit 90a5c9
size_t h2_proxy_ihash_count(h2_proxy_ihash_t *ih);
Packit 90a5c9
int h2_proxy_ihash_empty(h2_proxy_ihash_t *ih);
Packit 90a5c9
void *h2_proxy_ihash_get(h2_proxy_ihash_t *ih, int id);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Iterate over the hash members (without defined order) and invoke
Packit 90a5c9
 * fn for each member until 0 is returned.
Packit 90a5c9
 * @param ih the hash to iterate over
Packit 90a5c9
 * @param fn the function to invoke on each member
Packit 90a5c9
 * @param ctx user supplied data passed into each iteration call
Packit 90a5c9
 * @return 0 if one iteration returned 0, otherwise != 0
Packit 90a5c9
 */
Packit 90a5c9
int h2_proxy_ihash_iter(h2_proxy_ihash_t *ih, h2_proxy_ihash_iter_t *fn, void *ctx);
Packit 90a5c9
Packit 90a5c9
void h2_proxy_ihash_add(h2_proxy_ihash_t *ih, void *val);
Packit 90a5c9
void h2_proxy_ihash_remove(h2_proxy_ihash_t *ih, int id);
Packit 90a5c9
void h2_proxy_ihash_remove_val(h2_proxy_ihash_t *ih, void *val);
Packit 90a5c9
void h2_proxy_ihash_clear(h2_proxy_ihash_t *ih);
Packit 90a5c9
Packit 90a5c9
size_t h2_proxy_ihash_shift(h2_proxy_ihash_t *ih, void **buffer, size_t max);
Packit 90a5c9
size_t h2_proxy_ihash_ishift(h2_proxy_ihash_t *ih, int *buffer, size_t max);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * iqueue - sorted list of int with user defined ordering
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
typedef struct h2_proxy_iqueue {
Packit 90a5c9
    int *elts;
Packit 90a5c9
    int head;
Packit 90a5c9
    int nelts;
Packit 90a5c9
    int nalloc;
Packit 90a5c9
    apr_pool_t *pool;
Packit 90a5c9
} h2_proxy_iqueue;
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Comparator for two int to determine their order.
Packit 90a5c9
 *
Packit 90a5c9
 * @param i1 first int to compare
Packit 90a5c9
 * @param i2 second int to compare
Packit 90a5c9
 * @param ctx provided user data
Packit 90a5c9
 * @return value is the same as for strcmp() and has the effect:
Packit 90a5c9
 *    == 0: s1 and s2 are treated equal in ordering
Packit 90a5c9
 *     < 0: s1 should be sorted before s2
Packit 90a5c9
 *     > 0: s2 should be sorted before s1
Packit 90a5c9
 */
Packit 90a5c9
typedef int h2_proxy_iq_cmp(int i1, int i2, void *ctx);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Allocate a new queue from the pool and initialize.
Packit 90a5c9
 * @param id the identifier of the queue
Packit 90a5c9
 * @param pool the memory pool
Packit 90a5c9
 */
Packit 90a5c9
h2_proxy_iqueue *h2_proxy_iq_create(apr_pool_t *pool, int capacity);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Return != 0 iff there are no tasks in the queue.
Packit 90a5c9
 * @param q the queue to check
Packit 90a5c9
 */
Packit 90a5c9
int h2_proxy_iq_empty(h2_proxy_iqueue *q);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Return the number of int in the queue.
Packit 90a5c9
 * @param q the queue to get size on
Packit 90a5c9
 */
Packit 90a5c9
int h2_proxy_iq_count(h2_proxy_iqueue *q);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Add a stream id to the queue. 
Packit 90a5c9
 *
Packit 90a5c9
 * @param q the queue to append the task to
Packit 90a5c9
 * @param sid the stream id to add
Packit 90a5c9
 * @param cmp the comparator for sorting
Packit 90a5c9
 * @param ctx user data for comparator 
Packit 90a5c9
 */
Packit 90a5c9
void h2_proxy_iq_add(h2_proxy_iqueue *q, int sid, h2_proxy_iq_cmp *cmp, void *ctx);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Remove the stream id from the queue. Return != 0 iff task
Packit 90a5c9
 * was found in queue.
Packit 90a5c9
 * @param q the task queue
Packit 90a5c9
 * @param sid the stream id to remove
Packit 90a5c9
 * @return != 0 iff task was found in queue
Packit 90a5c9
 */
Packit 90a5c9
int h2_proxy_iq_remove(h2_proxy_iqueue *q, int sid);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Remove all entries in the queue.
Packit 90a5c9
 */
Packit 90a5c9
void h2_proxy_iq_clear(h2_proxy_iqueue *q);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Sort the stream idqueue again. Call if the task ordering
Packit 90a5c9
 * has changed.
Packit 90a5c9
 *
Packit 90a5c9
 * @param q the queue to sort
Packit 90a5c9
 * @param cmp the comparator for sorting
Packit 90a5c9
 * @param ctx user data for the comparator 
Packit 90a5c9
 */
Packit 90a5c9
void h2_proxy_iq_sort(h2_proxy_iqueue *q, h2_proxy_iq_cmp *cmp, void *ctx);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Get the first stream id from the queue or NULL if the queue is empty. 
Packit 90a5c9
 * The task will be removed.
Packit 90a5c9
 *
Packit 90a5c9
 * @param q the queue to get the first task from
Packit 90a5c9
 * @return the first stream id of the queue, 0 if empty
Packit 90a5c9
 */
Packit 90a5c9
int h2_proxy_iq_shift(h2_proxy_iqueue *q);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * common helpers
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
/* h2_proxy_log2(n) iff n is a power of 2 */
Packit 90a5c9
unsigned char h2_proxy_log2(int n);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * HTTP/2 header helpers
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
void h2_proxy_util_camel_case_header(char *s, size_t len);
Packit 90a5c9
int h2_proxy_res_ignore_header(const char *name, size_t len);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * nghttp2 helpers
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
typedef struct h2_proxy_ngheader {
Packit 90a5c9
    nghttp2_nv *nv;
Packit 90a5c9
    apr_size_t nvlen;
Packit 90a5c9
} h2_proxy_ngheader;
Packit 90a5c9
h2_proxy_ngheader *h2_proxy_util_nghd_make_req(apr_pool_t *p, 
Packit 90a5c9
                                               const struct h2_proxy_request *req);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * h2_proxy_request helpers
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
typedef struct h2_proxy_request h2_proxy_request;
Packit 90a5c9
Packit 90a5c9
struct h2_proxy_request {
Packit 90a5c9
    const char *method; /* pseudo header values, see ch. 8.1.2.3 */
Packit 90a5c9
    const char *scheme;
Packit 90a5c9
    const char *authority;
Packit 90a5c9
    const char *path;
Packit 90a5c9
    
Packit 90a5c9
    apr_table_t *headers;
Packit 90a5c9
    
Packit 90a5c9
    apr_time_t request_time;
Packit 90a5c9
    
Packit 90a5c9
    unsigned int chunked : 1;   /* iff requst body needs to be forwarded as chunked */
Packit 90a5c9
    unsigned int serialize : 1; /* iff this request is written in HTTP/1.1 serialization */
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
h2_proxy_request *h2_proxy_req_create(int id, apr_pool_t *pool, int serialize);
Packit 90a5c9
apr_status_t h2_proxy_req_make(h2_proxy_request *req, apr_pool_t *pool,
Packit 90a5c9
                               const char *method, const char *scheme, 
Packit 90a5c9
                               const char *authority, const char *path, 
Packit 90a5c9
                               apr_table_t *headers);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * reverse mapping for link headers
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
const char *h2_proxy_link_reverse_map(request_rec *r,
Packit 90a5c9
                                      proxy_dir_conf *conf, 
Packit 90a5c9
                                      const char *real_server_uri,
Packit 90a5c9
                                      const char *proxy_server_uri,
Packit 90a5c9
                                      const char *s);
Packit 90a5c9
Packit 90a5c9
/*******************************************************************************
Packit 90a5c9
 * FIFO queue
Packit 90a5c9
 ******************************************************************************/
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * A thread-safe FIFO queue with some extra bells and whistles, if you
Packit 90a5c9
 * do not need anything special, better use 'apr_queue'.
Packit 90a5c9
 */
Packit 90a5c9
typedef struct h2_proxy_fifo h2_proxy_fifo;
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Create a FIFO queue that can hold up to capacity elements. Elements can
Packit 90a5c9
 * appear several times.
Packit 90a5c9
 */
Packit 90a5c9
apr_status_t h2_proxy_fifo_create(h2_proxy_fifo **pfifo, apr_pool_t *pool, int capacity);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Create a FIFO set that can hold up to capacity elements. Elements only
Packit 90a5c9
 * appear once. Pushing an element already present does not change the
Packit 90a5c9
 * queue and is successful.
Packit 90a5c9
 */
Packit 90a5c9
apr_status_t h2_proxy_fifo_set_create(h2_proxy_fifo **pfifo, apr_pool_t *pool, int capacity);
Packit 90a5c9
Packit 90a5c9
apr_status_t h2_proxy_fifo_term(h2_proxy_fifo *fifo);
Packit 90a5c9
apr_status_t h2_proxy_fifo_interrupt(h2_proxy_fifo *fifo);
Packit 90a5c9
Packit 90a5c9
int h2_proxy_fifo_capacity(h2_proxy_fifo *fifo);
Packit 90a5c9
int h2_proxy_fifo_count(h2_proxy_fifo *fifo);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Push en element into the queue. Blocks if there is no capacity left.
Packit 90a5c9
 * 
Packit 90a5c9
 * @param fifo the FIFO queue
Packit 90a5c9
 * @param elem the element to push
Packit 90a5c9
 * @return APR_SUCCESS on push, APR_EAGAIN on try_push on a full queue,
Packit 90a5c9
 *         APR_EEXIST when in set mode and elem already there.
Packit 90a5c9
 */
Packit 90a5c9
apr_status_t h2_proxy_fifo_push(h2_proxy_fifo *fifo, void *elem);
Packit 90a5c9
apr_status_t h2_proxy_fifo_try_push(h2_proxy_fifo *fifo, void *elem);
Packit 90a5c9
Packit 90a5c9
apr_status_t h2_proxy_fifo_pull(h2_proxy_fifo *fifo, void **pelem);
Packit 90a5c9
apr_status_t h2_proxy_fifo_try_pull(h2_proxy_fifo *fifo, void **pelem);
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * Remove the elem from the queue, will remove multiple appearances.
Packit 90a5c9
 * @param elem  the element to remove
Packit 90a5c9
 * @return APR_SUCCESS iff > 0 elems were removed, APR_EAGAIN otherwise.
Packit 90a5c9
 */
Packit 90a5c9
apr_status_t h2_proxy_fifo_remove(h2_proxy_fifo *fifo, void *elem);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
#endif /* defined(__mod_h2__h2_proxy_util__) */