blob: 8f8be2993e0ed5b383665474c47cfbeb66388595 [file]
/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
*
* Licensed 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.
*/
#ifndef __mod_h2__h2_util__
#define __mod_h2__h2_util__
struct h2_request;
struct nghttp2_frame;
size_t h2_util_hex_dump(char *buffer, size_t maxlen,
const char *data, size_t datalen);
size_t h2_util_header_print(char *buffer, size_t maxlen,
const char *name, size_t namelen,
const char *value, size_t valuelen);
char *h2_strlwr(char *s);
void h2_util_camel_case_header(char *s, size_t len);
int h2_req_ignore_header(const char *name, size_t len);
int h2_req_ignore_trailer(const char *name, size_t len);
void h2_req_strip_ignored_header(apr_table_t *headers);
int h2_res_ignore_trailer(const char *name, size_t len);
/**
* Return != 0 iff the string s contains the token, as specified in
* HTTP header syntax, rfc7230.
*/
int h2_util_contains_token(apr_pool_t *pool, const char *s, const char *token);
const char *h2_util_first_token_match(apr_pool_t *pool, const char *s,
const char *tokens[], apr_size_t len);
/**
* I always wanted to write my own base64url decoder...not. See
* https://tools.ietf.org/html/rfc4648#section-5 for description.
*/
apr_size_t h2_util_base64url_decode(const char **decoded,
const char *encoded,
apr_pool_t *pool);
#define H2_HD_MATCH_LIT(l, name, nlen) \
((nlen == sizeof(l) - 1) && !apr_strnatcasecmp(l, name))
#define H2_HD_MATCH_LIT_CS(l, name) \
((strlen(name) == sizeof(l) - 1) && !apr_strnatcasecmp(l, name))
#define H2_CREATE_NV_LIT_CS(nv, NAME, VALUE) nv->name = (uint8_t *)NAME; \
nv->namelen = sizeof(NAME) - 1; \
nv->value = (uint8_t *)VALUE; \
nv->valuelen = strlen(VALUE)
#define H2_CREATE_NV_CS_LIT(nv, NAME, VALUE) nv->name = (uint8_t *)NAME; \
nv->namelen = strlen(NAME); \
nv->value = (uint8_t *)VALUE; \
nv->valuelen = sizeof(VALUE) - 1
#define H2_CREATE_NV_CS_CS(nv, NAME, VALUE) nv->name = (uint8_t *)NAME; \
nv->namelen = strlen(NAME); \
nv->value = (uint8_t *)VALUE; \
nv->valuelen = strlen(VALUE)
int h2_util_ignore_header(const char *name);
typedef struct h2_ngheader {
nghttp2_nv *nv;
apr_size_t nvlen;
} h2_ngheader;
h2_ngheader *h2_util_ngheader_make(apr_pool_t *p, apr_table_t *header);
h2_ngheader *h2_util_ngheader_make_res(apr_pool_t *p,
int http_status,
apr_table_t *header);
h2_ngheader *h2_util_ngheader_make_req(apr_pool_t *p,
const struct h2_request *req);
/**
* Moves data from one brigade into another. If maxlen > 0, it only
* moves up to maxlen bytes into the target brigade, making bucket splits
* if needed.
* @param to the brigade to move the data to
* @param from the brigade to get the data from
* @param maxlen of bytes to move, <= 0 for all
* @param pfile_buckets_allowed how many file buckets may be moved,
* may be 0 or NULL
* @param msg message for use in logging
*/
apr_status_t h2_util_move(apr_bucket_brigade *to, apr_bucket_brigade *from,
apr_off_t maxlen, int *pfile_buckets_allowed,
const char *msg);
/**
* Copies buckets from one brigade into another. If maxlen > 0, it only
* copies up to maxlen bytes into the target brigade, making bucket splits
* if needed.
* @param to the brigade to copy the data to
* @param from the brigade to get the data from
* @param maxlen of bytes to copy, <= 0 for all
* @param msg message for use in logging
*/
apr_status_t h2_util_copy(apr_bucket_brigade *to, apr_bucket_brigade *from,
apr_off_t maxlen, const char *msg);
/**
* Return != 0 iff there is a FLUSH or EOS bucket in the brigade.
* @param bb the brigade to check on
* @return != 0 iff brigade holds FLUSH or EOS bucket (or both)
*/
int h2_util_has_flush_or_eos(apr_bucket_brigade *bb);
int h2_util_has_eos(apr_bucket_brigade *bb, apr_off_t len);
int h2_util_bb_has_data(apr_bucket_brigade *bb);
int h2_util_bb_has_data_or_eos(apr_bucket_brigade *bb);
/**
* Check how many bytes of the desired amount are available and if the
* end of stream is reached by that amount.
* @param bb the brigade to check
* @param plen the desired length and, on return, the available length
* @param on return, if eos has been reached
*/
apr_status_t h2_util_bb_avail(apr_bucket_brigade *bb,
apr_off_t *plen, int *peos);
typedef apr_status_t h2_util_pass_cb(void *ctx,
const char *data, apr_off_t len);
/**
* Read at most *plen bytes from the brigade and pass them into the
* given callback. If cb is NULL, just return the amount of data that
* could have been read.
* If an EOS was/would be encountered, set *peos != 0.
* @param bb the brigade to read from
* @param cb the callback to invoke for the read data
* @param ctx optional data passed to callback
* @param plen inout, as input gives the maximum number of bytes to read,
* on return specifies the actual/would be number of bytes
* @param peos != 0 iff an EOS bucket was/would be encountered.
*/
apr_status_t h2_util_bb_readx(apr_bucket_brigade *bb,
h2_util_pass_cb *cb, void *ctx,
apr_off_t *plen, int *peos);
/**
* Logs the bucket brigade (which bucket types with what length)
* to the log at the given level.
* @param c the connection to log for
* @param stream_id the stream identifier this brigade belongs to
* @param level the log level (as in APLOG_*)
* @param tag a short message text about the context
* @param bb the brigade to log
*/
void h2_util_bb_log(conn_rec *c, int stream_id, int level,
const char *tag, apr_bucket_brigade *bb);
/**
* Transfer buckets from one brigade to another with a limit on the
* maximum amount of bytes transfered.
* @param to brigade to transfer buckets to
* @param from brigades to remove buckets from
* @param p pool that buckets should be setaside to
* @param plen maximum bytes to transfer, actual bytes transferred
* @param peos if an EOS bucket was transferred
*/
apr_status_t h2_transfer_brigade(apr_bucket_brigade *to,
apr_bucket_brigade *from,
apr_pool_t *p,
apr_off_t *plen,
int *peos);
#endif /* defined(__mod_h2__h2_util__) */