Documentation
#ifndef TURTLS_H
#define TURTLS_H

/* This file is autogenerated by cbindgen. Don't modify this manually. */

#include <stddef.h>
#include <stdint.h>


/**
 * The ECDSA signature algoritm over the secp256r1 (NIST-P 256) curve.
 */
#define TURTLS_ECDSA_SECP256R1 1

/**
 * Key exchange via ECDH on the secp256r1 (NIST-P 256) curve.
 */
#define TURTLS_SECP256R1 1

/**
 * TLS error reporting.
 */
enum TurtlsAlert {
    /**
     * The connection is being closed
     */
    TURTLS_ALERT_CLOSE_NOTIFY = 0,
    /**
     * An unexpected message was received.
     */
    TURTLS_ALERT_UNEXPECTED_MESSAGE = 10,
    /**
     * Record authentication failed.
     */
    TURTLS_ALERT_BAD_RECORD_MAC = 20,
    /**
     * The record was longer than the maximum record size.
     */
    TURTLS_ALERT_RECORD_OVERFLOW = 22,
    /**
     * The handshake failed for an unspecified reason.
     */
    TURTLS_ALERT_HANDSHAKE_FAILURE = 40,
    /**
     * The provided certificate was invalid.
     */
    TURTLS_ALERT_BAD_CERT = 42,
    /**
     * The provided certificated is unsupported.
     */
    TURTLS_ALERT_UNSUPPORTED_CERT = 43,
    /**
     * The provided certificate has been revoked.
     */
    TURTLS_ALERT_CERT_REVOKED = 44,
    /**
     * The provided certificate has expired.
     */
    TURTLS_ALERT_CERT_EXPIRED = 45,
    /**
     * There was an unspecified error processing the certificate.
     */
    TURTLS_ALERT_CERT_UNKNOWN = 46,
    /**
     * A parameter was invalid (e.g. an elliptic curve point wasn't on the curve).
     */
    TURTLS_ALERT_ILLEGAL_PARAM = 47,
    /**
     * The provided certificate authority is unrecognized.
     */
    TURTLS_ALERT_UNKNOWN_CA = 48,
    /**
     * The sender decided not to proceed with the handshake.
     */
    TURTLS_ALERT_ACCESS_DENIED = 49,
    /**
     * There was an error decoding a message.
     */
    TURTLS_ALERT_DECODE_ERROR = 50,
    /**
     * There was an error decrypting a message.
     */
    TURTLS_ALERT_DECRYPT_ERORR = 51,
    /**
     * The attempted protocol version is unsupported.
     */
    TURTLS_ALERT_PROTOCOL_VERSION = 70,
    /**
     * The server requires more-secure parameters than those provided by the client.
     */
    TURTLS_ALERT_INSUFFICIENT_SECURITY = 71,
    /**
     * An unrelated internal error has occured.
     */
    TURTLS_ALERT_INTERNAL_ERROR = 80,
    /**
     * An inappropriate downgrade was attempted.
     */
    TURTLS_ALERT_INAPPROPRIATE_FALLBACK = 86,
    /**
     * The user interupted the handshake.
     */
    TURTLS_ALERT_USER_CANCELLED = 90,
    /**
     * A required extension is missing.
     */
    TURTLS_ALERT_MISSING_EXTENSION = 109,
    /**
     * An extension was sent that isn't supported.
     */
    TURTLS_ALERT_UNSUPPORTED_EXTENSION = 110,
    /**
     * The provided server name is unrecognized.
     */
    TURTLS_ALERT_UNRECOGNIZED_NAME = 112,
    /**
     * An invalid or unacceptable OCSP was provided.
     */
    TURTLS_ALERT_BAD_CERT_STATUS_RESPONSE = 113,
    /**
     * PSK is desired but no acceptable PSK identity is sent by the client.
     */
    TURTLS_ALERT_UNKNOWN_PSK_IDENTITY = 115,
    /**
     * A certificate is required.
     */
    TURTLS_ALERT_CERT_REQUIRED = 116,
    /**
     * No application protocol was provided.
     */
    TURTLS_ALERT_NO_APP_PROTOCOL = 120,
};

/**
 * The result of a TLS operation.
 *
 * All values other than `None` represent an error.
 */
enum TurtlsError {
    /**
     * There was an error in the TLS protocol.
     *
     * The specific error can be accessed via `turtls_get_tls_error`.
     */
    TURTLS_ERROR_TLS,
    /**
     * The peer indicated an error in the TLS protocol.
     *
     * The specific error can be accessed via `turtls_get_tls_error`.
     */
    TURTLS_ERROR_TLS_PEER,
    /**
     * There was an error generating a random number.
     */
    TURTLS_ERROR_RNG,
    /**
     * A read operation failed.
     *
     * This error IS resumable if the failure is recoverable.
     */
    TURTLS_ERROR_WANT_READ,
    /**
     * A write operation failed.
     *
     * This error IS resumable if the failure is recoverable.
     */
    TURTLS_ERROR_WANT_WRITE,
    /**
     * The randomly-generated private key was zero.
     */
    TURTLS_ERROR_PRIV_KEY_IS_ZERO,
    /**
     * One or more required extensions are missing.
     */
    TURTLS_ERROR_MISSING_EXTENSIONS,
};

/**
 * A TLS connection object.
 *
 * An instance may be reused between multiple consecutive connections.
 */
struct TurtlsConn;

/**
 * The extensions to use in the handshake.
 *
 * Refer to each extension's individual documentation for specific usage information.
 */
struct TurtlsExts {
    /**
     * The server name to send to the server or to expect from the client.
     *
     * If `server_name` is `null`, the extension won't be sent.
     *
     * `server_name` MUST be nul-terminated
     */
    const char *server_name;
    /**
     * The signature algorithms to support.
     */
    uint16_t sig_algs;
    /**
     * The methods to use for key exchange.
     */
    uint16_t sup_groups;
    /**
     * A list of supported nul-terminated application protocols.
     *
     * Each name is encoded as a one-byte length and then the name.
     *
     * If `app_protos` is null, the extension isn't sent.
     *
     * A URL containing a list of protocol names is provided below.
     * For example, HTTP/2 over TLS is "h2".
     *
     * <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids>
     */
    const char *app_protos;
    /**
     * The number of supported application protocols.
     *
     * If `app_proto_count` is null, the extension isn't sent.
     */
    size_t app_protos_len;
};

/**
 * The supported ciphersuites.
 */
typedef uint8_t TurtlsCipherList;
/**
 * ChaCha20 Poly1305 with SHA-256.
 *
 * This is a good option. You should probably leave it enabled.
 */
#define TurtlsCipherList_TURTLS_CHA_CHA_POLY1305_SHA256 1
/**
 * AES-128 GCM with SHA-256.
 *
 * Hardware instructions are *not* yet supported.
 *
 * This is a good option. You should probably leave it enabled.
 */
#define TurtlsCipherList_TURTLS_AES_128_GCM_SHA256 2

/**
 * Configure `TurtlsConn` connections.
 *
 * This struct can be accessed via `turtls_get_config`.
 *
 * Most configuration is done via bitflags. Constants are provided for each flag.
 */
struct TurtlsConfig {
    /**
     * The extensions to use.
     */
    struct TurtlsExts extensions;
    /**
     * The cipher suites to use.
     */
    TurtlsCipherList cipher_suites;
};

/**
 * The functions to use to perform IO.
 *
 * This includes reading, writing, and closing the connection.
 */
struct TurtlsIo {
    /**
     * A write function.
     *
     * `write_fn` must return the number of bytes written. To indicate an error, it must return a
     * value less than `1`.
     *
     * `buf`: the buffer to write.
     * `amt`: the number of bytes to write.
     * `ctx`: contextual data.
     */
    ptrdiff_t (*write_fn)(const void *buf, size_t amt, const void *ctx);
    /**
     * A read function.
     *
     * `read_fn` must return the number of bytes read. To indicate an error, it must return a
     * value less than `1`.
     *
     * `buf`: the buffer to read to.
     * `amt`: the maximum number of bytes to read.
     * `ctx`: contextual data.
     */
    ptrdiff_t (*read_fn)(void *buf, size_t amt, const void *ctx);
    /**
     * A function to close the connection.
     *
     * `ctx`: contextual data.
     */
    void (*close_fn)(const void *ctx);
    /**
     * Contextual data.
     *
     * This can simply be a file descriptor, or it can be something more complex. For example, it
     * could store both a read and a write file descriptor, error values, and even mutable state.
     *
     * Lifetime: this pointer must be valid for the duration of the connection.
     */
    void *ctx;
};

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

/**
 * Returns a pointer to name of the negotiated application protocol.
 *
 * The string is nul-terminated.
 *
 * # Safety
 * `tls_conn` must be valid.
 *
 * Lifetime: the returned pointer is valid for the entire lifetime of `connection`. If a new
 * connection is created with the same allocation, pointer is still valid and will point to the
 * new application protocol.
 */
const char *turtls_app_proto(const struct TurtlsConn *tls_conn);

/**
 * Alerts the peer and closes the connection.
 *
 * # Safety:
 * `tls_conn` must be valid.
 */
void turtls_close(struct TurtlsConn *tls_conn);

/**
 * Performs a TLS handshake with a server, returning the connection status.
 *
 * If any error is returned, the connection is automatically closed.
 *
 * # Safety:
 * `tls_conn` must be valid.
 */
int turtls_connect(struct TurtlsConn *tls_conn);

/**
 * Frees a connection object.
 *
 * Once this function is called, `tls_conn` is no longer valid.
 *
 * # Safety:
 * `tls_conn` must be allocated by `turtls_new`.
 */
void turtls_free(struct TurtlsConn *tls_conn);

/**
 * Returns a pointer to the configuration struct `tls_conn`.
 */
struct TurtlsConfig *turtls_get_config(struct TurtlsConn *tls_conn);

/**
 * Returns the last error to occur.
 *
 * # Safety
 * `tls_conn` must be valid
 */
enum TurtlsError turtls_get_error(const struct TurtlsConn *tls_conn);

/**
 * Returns last TLS error to occur.
 *
 * # Safety
 * `tls_conn` must be valid
 */
enum TurtlsAlert turtls_get_tls_error(const struct TurtlsConn *tls_conn);

/**
 * Creates a new connection object.
 *
 * The object must be freed by `turtls_free` to avoid memory leakage.
 *
 * Lifetime: All pointers contained in `io` must be valid for the lifespan of the connection
 * object.
 */
struct TurtlsConn *turtls_new(struct TurtlsIo io);

/**
 * Returns a string representation of the alert.
 *
 * Lifetime: the returned string has a static lifetime and as such can be used for the duration of
 * the program.
 */
const char *turtls_stringify_alert(enum TurtlsAlert alert);

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

#endif  /* TURTLS_H */