#ifndef _HTP_H
#define _HTP_H

/* Warning, this file is autogenerated by cbindgen. Do NOT modify manually */

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define htp_url_encoding_handling_t HtpUrlEncodingHandling
#define htp_log_code_t HtpLogCode


/**
 * Status codes used by LibHTP internally.
 */
typedef enum HtpStatus {
  /**
   * The lowest value LibHTP will use internally.
   */
  HTP_STATUS_ERROR_RESERVED = -1000,
  /**
   * General-purpose error code.
   */
  HTP_STATUS_ERROR = -1,
  /**
   * No processing or work was done. This is typically used by callbacks
   * to indicate that they were not interested in doing any work in the
   * given context.
   */
  HTP_STATUS_DECLINED = 0,
  /**
   * Returned by a function when its work was successfully completed.
   */
  HTP_STATUS_OK = 1,
  /**
   *  Returned when processing a connection stream, after consuming all
   *  provided data. The caller should call again with more data.
   */
  HTP_STATUS_DATA = 2,
  /**
   * Returned when processing a connection stream, after encountering
   * a situation where processing needs to continue on the alternate
   * stream (e.g., the inbound parser needs to observe some outbound
   * data). The data provided was not completely consumed. On the next
   * invocation the caller should supply only the data that has not
   * been processed already. Use request_data_consumed() and response_data_consumed()
   * to determine how much of the most recent data chunk was consumed.
   */
  HTP_STATUS_DATA_OTHER = 3,
  /**
   * Used by callbacks to indicate that the processing should stop. For example,
   * returning HtpStatus::STOP from a connection callback indicates that LibHTP should
   * stop following that particular connection.
   */
  HTP_STATUS_STOP = 4,
  /**
   * Same as DATA, but indicates that any non-consumed part of the data chunk
   * should be preserved (buffered) for later.
   */
  HTP_STATUS_DATA_BUFFER = 5,
  /**
   * The highest value LibHTP will use internally.
   */
  HTP_STATUS_STATUS_RESERVED = 1000,
} HtpStatus;

/**
 * Enumerates the possible server personalities.
 */
typedef enum HtpServerPersonality {
  /**
   * Minimal personality that performs as little work as possible. All optional
   * features are disabled. This personality is a good starting point for customization.
   */
  HTP_SERVER_PERSONALITY_MINIMAL,
  /**
   * A generic personality that aims to work reasonably well for all server types.
   */
  HTP_SERVER_PERSONALITY_GENERIC,
  /**
   * The IDS personality tries to perform as much decoding as possible.
   */
  HTP_SERVER_PERSONALITY_IDS,
  /**
   * Mimics the behavior of IIS 4.0, as shipped with Windows NT 4.0.
   */
  HTP_SERVER_PERSONALITY_IIS_4_0,
  /**
   * Mimics the behavior of IIS 5.0, as shipped with Windows 2000.
   */
  HTP_SERVER_PERSONALITY_IIS_5_0,
  /**
   * Mimics the behavior of IIS 5.1, as shipped with Windows XP Professional.
   */
  HTP_SERVER_PERSONALITY_IIS_5_1,
  /**
   * Mimics the behavior of IIS 6.0, as shipped with Windows 2003.
   */
  HTP_SERVER_PERSONALITY_IIS_6_0,
  /**
   * Mimics the behavior of IIS 7.0, as shipped with Windows 2008.
   */
  HTP_SERVER_PERSONALITY_IIS_7_0,
  /**
   * Mimics the behavior of IIS 7.5, as shipped with Windows 7.
   */
  HTP_SERVER_PERSONALITY_IIS_7_5,
  /**
   * Mimics the behavior of Apache 2.x.
   */
  HTP_SERVER_PERSONALITY_APACHE_2,
} HtpServerPersonality;

/**
 * Enumerates the possible approaches to handling invalid URL-encodings.
 */
typedef enum HtpUrlEncodingHandling {
  /**
   * Ignore invalid URL encodings and leave the % in the data.
   */
  HTP_URL_ENCODING_HANDLING_PRESERVE_PERCENT,
  /**
   * Ignore invalid URL encodings, but remove the % from the data.
   */
  HTP_URL_ENCODING_HANDLING_REMOVE_PERCENT,
  /**
   * Decode invalid URL encodings.
   */
  HTP_URL_ENCODING_HANDLING_PROCESS_INVALID,
} HtpUrlEncodingHandling;

/**
 * Enumerates all stream states. Each connection has two streams, one
 * inbound and one outbound. Their states are tracked separately.
 */
typedef enum HtpStreamState {
  /**
   * Default stream state.
   */
  HTP_STREAM_STATE_NEW,
  /**
   * State when connection is open.
   */
  HTP_STREAM_STATE_OPEN,
  /**
   * State when connection is closed.
   */
  HTP_STREAM_STATE_CLOSED,
  /**
   * State when stream produces a fatal error.
   */
  HTP_STREAM_STATE_ERROR,
  /**
   * State for a tunnelled stream.
   */
  HTP_STREAM_STATE_TUNNEL,
  /**
   * State when parsing is suspended and not consumed in order. This is to
   * allow processing on another stream.
   */
  HTP_STREAM_STATE_DATA_OTHER,
  /**
   * State when we should stop parsing the associated connection.
   */
  HTP_STREAM_STATE_STOP,
  /**
   * State when all current data in the stream has been processed.
   */
  HTP_STREAM_STATE_DATA,
} HtpStreamState;

/**
 * Different codes used for logging.
 */
typedef enum HtpLogCode {
  /**
   * Default
   */
  HTP_LOG_CODE_UNKNOWN = 0,
  /**
   * Gzip Decompression Failed
   */
  HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED,
  /**
   * Request field missing a colon.
   */
  HTP_LOG_CODE_REQUEST_FIELD_MISSING_COLON,
  /**
   * Response field missing a colon.
   */
  HTP_LOG_CODE_RESPONSE_FIELD_MISSING_COLON,
  /**
   * Request chunk length parsing failed.
   */
  HTP_LOG_CODE_INVALID_REQUEST_CHUNK_LEN,
  /**
   * Response chunked-length parsing failed.
   */
  HTP_LOG_CODE_INVALID_RESPONSE_CHUNK_LEN,
  /**
   * Response chunk exension.
   */
  HTP_LOG_CODE_REQUEST_CHUNK_EXTENSION,
  /**
   * Response chunk exension.
   */
  HTP_LOG_CODE_RESPONSE_CHUNK_EXTENSION,
  /**
   * Request has too many headers.
   */
  HTP_LOG_CODE_REQUEST_TOO_MANY_HEADERS,
  /**
   * Response has too many headers.
   */
  HTP_LOG_CODE_RESPONSE_TOO_MANY_HEADERS,
  /**
   * Request transfer-encoding invalid.
   */
  HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST,
  /**
   * Response transfer-encoding invalid.
   */
  HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE,
  /**
   * Request content-length parsing failed.
   */
  HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST,
  /**
   * Response content-length parsing failed.
   */
  HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE,
  /**
   * Request has a duplicate content-length field.
   */
  HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST,
  /**
   * Response has a duplicate content-length field.
   */
  HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE,
  /**
   * 100 Continue response status already seen.
   */
  HTP_LOG_CODE_CONTINUE_ALREADY_SEEN,
  /**
   * Unable to match response to a request.
   */
  HTP_LOG_CODE_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST,
  /**
   * Request server port is invalid.
   */
  HTP_LOG_CODE_INVALID_SERVER_PORT_IN_REQUEST,
  /**
   * Authority port is invalid.
   */
  HTP_LOG_CODE_INVALID_AUTHORITY_PORT,
  /**
   * Request header name is incorrectly formed.
   */
  HTP_LOG_CODE_REQUEST_HEADER_INVALID,
  /**
   * Response header name is incorrectly formed.
   */
  HTP_LOG_CODE_RESPONSE_HEADER_INVALID,
  /**
   * Host header is missing.
   */
  HTP_LOG_CODE_MISSING_HOST_HEADER,
  /**
   * Host header is ambiguous.
   */
  HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS,
  /**
   * Request has invalid line folding.
   */
  HTP_LOG_CODE_INVALID_REQUEST_FIELD_FOLDING,
  /**
   * Response has invalid line folding.
   */
  HTP_LOG_CODE_INVALID_RESPONSE_FIELD_FOLDING,
  /**
   * Request buffer field is over the limit.
   */
  HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG,
  /**
   * Response buffer field is over the limit.
   */
  HTP_LOG_CODE_RESPONSE_FIELD_TOO_LONG,
  /**
   * Mismatch between request server port and tcp port.
   */
  HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH,
  /**
   * Uri hostname is invalid.
   */
  HTP_LOG_CODE_URI_HOST_INVALID,
  /**
   * Header hostname is invalid.
   */
  HTP_LOG_CODE_HEADER_HOST_INVALID,
  /**
   * Non compliant delimiter between method and URI in request line.
   */
  HTP_LOG_CODE_METHOD_DELIM_NON_COMPLIANT,
  /**
   * Parsed request-uri contains a non compliant delimiter.
   */
  HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT,
  /**
   * Request line has leading whitespace.
   */
  HTP_LOG_CODE_REQUEST_LINE_LEADING_WHITESPACE,
  /**
   * Response content encoding lzma layers is greater than limit.
   */
  HTP_LOG_CODE_RESPONSE_TOO_MANY_LZMA_LAYERS,
  /**
   * Request content encoding lzma layers is greater than limit.
   */
  HTP_LOG_CODE_REQUEST_TOO_MANY_LZMA_LAYERS,
  /**
   * Too many request or response encoding layers
   */
  HTP_LOG_CODE_TOO_MANY_ENCODING_LAYERS,
  /**
   * Response header content-encoding header is invalid
   */
  HTP_LOG_CODE_ABNORMAL_CE_HEADER,
  /**
   * Request authorization header unrecognized
   */
  HTP_LOG_CODE_AUTH_UNRECOGNIZED,
  /**
   * Request header has been seen more than once.
   */
  HTP_LOG_CODE_REQUEST_HEADER_REPETITION,
  /**
   * response header has been seen more than once.
   */
  HTP_LOG_CODE_RESPONSE_HEADER_REPETITION,
  /**
   * Response content-type is multipart-byteranges (unsupported).
   */
  HTP_LOG_CODE_RESPONSE_MULTIPART_BYTERANGES,
  /**
   * Response transfer-encoding has an abnormal chunked value.
   */
  HTP_LOG_CODE_RESPONSE_ABNORMAL_TRANSFER_ENCODING,
  /**
   * Response chunked transfer-encoding on HTTP/0.9 or HTTP/1.0.
   */
  HTP_LOG_CODE_RESPONSE_CHUNKED_OLD_PROTO,
  /**
   * Response protocol invalid.
   */
  HTP_LOG_CODE_RESPONSE_INVALID_PROTOCOL,
  /**
   * Response status invalid.
   */
  HTP_LOG_CODE_RESPONSE_INVALID_STATUS,
  /**
   * Response line is incomplete.
   */
  HTP_LOG_CODE_REQUEST_LINE_INCOMPLETE,
  /**
   * Request uri has double encoding.
   */
  HTP_LOG_CODE_DOUBLE_ENCODED_URI,
  /**
   * Request line is invalid.
   */
  HTP_LOG_CODE_REQUEST_LINE_INVALID,
  /**
   * Unexpected request body present.
   */
  HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED,
  /**
   * Reached LZMA memory limit.
   */
  HTP_LOG_CODE_LZMA_MEMLIMIT_REACHED,
  /**
   * Reached configured time limit for decompression or reached bomb limit.
   */
  HTP_LOG_CODE_COMPRESSION_BOMB,
  /**
   * Unexpected response body present.
   */
  HTP_LOG_CODE_RESPONSE_BODY_UNEXPECTED,
  /**
   * Content-length parsing contains extra leading characters.
   */
  HTP_LOG_CODE_CONTENT_LENGTH_EXTRA_DATA_START,
  /**
   * Content-length parsing contains extra trailing characters
   */
  HTP_LOG_CODE_CONTENT_LENGTH_EXTRA_DATA_END,
  /**
   * 101 Switching Protocol seen with a content-length.
   */
  HTP_LOG_CODE_SWITCHING_PROTO_WITH_CONTENT_LENGTH,
  /**
   * End of line is deformed.
   */
  HTP_LOG_CODE_DEFORMED_EOL,
  /**
   * Parsing error encountered in request or response.
   */
  HTP_LOG_CODE_PARSER_STATE_ERROR,
  /**
   * Missing outbound transaction while state is not idle.
   */
  HTP_LOG_CODE_MISSING_OUTBOUND_TRANSACTION_DATA,
  /**
   * Missing inbound transaction while state is not idle.
   */
  HTP_LOG_CODE_MISSING_INBOUND_TRANSACTION_DATA,
  /**
   * Supplied data chunk has a length of zero.
   */
  HTP_LOG_CODE_ZERO_LENGTH_DATA_CHUNKS,
  /**
   * Request Line method is unknown.
   */
  HTP_LOG_CODE_REQUEST_LINE_UNKNOWN_METHOD,
  /**
   * Request line method is unknown and no protocol information was found.
   */
  HTP_LOG_CODE_REQUEST_LINE_UNKNOWN_METHOD_NO_PROTOCOL,
  /**
   * Request line method is unknown and protocol is invalid.
   */
  HTP_LOG_CODE_REQUEST_LINE_UNKNOWN_METHOD_INVALID_PROTOCOL,
  /**
   * Request line protocol information was not found.
   */
  HTP_LOG_CODE_REQUEST_LINE_NO_PROTOCOL,
  /**
   * Response line protocol is invalid.
   */
  HTP_LOG_CODE_RESPONSE_LINE_INVALID_PROTOCOL,
  /**
   * Response line status number is out of range.
   */
  HTP_LOG_CODE_RESPONSE_LINE_INVALID_RESPONSE_STATUS,
  /**
   * Response parsing progress is at an invalid state.
   */
  HTP_LOG_CODE_RESPONSE_BODY_INTERNAL_ERROR,
  /**
   * Request body data callback produced a error.
   */
  HTP_LOG_CODE_REQUEST_BODY_DATA_CALLBACK_ERROR,
  /**
   * Response header name is empty.
   */
  HTP_LOG_CODE_RESPONSE_INVALID_EMPTY_NAME,
  /**
   * Request header name is empty.
   */
  HTP_LOG_CODE_REQUEST_INVALID_EMPTY_NAME,
  /**
   * Response header name has extra whitespace after name.
   */
  HTP_LOG_CODE_RESPONSE_INVALID_LWS_AFTER_NAME,
  /**
   * Response header name is not a valid token.
   */
  HTP_LOG_CODE_RESPONSE_HEADER_NAME_NOT_TOKEN,
  /**
   * Request header name has extra whitespace after name.
   */
  HTP_LOG_CODE_REQUEST_INVALID_LWS_AFTER_NAME,
  /**
   * LZMA decompression is disabled.
   */
  HTP_LOG_CODE_LZMA_DECOMPRESSION_DISABLED,
  /**
   * Tried to open a connection that is already open.
   */
  HTP_LOG_CODE_CONNECTION_ALREADY_OPEN,
  /**
   * Protocol parsing detected leading or trailing data.
   */
  HTP_LOG_CODE_PROTOCOL_CONTAINS_EXTRA_DATA,
  /**
   * Invalid gap detected.
   */
  HTP_LOG_CODE_INVALID_GAP,
  /**
   * Compression bomb due to double lzma encoding.
   */
  HTP_LOG_CODE_COMPRESSION_BOMB_DOUBLE_LZMA,
  /**
   * Invalid content-encoding detected.
   */
  HTP_LOG_CODE_INVALID_CONTENT_ENCODING,
  /**
   * Error retrieving a log message's code
   */
  HTP_LOG_CODE_ERROR,
} HtpLogCode;

/**
 * Enumerate HTTP methods.
 */
typedef enum HtpMethod {
  /**
   * Used by default, until the method is determined (e.g., before
   * the request line is processed.
   */
  HTP_METHOD_UNKNOWN,
  /**
   * HEAD
   */
  HTP_METHOD_HEAD,
  /**
   * GET
   */
  HTP_METHOD_GET,
  /**
   * PUT
   */
  HTP_METHOD_PUT,
  /**
   * POST
   */
  HTP_METHOD_POST,
  /**
   * DELETE
   */
  HTP_METHOD_DELETE,
  /**
   * CONNECT
   */
  HTP_METHOD_CONNECT,
  /**
   * OPTIONS
   */
  HTP_METHOD_OPTIONS,
  /**
   * TRACE
   */
  HTP_METHOD_TRACE,
  /**
   * PATCH
   */
  HTP_METHOD_PATCH,
  /**
   * PROPFIND
   */
  HTP_METHOD_PROPFIND,
  /**
   * PROPPATCH
   */
  HTP_METHOD_PROPPATCH,
  /**
   * MKCOL
   */
  HTP_METHOD_MKCOL,
  /**
   * COPY
   */
  HTP_METHOD_COPY,
  /**
   * MOVE
   */
  HTP_METHOD_MOVE,
  /**
   * LOCK
   */
  HTP_METHOD_LOCK,
  /**
   * UNLOCK
   */
  HTP_METHOD_UNLOCK,
  /**
   * VERSION_CONTROL
   */
  HTP_METHOD_VERSION_CONTROL,
  /**
   * CHECKOUT
   */
  HTP_METHOD_CHECKOUT,
  /**
   * UNCHECKOUT
   */
  HTP_METHOD_UNCHECKOUT,
  /**
   * CHECKIN
   */
  HTP_METHOD_CHECKIN,
  /**
   * UPDATE
   */
  HTP_METHOD_UPDATE,
  /**
   * LABEL
   */
  HTP_METHOD_LABEL,
  /**
   * REPORT
   */
  HTP_METHOD_REPORT,
  /**
   * MKWORKSPACE
   */
  HTP_METHOD_MKWORKSPACE,
  /**
   * MKACTIVITY
   */
  HTP_METHOD_MKACTIVITY,
  /**
   * BASELINE_CONTROL
   */
  HTP_METHOD_BASELINE_CONTROL,
  /**
   * MERGE
   */
  HTP_METHOD_MERGE,
  /**
   * INVALID
   */
  HTP_METHOD_INVALID,
  /**
   * ERROR
   */
  HTP_METHOD_ERROR,
} HtpMethod;

/**
 * Protocol version constants.
 */
typedef enum HtpProtocol {
  /**
   * Error with the transaction side.
   */
  HTP_PROTOCOL_ERROR = -3,
  /**
   * Could not resolve protocol version number.
   */
  HTP_PROTOCOL_INVALID = -2,
  /**
   * Default protocol value.
   */
  HTP_PROTOCOL_UNKNOWN = -1,
  /**
   * HTTP/0.9 version.
   */
  HTP_PROTOCOL_V0_9 = 9,
  /**
   * HTTP/1.0 version.
   */
  HTP_PROTOCOL_V1_0 = 100,
  /**
   * HTTP/1.1 version.
   */
  HTP_PROTOCOL_V1_1 = 101,
} HtpProtocol;

/**
 * Enumerates the possible values for authentication type.
 */
typedef enum HtpAuthType {
  /**
   * This is the default value that is used before
   * the presence of authentication is determined (e.g.,
   * before request headers are seen).
   */
  HTP_AUTH_TYPE_UNKNOWN,
  /**
   * No authentication.
   */
  HTP_AUTH_TYPE_NONE,
  /**
   * HTTP Basic authentication used.
   */
  HTP_AUTH_TYPE_BASIC,
  /**
   * HTTP Digest authentication used.
   */
  HTP_AUTH_TYPE_DIGEST,
  /**
   * HTTP Bearer authentication used.
   */
  HTP_AUTH_TYPE_BEARER,
  /**
   * Unrecognized authentication method.
   */
  HTP_AUTH_TYPE_UNRECOGNIZED = 9,
  /**
   * Error retrieving the auth type.
   */
  HTP_AUTH_TYPE_ERROR,
} HtpAuthType;

/**
 * Possible states of a progressing transaction. Internally, progress will change
 * to the next state when the processing activities associated with that state
 * begin. For example, when we start to process request line bytes, the request
 * state will change from NOT_STARTED to LINE.*
 */
typedef enum HtpRequestProgress {
  /**
   * Default state.
   */
  HTP_REQUEST_PROGRESS_NOT_STARTED,
  /**
   * In request line state.
   */
  HTP_REQUEST_PROGRESS_LINE,
  /**
   * In request headers state.
   */
  HTP_REQUEST_PROGRESS_HEADERS,
  /**
   * In request body state.
   */
  HTP_REQUEST_PROGRESS_BODY,
  /**
   * Trailer data.
   */
  HTP_REQUEST_PROGRESS_TRAILER,
  /**
   * Request is completed.
   */
  HTP_REQUEST_PROGRESS_COMPLETE,
  /**
   * Error involving request side of transaction.
   */
  HTP_REQUEST_PROGRESS_ERROR,
  /**
   * In request gap state.
   */
  HTP_REQUEST_PROGRESS_GAP,
} HtpRequestProgress;

/**
 * Possible states of a progressing transaction. Internally, progress will change
 * to the next state when the processing activities associated with that state
 * begin. For example, when we start to process request line bytes, the request
 * state will change from NOT_STARTED to LINE.*
 */
typedef enum HtpResponseProgress {
  /**
   * Default state.
   */
  HTP_RESPONSE_PROGRESS_NOT_STARTED,
  /**
   * Response Line.
   */
  HTP_RESPONSE_PROGRESS_LINE,
  /**
   * Response Headers.
   */
  HTP_RESPONSE_PROGRESS_HEADERS,
  /**
   * Response Body.
   */
  HTP_RESPONSE_PROGRESS_BODY,
  /**
   * Trailer data.
   */
  HTP_RESPONSE_PROGRESS_TRAILER,
  /**
   * Response completed.
   */
  HTP_RESPONSE_PROGRESS_COMPLETE,
  /**
   * Error involving response side of transaction.
   */
  HTP_RESPONSE_PROGRESS_ERROR,
  /**
   * Response gap.
   */
  HTP_RESPONSE_PROGRESS_GAP,
} HtpResponseProgress;

/**
 * Bstr is a convenience wrapper around binary data that adds string-like functions.
 */
typedef struct bstr bstr;

/**
 * Configuration for libhtp parsing.
 */
typedef struct htp_cfg_t htp_cfg_t;

/**
 * Stores information about the session.
 */
typedef struct htp_conn_t htp_conn_t;

/**
 * Stores information about the parsing process and associated transactions.
 */
typedef struct htp_connp_t htp_connp_t;

/**
 * This structure is used to pass transaction data (for example
 * request and response body buffers) to callbacks.
 */
typedef struct htp_tx_data_t htp_tx_data_t;

typedef struct htp_header_t htp_header_t;

/**
 * Table of request or response headers.
 */
typedef struct htp_headers_t htp_headers_t;

/**
 * Represents a single log entry.
 */
typedef struct htp_log_t htp_log_t;

/**
 * Represents a single HTTP transaction, which is a combination of a request and a response.
 */
typedef struct htp_tx_t htp_tx_t;

/**
 * URI structure. Each of the fields provides access to a single
 * URI element. Where an element is not present in a URI, the
 * corresponding field will be set to NULL or -1, depending on the
 * field type.
 */
typedef struct htp_uri_t htp_uri_t;

/**
 * External (C) callback function prototype
 */
typedef enum HtpStatus (*DataExternalCallbackFn)(const struct htp_connp_t *connp,
                                                 struct htp_tx_data_t *data);

/**
 * External (C) callback function prototype
 */
typedef enum HtpStatus (*TxExternalCallbackFn)(const struct htp_connp_t *connp, struct htp_tx_t *tx);

/**
 * External (C) callback function prototype
 */
typedef void *(*TxCreateCallbackFn)(bool req);

/**
 * External (C) callback function prototype
 */
typedef void (*TxDestroyCallbackFn)(void *tx_ud);

/**
 * Various flag bits. Even though we have a flag field in several places
 * (header, transaction, connection), these fields are all in the same namespace
 * because we may want to set the same flag in several locations. For example, we
 * may set HTP_FIELD_FOLDED on the actual folded header, but also on the transaction
 * that contains the header. Both uses are useful.
 */
typedef struct HTP_FLAGS {

} HTP_FLAGS;
/**
 * Field cannot be parsed.
 */
#define HTP_FLAGS_FIELD_UNPARSEABLE 4
/**
 * Field is invalid.
 */
#define HTP_FLAGS_FIELD_INVALID 8
/**
 * Field is folded.
 */
#define HTP_FLAGS_FIELD_FOLDED 16
/**
 * Field has been seen more than once.
 */
#define HTP_FLAGS_FIELD_REPEATED 32
/**
 * Detect HTTP request smuggling.
 */
#define HTP_FLAGS_REQUEST_SMUGGLING 256
/**
 * Invalid header folding.
 */
#define HTP_FLAGS_INVALID_FOLDING 512
/**
 * Invalid request transfer-encoding.
 */
#define HTP_FLAGS_REQUEST_INVALID_T_E 1024
/**
 * Multiple chunks.
 */
#define HTP_FLAGS_MULTI_PACKET_HEAD 2048
/**
 * No host information in header.
 */
#define HTP_FLAGS_HOST_MISSING 4096
/**
 * Inconsistent host or port information.
 */
#define HTP_FLAGS_HOST_AMBIGUOUS 8192
/**
 * Encoded path contains null.
 */
#define HTP_FLAGS_PATH_ENCODED_NUL 16384
/**
 * Url encoded contains raw null.
 */
#define HTP_FLAGS_PATH_RAW_NUL 32768
/**
 * Url encoding is invalid.
 */
#define HTP_FLAGS_PATH_INVALID_ENCODING 65536
/**
 * Overlong usage in path.
 */
#define HTP_FLAGS_PATH_OVERLONG_U 262144
/**
 * Encoded path separators present.
 */
#define HTP_FLAGS_PATH_ENCODED_SEPARATOR 524288
/**
 * At least one valid UTF-8 character and no invalid ones.
 */
#define HTP_FLAGS_PATH_UTF8_VALID 1048576
/**
 * Invalid utf8 in path.
 */
#define HTP_FLAGS_PATH_UTF8_INVALID 2097152
/**
 * Invalid utf8 overlong character.
 */
#define HTP_FLAGS_PATH_UTF8_OVERLONG 4194304
/**
 * Range U+FF00 - U+FFEF detected.
 */
#define HTP_FLAGS_PATH_HALF_FULL_RANGE 8388608
/**
 * Status line is invalid.
 */
#define HTP_FLAGS_STATUS_LINE_INVALID 16777216
/**
 * Host in the URI.
 */
#define HTP_FLAGS_HOSTU_INVALID 33554432
/**
 * Host in the Host header.
 */
#define HTP_FLAGS_HOSTH_INVALID 67108864
/**
 * Contains null.
 */
#define HTP_FLAGS_URLEN_ENCODED_NUL 134217728
/**
 * Invalid encoding.
 */
#define HTP_FLAGS_URLEN_INVALID_ENCODING 268435456
/**
 * Overlong usage.
 */
#define HTP_FLAGS_URLEN_OVERLONG_U 536870912
/**
 * Range U+FF00 - U+FFEF detected.
 */
#define HTP_FLAGS_URLEN_HALF_FULL_RANGE 1073741824
/**
 * Raw null byte.
 */
#define HTP_FLAGS_URLEN_RAW_NUL 2147483648
/**
 * Request invalid.
 */
#define HTP_FLAGS_REQUEST_INVALID 4294967296
/**
 * Request content-length invalid.
 */
#define HTP_FLAGS_REQUEST_INVALID_C_L 8589934592
/**
 * Authorization is invalid.
 */
#define HTP_FLAGS_AUTH_INVALID 17179869184
/**
 * Missing bytes in request and/or response data.
 */
#define HTP_FLAGS_MISSING_BYTES 34359738368
/**
 * Missing bytes in request data.
 */
#define HTP_FLAGS_REQUEST_MISSING_BYTES (68719476736 | HTP_FLAGS_MISSING_BYTES)
/**
 * Missing bytes in the response data.
 */
#define HTP_FLAGS_RESPONSE_MISSING_BYTES (137438953472 | HTP_FLAGS_MISSING_BYTES)
/**
 * Too many headers, log only once.
 */
#define HTP_FLAGS_HEADERS_TOO_MANY 274877906944

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
 * Returns the LibHTP version string.
 */
const char *htp_get_version(void);

/**
 * Free rust allocated cstring
 *
 * # Safety
 * This should only ever be called with a pointer that was earlier obtained by calling [CString::into_raw].
 */
void htp_free_cstring(char *input);

/**
 * Deallocate the supplied bstring instance. Allows NULL on input.
 * # Safety
 * This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.
 */
void bstr_free(struct bstr *b);

/**
 * Return the length of the string
 * # Safety
 * x must be properly intialized: not NULL, dangling, or misaligned
 */
size_t bstr_len(const struct bstr *x);

/**
 * Return a pointer to the bstr payload
 * # Safety
 * x must be properly intialized: not NULL, dangling, or misaligned
 */
unsigned char *bstr_ptr(const struct bstr *x);

/**
 * Return the capacity of the string
 * # Safety
 * x must be properly intialized: not NULL, dangling, or misaligned
 */
size_t bstr_size(const struct bstr *x);

/**
 * Case-sensitive comparison of a bstring and a NUL-terminated string.
 * returns -1 if b is less than c
 *          0 if b is equal to c
 *          1 if b is greater than c
 * # Safety
 * b and c must be properly intialized: not NULL, dangling, or misaligned.
 * c must point to memory that contains a valid nul terminator byte at the end of the string
 */
int bstr_cmp_c(const struct bstr *b, const char *c);

/**
 * Case-indensitive comparison of a bstring and a NUL-terminated string.
 * returns -1 if b is less than c
 *          0 if b is equal to c
 *          1 if b is greater than c
 * # Safety
 * b and c must be properly intialized: not NULL, dangling, or misaligned.
 * c must point to memory that contains a valid nul terminator byte at the end of the string
 */
bool bstr_cmp_c_nocase(const struct bstr *b, const char *c);

/**
 * Create a new bstring by copying the provided NUL-terminated string
 * # Safety
 * cstr must be properly intialized: not NULL, dangling, or misaligned.
 * cstr must point to memory that contains a valid nul terminator byte at the end of the string
 */
struct bstr *bstr_dup_c(const char *cstr);

/**
 * Create a new NUL-terminated string out of the provided bstring. If NUL bytes
 * are contained in the bstring, each will be replaced with "\0" (two characters).
 * The caller is responsible to keep track of the allocated memory area and free
 * it once it is no longer needed.
 * returns The newly created NUL-terminated string, or NULL in case of memory
 *         allocation failure.
 * # Safety
 * b must be properly intialized and not dangling nor misaligned.
 */
char *bstr_util_strdup_to_c(const struct bstr *b);

/**
 * Creates a new configuration structure. Configuration structures created at
 * configuration time must not be changed afterwards in order to support lock-less
 * copying.
 */
struct htp_cfg_t *htp_config_create(void);

/**
 * Destroy a configuration structure.
 * # Safety
 * This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.
 */
void htp_config_destroy(struct htp_cfg_t *cfg);

/**
 * Registers a REQUEST_BODY_DATA callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_body_data(struct htp_cfg_t *cfg, DataExternalCallbackFn cbk_fn);

/**
 * Registers a REQUEST_COMPLETE callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_complete(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a REQUEST_HEADER_DATA callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_header_data(struct htp_cfg_t *cfg, DataExternalCallbackFn cbk_fn);

/**
 * Registers a REQUEST_LINE callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_line(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a tx create callback, which is invoked every time a new
 * request begins and before any parsing is done.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_tx_create(struct htp_cfg_t *cfg, TxCreateCallbackFn cbk_fn);

/**
 * Registers a tx destroy callback, which is invoked every time a tx is dropped
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_tx_destroy(struct htp_cfg_t *cfg, TxDestroyCallbackFn cbk_fn);

/**
 * Registers a REQUEST_START callback, which is invoked every time a new
 * request begins and before any parsing is done.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_start(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a HTP_REQUEST_TRAILER callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_trailer(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a REQUEST_TRAILER_DATA callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_request_trailer_data(struct htp_cfg_t *cfg, DataExternalCallbackFn cbk_fn);

/**
 * Registers a RESPONSE_BODY_DATA callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_response_body_data(struct htp_cfg_t *cfg, DataExternalCallbackFn cbk_fn);

/**
 * Registers a RESPONSE_COMPLETE callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_response_complete(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a RESPONSE_HEADER_DATA callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_response_header_data(struct htp_cfg_t *cfg, DataExternalCallbackFn cbk_fn);

/**
 * Registers a RESPONSE_START callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_response_start(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a RESPONSE_TRAILER callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_response_trailer(struct htp_cfg_t *cfg, TxExternalCallbackFn cbk_fn);

/**
 * Registers a RESPONSE_TRAILER_DATA callback.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_register_response_trailer_data(struct htp_cfg_t *cfg,
                                               DataExternalCallbackFn cbk_fn);

/**
 * Configures whether backslash characters are treated as path segment separators. They
 * are not on Unix systems, but are on Windows systems. If this setting is enabled, a path
 * such as "/one\two/three" will be converted to "/one/two/three".
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_backslash_convert_slashes(struct htp_cfg_t *cfg, int enabled);

/**
 * Sets the replacement character that will be used to in the lossy best-fit
 * mapping from multi-byte to single-byte streams. The question mark character
 * is used as the default replacement byte.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_bestfit_replacement_byte(struct htp_cfg_t *cfg, int b);

/**
 * Configures the maximum compression bomb size LibHTP will decompress.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_compression_bomb_limit(struct htp_cfg_t *cfg, size_t bomblimit);

/**
 * Configures the maximum compression time LibHTP will allow.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_compression_time_limit(struct htp_cfg_t *cfg, unsigned int timelimit);

/**
 * Configures whether input data will be converted to lowercase. Useful for handling servers with
 * case-insensitive filesystems.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_convert_lowercase(struct htp_cfg_t *cfg, int enabled);

/**
 * Configures the maximum size of the buffer LibHTP will use when all data is not available
 * in the current buffer (e.g., a very long header line that might span several packets). This
 * limit is controlled by the field_limit parameter.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_field_limit(struct htp_cfg_t *cfg, size_t field_limit);

/**
 * Configures the maximum memlimit LibHTP will pass to liblzma.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_lzma_memlimit(struct htp_cfg_t *cfg, size_t memlimit);

/**
 * Configures the maximum number of lzma layers to pass to the decompressor.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_lzma_layers(struct htp_cfg_t *cfg, int limit);

/**
 * Configures the maximum number of live transactions per connection
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_max_tx(struct htp_cfg_t *cfg, uint32_t limit);

/**
 * Configures the maximum number of headers in one transaction
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_number_headers_limit(struct htp_cfg_t *cfg, uint32_t limit);

/**
 * Configures how the server reacts to encoded NUL bytes. Some servers will stop at
 * at NUL, while some will respond with 400 or 404. When the termination option is not
 * used, the NUL byte will remain in the path.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_nul_encoded_terminates(struct htp_cfg_t *cfg, int enabled);

/**
 * Configures the handling of raw NUL bytes. If enabled, raw NUL terminates strings.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_nul_raw_terminates(struct htp_cfg_t *cfg, int enabled);

/**
 * Enable or disable request cookie parsing. Enabled by default.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_parse_request_cookies(struct htp_cfg_t *_cfg, int _parse_request_cookies);

/**
 * Configures whether consecutive path segment separators will be compressed. When enabled, a path
 * such as "/one//two" will be normalized to "/one/two". Backslash conversion and path segment separator
 * decoding are carried out before compression. For example, the path "/one\\/two\/%5cthree/%2f//four"
 * will be converted to "/one/two/three/four" (assuming all 3 options are enabled).
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_path_separators_compress(struct htp_cfg_t *cfg,
                                             int enabled);

/**
 * Configures whether plus characters are converted to spaces when decoding URL-encoded strings. This
 * is appropriate to do for parameters, but not for URLs. Only applies to contexts where decoding
 * is taking place.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_plusspace_decode(struct htp_cfg_t *cfg,
                                     int enabled);

/**
 * Configures whether encoded path segment separators will be decoded. Apache does not do
 * this by default, but IIS does. If enabled, a path such as "/one%2ftwo" will be normalized
 * to "/one/two". If the backslash_separators option is also enabled, encoded backslash
 * characters will be converted too (and subsequently normalized to forward slashes).
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_path_separators_decode(struct htp_cfg_t *cfg, int enabled);

/**
 * Configures whether request data is decompressed
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_request_decompression(struct htp_cfg_t *cfg, int enabled);

/**
 * Configures many layers of compression we try to decompress.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_decompression_layer_limit(struct htp_cfg_t *cfg, int limit);

/**
 * Enable or disable allowing spaces in URIs. Disabled by default.
 * # Safety
 * When calling this method the given cfg must be initialized or NULL.
 */
void htp_config_set_allow_space_uri(struct htp_cfg_t *cfg, bool allow_space);

/**
 * Configure desired server personality.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
enum HtpStatus htp_config_set_server_personality(struct htp_cfg_t *cfg,
                                                 enum HtpServerPersonality personality);

/**
 * Configures whether %u-encoded sequences are decoded. Such sequences
 * will be treated as invalid URL encoding if decoding is not desirable.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_u_encoding_decode(struct htp_cfg_t *cfg, int enabled);

/**
 * Configures how the server handles to invalid URL encoding.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_url_encoding_invalid_handling(struct htp_cfg_t *cfg,
                                                  enum HtpUrlEncodingHandling handling);

/**
 * Controls whether the data should be treated as UTF-8 and converted to a single-byte
 * stream using best-fit mapping.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_utf8_convert_bestfit(struct htp_cfg_t *cfg, int enabled);

/**
 * Configures whether to attempt to decode a double encoded query in the normalized uri
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_double_decode_normalized_query(struct htp_cfg_t *cfg, bool set);

/**
 * Configures whether to attempt to decode a double encoded path in the normalized uri
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_double_decode_normalized_path(struct htp_cfg_t *cfg, bool set);

/**
 * Configures whether to normalize URIs into a complete or partial form.
 * Pass `true` to use complete normalized URI or `false` to use partials.
 * # Safety
 * When calling this method, you have to ensure that cfg is either properly initialized or NULL
 */
void htp_config_set_normalized_uri_include_all(struct htp_cfg_t *cfg, bool set);

/**
 * Returns the request_data_counter
 * # Safety
 * When calling this method, you have to ensure that conn is either properly initialized or NULL
 */
uint64_t htp_conn_request_data_counter(const struct htp_conn_t *conn);

/**
 * Returns the response_data_counter
 * # Safety
 * When calling this method, you have to ensure that conn is either properly initialized or NULL
 */
uint64_t htp_conn_response_data_counter(const struct htp_conn_t *conn);

/**
 * Get the next logged message from the connection
 *
 * Returns the next log or NULL on error.
 * The caller must free this result with htp_log_free
 * # Safety
 * When calling this method, you have to ensure that conn is either properly initialized or NULL
 */
struct htp_log_t *htp_conn_next_log(const struct htp_conn_t *conn);

/**
 * Closes the connection associated with the supplied parser.
 *
 * timestamp is optional
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
void htp_connp_close(struct htp_connp_t *connp, const struct timeval *timestamp);

/**
 * Creates a new connection parser using the provided configuration or a default configuration if NULL provided.
 * Note the provided config will be copied into the created connection parser. Therefore, subsequent modification
 * to the original config will have no effect.
 *
 * Returns a new connection parser instance, or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
struct htp_connp_t *htp_connp_create(const struct htp_cfg_t *cfg);

/**
 * Destroys the connection parser, its data structures, as well
 * as the connection and its transactions.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
void htp_connp_destroy_all(struct htp_connp_t *connp);

/**
 * Returns the connection associated with the connection parser.
 *
 * Returns Connection instance, or NULL if one is not available.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
const struct htp_conn_t *htp_connp_connection(const struct htp_connp_t *connp);

/**
 * Retrieve the user data associated with this connection parser.
 * Returns user data, or NULL if there isn't any.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
void *htp_connp_user_data(const struct htp_connp_t *connp);

/**
 * Associate user data with the supplied parser.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
void htp_connp_set_user_data(struct htp_connp_t *connp, void *user_data);

/**
 * Opens connection.
 *
 * timestamp is optional
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
void htp_connp_open(struct htp_connp_t *connp,
                    const char *client_addr,
                    int client_port,
                    const char *server_addr,
                    int server_port,
                    const struct timeval *timestamp);

/**
 * Closes the connection associated with the supplied parser.
 *
 * timestamp is optional
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
void htp_connp_request_close(struct htp_connp_t *connp, const struct timeval *timestamp);

/**
 * Process a chunk of inbound client request data
 *
 * timestamp is optional
 * Returns HTP_STREAM_STATE_DATA, HTP_STREAM_STATE_ERROR or HTP_STREAM_STATE_DATA_OTHER (see QUICK_START).
 *         HTP_STREAM_STATE_CLOSED and HTP_STREAM_STATE_TUNNEL are also possible.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
enum HtpStreamState htp_connp_request_data(struct htp_connp_t *connp,
                                           const struct timeval *timestamp,
                                           const void *data,
                                           size_t len);

/**
 * Process a chunk of outbound (server or response) data.
 *
 * timestamp is optional.
 * Returns HTP_STREAM_STATE_OK on state change, HTP_STREAM_STATE_ERROR on error, or HTP_STREAM_STATE_DATA when more data is needed
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
enum HtpStreamState htp_connp_response_data(struct htp_connp_t *connp,
                                            const struct timeval *timestamp,
                                            const void *data,
                                            size_t len);

/**
 * Get the number of transactions processed on this connection.
 *
 * Returns the number of transactions or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
intptr_t htp_connp_tx_size(const struct htp_connp_t *connp);

/**
 * Get a transaction by its index for the iterator.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
struct htp_tx_t *htp_connp_tx_index(struct htp_connp_t *connp, uintptr_t index);

/**
 * Get a transaction.
 *
 * Returns the transaction or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
const struct htp_tx_t *htp_connp_tx(struct htp_connp_t *connp, uintptr_t tx_id);

/**
 * Retrieves the pointer to the active response transaction. In connection
 * parsing mode there can be many open transactions, and up to 2 active
 * transactions at any one time. This is due to HTTP pipelining. Can be NULL.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
const struct htp_tx_t *htp_connp_get_response_tx(struct htp_connp_t *connp);

/**
 * Retrieves the pointer to the active request transaction. In connection
 * parsing mode there can be many open transactions, and up to 2 active
 * transactions at any one time. This is due to HTTP pipelining. Call be NULL.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
const struct htp_tx_t *htp_connp_get_request_tx(struct htp_connp_t *connp);

/**
 * Returns the number of bytes consumed from the current data chunks so far or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
int64_t htp_connp_request_data_consumed(const struct htp_connp_t *connp);

/**
 * Returns the number of bytes consumed from the most recent outbound data chunk. Normally, an invocation
 * of htp_connp_response_data() will consume all data from the supplied buffer, but there are circumstances
 * where only partial consumption is possible. In such cases HTP_STREAM_DATA_OTHER will be returned.
 * Consumed bytes are no longer necessary, but the remainder of the buffer will be need to be saved
 * for later.
 * Returns the number of bytes consumed from the last data chunk sent for outbound processing
 * or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that connp is either properly initialized or NULL
 */
int64_t htp_connp_response_data_consumed(const struct htp_connp_t *connp);

/**
 * Get the first header value matching the key.
 *
 * headers: Header table.
 * ckey: Header name to match.
 *
 * Returns the header or NULL when not found or on error
 * # Safety
 * When calling this method, you have to ensure that headers is either properly initialized or NULL
 */
const struct htp_header_t *htp_headers_get(const struct htp_headers_t *headers, const char *ckey);

/**
 * Get the header at a given index.
 *
 * headers: Header table.
 * index: Index into the table.
 *
 * Returns the header or NULL when not found or on error
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
const struct htp_header_t *htp_headers_get_index(const struct htp_headers_t *headers,
                                                 uintptr_t index);

/**
 * Get the size of the headers table.
 *
 * headers: Headers table.
 *
 * Returns the size or -1 on error
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
intptr_t htp_headers_size(const struct htp_headers_t *headers);

/**
 * Get the name of a header.
 *
 * header: Header pointer.
 *
 * Returns the name or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
const struct bstr *htp_header_name(const struct htp_header_t *header);

/**
 * Get the name of a header as a ptr.
 *
 * header: Header pointer.
 *
 * Returns the pointer or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
const uint8_t *htp_header_name_ptr(const struct htp_header_t *header);

/**
 * Get the length of a header name.
 *
 * tx: Header pointer.
 *
 * Returns the length or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
intptr_t htp_header_name_len(const struct htp_header_t *header);

/**
 * Get the value of a header.
 *
 * tx: Header pointer.
 *
 * Returns the value or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
const struct bstr *htp_header_value(const struct htp_header_t *header);

/**
 * Get the value of a header as a ptr.
 *
 * tx: Header pointer.
 *
 * Returns the pointer or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
const uint8_t *htp_header_value_ptr(const struct htp_header_t *header);

/**
 * Get the length of a header value.
 *
 * tx: Header pointer.
 *
 * Returns the length or 0 on a NULL pointer.
 * # Safety
 * When calling this method, you have to ensure that header is either properly initialized or NULL
 */
uintptr_t htp_header_value_len(const struct htp_header_t *header);

/**
 * Get the log's message string
 *
 * Returns the log message as a cstring or NULL on error
 * The caller must free this result with htp_free_cstring
 * # Safety
 * When calling this method, you have to ensure that log is either properly initialized or NULL
 */
char *htp_log_message(const struct htp_log_t *log);

/**
 * Get a log's message code
 *
 * Returns a code or HTP_LOG_CODE_ERROR on error
 * # Safety
 * When calling this method, you have to ensure that log is either properly initialized or NULL
 */
enum HtpLogCode htp_log_code(const struct htp_log_t *log);

/**
 * Free log
 * # Safety
 * This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.
 */
void htp_log_free(struct htp_log_t *log);

/**
 * Destroys the supplied transaction.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
void htp_tx_destroy(struct htp_connp_t *connp, uintptr_t index);

/**
 * Get a transaction's normalized parsed uri.
 *
 * tx: Transaction pointer.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_normalized_uri(const struct htp_tx_t *tx);

/**
 * Returns the user data associated with this transaction or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
void *htp_tx_get_user_data(const struct htp_tx_t *tx);

/**
 * Get a transaction's request line.
 *
 * tx: Transaction pointer.
 *
 * Returns the request line or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_request_line(const struct htp_tx_t *tx);

/**
 * Get a transaction's request method.
 *
 * tx: Transaction pointer.
 *
 * Returns the request method or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_request_method(const struct htp_tx_t *tx);

/**
 * Get the transaction's request method number.
 *
 * tx: Transaction pointer.
 *
 * Returns the request method number or ERROR on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
enum HtpMethod htp_tx_request_method_number(const struct htp_tx_t *tx);

/**
 * Get a transaction's request uri.
 *
 * tx: Transaction pointer.
 *
 * Returns the request uri or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_request_uri(const struct htp_tx_t *tx);

/**
 * Get a transaction's request protocol.
 *
 * tx: Transaction pointer.
 *
 * Returns the protocol or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_request_protocol(const struct htp_tx_t *tx);

/**
 * Get a transaction's request protocol number.
 *
 * tx: Transaction pointer.
 *
 * Returns the protocol number or ERROR on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
enum HtpProtocol htp_tx_request_protocol_number(const struct htp_tx_t *tx);

/**
 * Get whether a transaction's protocol is version 0.9.
 *
 * tx: Transaction pointer.
 *
 * Returns 1 if the version is 0.9 or 0 otherwise. A NULL argument will
 * also result in a return value of 0.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
int32_t htp_tx_is_protocol_0_9(const struct htp_tx_t *tx);

/**
 * Get a transaction's parsed uri.
 *
 * tx: Transaction pointer.
 *
 * Returns the parsed uri or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct htp_uri_t *htp_tx_parsed_uri(const struct htp_tx_t *tx);

/**
 * Get a transaction's request headers.
 *
 * tx: Transaction pointer.
 *
 * Returns the request headers or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct htp_headers_t *htp_tx_request_headers(const struct htp_tx_t *tx);

/**
 * Get a transaction's request headers size.
 *
 * tx: Transaction pointer.
 *
 * Returns the size or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
intptr_t htp_tx_request_headers_size(const struct htp_tx_t *tx);

/**
 * Get the first request header value matching the key from a transaction.
 *
 * tx: Transaction pointer.
 * ckey: Header name to match.
 *
 * Returns the header or NULL when not found or on error
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct htp_header_t *htp_tx_request_header(const struct htp_tx_t *tx, const char *ckey);

/**
 * Get the request header at the given index.
 *
 * tx: Transaction pointer.
 * index: request header table index.
 *
 * Returns the header or NULL on error
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct htp_header_t *htp_tx_request_header_index(const struct htp_tx_t *tx, uintptr_t index);

/**
 * Get the transaction's request authentication type.
 *
 * tx: Transaction pointer.
 *
 * Returns the auth type or HTP_AUTH_ERROR on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
enum HtpAuthType htp_tx_request_auth_type(const struct htp_tx_t *tx);

/**
 * Get a transaction's request hostname.
 *
 * tx: Transaction pointer.
 *
 * Returns the request hostname or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_request_hostname(const struct htp_tx_t *tx);

/**
 * Get the transaction's request port number.
 *
 * tx: Transaction pointer.
 *
 * Returns the request port number or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
int32_t htp_tx_request_port_number(const struct htp_tx_t *tx);

/**
 * Get a transaction's request message length.
 *
 * tx: Transaction pointer.
 *
 * Returns the request message length or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
int64_t htp_tx_request_message_len(const struct htp_tx_t *tx);

/**
 * Get a transaction's response line.
 *
 * tx: Transaction pointer.
 *
 * Returns the response line or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_response_line(const struct htp_tx_t *tx);

/**
 * Get a transaction's response protocol.
 *
 * tx: Transaction pointer.
 *
 * Returns the response protocol or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_response_protocol(const struct htp_tx_t *tx);

/**
 * Get a transaction's response protocol number.
 *
 * tx: Transaction pointer.
 *
 * Returns the protocol number or ERROR on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
enum HtpProtocol htp_tx_response_protocol_number(const struct htp_tx_t *tx);

/**
 * Get the transaction's response status.
 *
 * tx: Transaction pointer.
 *
 * Returns the response status or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_response_status(const struct htp_tx_t *tx);

/**
 * Get the transaction's response status number.
 *
 * tx: Transaction pointer.
 *
 * Returns the response status number or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
int32_t htp_tx_response_status_number(const struct htp_tx_t *tx);

/**
 * Get a transaction's response message.
 *
 * tx: Transaction pointer.
 *
 * Returns the response message or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct bstr *htp_tx_response_message(const struct htp_tx_t *tx);

/**
 * Get a transaction's response headers.
 *
 * tx: Transaction pointer.
 *
 * Returns the response headers or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct htp_headers_t *htp_tx_response_headers(const struct htp_tx_t *tx);

/**
 * Get the first response header value matching the key from a transaction.
 *
 * tx: Transaction pointer.
 * ckey: Header name to match.
 *
 * Returns the header or NULL when not found or on error
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
const struct htp_header_t *htp_tx_response_header(const struct htp_tx_t *tx, const char *ckey);

/**
 * Get a transaction's response message length.
 *
 * tx: Transaction pointer.
 *
 * Returns the response message length or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
int64_t htp_tx_response_message_len(const struct htp_tx_t *tx);

/**
 * Get the transaction's bit flags.
 *
 * tx: Transaction pointer.
 *
 * Returns the flags represented as an integer or 0 if the flags are empty
 * or a NULL ptr is passed as an argument.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
uint64_t htp_tx_flags(const struct htp_tx_t *tx);

/**
 * Get the transaction's index.
 *
 * tx: Transaction pointer.
 *
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
uintptr_t htp_tx_index(const struct htp_tx_t *tx);

/**
 * Get the transaction's request progress.
 *
 * tx: Transaction pointer.
 *
 * Returns the progress or HTP_REQUEST_ERROR on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
enum HtpRequestProgress htp_tx_request_progress(const struct htp_tx_t *tx);

/**
 * Get the transaction's response progress.
 *
 * tx: Transaction pointer.
 *
 * Returns the progress or ERROR on error.
 * # Safety
 * When calling this method, you have to ensure that tx is either properly initialized or NULL
 */
enum HtpResponseProgress htp_tx_response_progress(const struct htp_tx_t *tx);

/**
 * Get the data's transaction.
 *
 * Returns the transaction or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that data is either properly initialized or NULL
 */
const struct htp_tx_t *htp_tx_data_tx(const struct htp_tx_data_t *data);

/**
 * Get the data pointer.
 *
 * Returns the data or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that data is either properly initialized or NULL
 */
const uint8_t *htp_tx_data_data(const struct htp_tx_data_t *data);

/**
 * Get the length of the data.
 *
 * Returns the length or -1 on error.
 * # Safety
 * When calling this method, you have to ensure that data is either properly initialized or NULL
 */
intptr_t htp_tx_data_len(const struct htp_tx_data_t *data);

/**
 * Get whether this data is empty.
 *
 * Returns true if data is NULL or zero-length.
 * # Safety
 * When calling this method, you have to ensure that data is either properly initialized or NULL
 */
bool htp_tx_data_is_empty(const struct htp_tx_data_t *data);

/**
 * Get the hostname of a uri.
 *
 * Returns the hostname for uri or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that uri is either properly initialized or NULL
 */
const struct bstr *htp_uri_hostname(const struct htp_uri_t *uri);

/**
 * Get the path of a uri.
 *
 * Returns the path for uri or NULL on error.
 * # Safety
 * When calling this method, you have to ensure that uri is either properly initialized or NULL
 */
const struct bstr *htp_uri_path(const struct htp_uri_t *uri);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus

#endif  /* _HTP_H */
