Loading...
Searching...
No Matches
Functions | Variables
imquic.c File Reference

imquic public interface More...

#include "imquic/imquic.h"
#include "internal/configuration.h"
#include "internal/quic.h"
#include "internal/loop.h"
#include "internal/crypto.h"
#include "internal/buffer.h"
#include "internal/utils.h"
#include "internal/listmap.h"
#include "internal/version.h"
#include "internal/http3.h"
#include "internal/moq.h"
#include "internal/roq.h"
Include dependency graph for imquic.c:

Functions

int imquic_init (const char *secrets_log)
 Initialize the imquic library.
 
void imquic_deinit (void)
 Uninitialize the imquic library.
 
uint32_t imquic_get_version (void)
 Get the current version of the library as a number.
 
int imquic_get_version_major (void)
 Get the current major version of the library as a number.
 
int imquic_get_version_minor (void)
 Get the current minor version of the library as a number.
 
int imquic_get_version_patch (void)
 Get the current patch version of the library as a number.
 
const char * imquic_get_version_release (void)
 Get the current release type of the library as a string.
 
const char * imquic_get_version_string (void)
 Get the current version of the library as a string.
 
const char * imquic_get_version_string_full (void)
 Get the current version of the library, including release type, as a string.
 
const char * imquic_get_build_time (void)
 Get info on when this shared object was built.
 
const char * imquic_get_build_sha (void)
 Get info on the git commit was compiled in this build.
 
void imquic_set_log_level (int level)
 Set the log level for the library.
 
void imquic_set_lock_debugging (gboolean enabled)
 Enable or disable lock/mutex debugging.
 
void imquic_set_refcount_debugging (gboolean enabled)
 Enable or disable debugging of reference counters.
 
const char * imquic_config_str (imquic_config type)
 Helper function to serialize to string the name of a imquic_config property.
 
imquic_serverimquic_create_server (const char *name,...)
 Method to create a new QUIC server, using variable arguments to dictate what the server should do (e.g., port to bind to, ALPN, etc.). Variable arguments are in the form of a sequence of name-value started with a IMQUIC_CONFIG_INIT and ended by a IMQUIC_CONFIG_DONE , e.g.:
 
imquic_clientimquic_create_client (const char *name,...)
 Method to create a new QUIC client, using variable arguments to dictate what the client should do (e.g., address to connect to, ALPN, etc.). Variable arguments are in the form of a sequence of name-value started with a IMQUIC_CONFIG_INIT and ended by a IMQUIC_CONFIG_DONE , e.g.:
 
const char * imquic_get_endpoint_name (imquic_endpoint *endpoint)
 Helper function to get the endpoint name of a local client or server.
 
gboolean imquic_is_endpoint_server (imquic_endpoint *endpoint)
 Helper function to check whether a local endpoint is a server.
 
const char * imquic_get_endpoint_alpn (imquic_endpoint *endpoint)
 Helper function to get the ALPN a local client or server is configured to negotiate.
 
const char * imquic_get_endpoint_subprotocol (imquic_endpoint *endpoint)
 Helper function to get the WebTransport protocol a local client or server is configured to negotiate.
 
uint16_t imquic_get_endpoint_port (imquic_endpoint *endpoint)
 Helper function to get the local port a client or server is bound to.
 
void imquic_start_endpoint (imquic_endpoint *endpoint)
 Start a QUIC stack previously created with imquic_create_server or imquic_create_client. In case of a server, it will start listening for incoming connections; in case of a client, it will attempt to connect to the provided remote address.
 
void imquic_shutdown_endpoint (imquic_endpoint *endpoint)
 Shutdown a previously started QUIC endpoint (client or server) In case of a server, it will terminate all client connections it's handling, and stop accepting new ones; in case of a client, it will terminate the active connection, if any.
 
void imquic_set_new_connection_cb (imquic_endpoint *endpoint, void(*new_connection)(imquic_connection *conn, void *user_data))
 Configure the callback function to be notified about new connections on the configured endpoint. For a server, it will be triggered any time a client successfully connects to the server; for a client, it will be triggered when the client successfully connects to the server.
 
void imquic_set_stream_incoming_cb (imquic_endpoint *endpoint, void(*stream_incoming)(imquic_connection *conn, uint64_t stream_id, uint8_t *bytes, uint64_t offset, uint64_t length, gboolean complete))
 Configure the callback function to be notified about incoming STREAM data on an existing connection handled by this endpoint.
 
void imquic_set_datagram_incoming_cb (imquic_endpoint *endpoint, void(*datagram_incoming)(imquic_connection *conn, uint8_t *bytes, uint64_t length))
 Configure the callback function to be notified about incoming DATAGRAM data on an existing connection handled by this endpoint.
 
void imquic_set_connection_gone_cb (imquic_endpoint *endpoint, void(*connection_gone)(imquic_connection *conn))
 Configure the callback function to be notified when an existing connection handled by this endpoint has been closed/shut down.
 
int imquic_send_on_stream (imquic_connection *conn, uint64_t stream_id, uint8_t *bytes, uint64_t offset, uint64_t length, gboolean complete)
 Helper method to send data on a QUIC STREAM.
 
int imquic_send_on_datagram (imquic_connection *conn, uint8_t *bytes, uint64_t length)
 Helper method to send data on a QUIC DATAGRAM.
 
const char * imquic_get_connection_alpn (imquic_connection *conn)
 Helper function to get the ALPN of a connection.
 
const char * imquic_get_connection_name (imquic_connection *conn)
 Helper function to get the display name of a connection.
 
int imquic_new_stream_id (imquic_connection *conn, gboolean bidirectional, uint64_t *stream_id)
 Helper method to ask for the next usable locally originated stream ID on this connection.
 
void imquic_close_connection (imquic_connection *conn, uint64_t error, const char *reason)
 Helper method to close a QUIC connection.
 
void imquic_connection_ref (imquic_connection *conn)
 Increase a reference to a imquic_connection instance.
 
void imquic_connection_unref (imquic_connection *conn)
 Decrease a reference to a imquic_connection instance.
 
void imquic_stream_id_parse (uint64_t stream_id, uint64_t *id, gboolean *client_initiated, gboolean *bidirectional)
 Parse a QUIC stream ID to its actual ID and its other properties.
 
uint64_t imquic_stream_id_build (uint64_t id, gboolean client_initiated, gboolean bidirectional)
 Build a QUIC stream ID out of its actual ID and its other properties.
 
uint64_t imquic_varint_read (uint8_t *bytes, size_t blen, uint8_t *length)
 Read a variable size integer from a buffer.
 
uint8_t imquic_varint_write (uint64_t number, uint8_t *bytes, size_t blen)
 Write a variable size integer to a buffer.
 
uint64_t imquic_uint64_random (void)
 Helper to generate random 64 bit unsigned integers.
 
uint64_t * imquic_uint64_dup (uint64_t num)
 Helper to generate an allocated copy of a uint64_t number.
 

Variables

int imquic_log_level = IMQUIC_LOG_VERB
 
gboolean imquic_log_timestamps = FALSE
 
gboolean imquic_log_colors = TRUE
 
gboolean imquic_lock_debug = FALSE
 
gboolean imquic_refcount_debug = FALSE
 
volatile int initialized = IMQUIC_NOT_INITIALIZED
 

Detailed Description

imquic public interface

Author
Lorenzo Miniero loren.nosp@m.zo@m.nosp@m.eetec.nosp@m.ho.c.nosp@m.om

Public interface to the imquic library. This is where public functions are callbacks to interact with the library are defined.

Function Documentation

◆ imquic_close_connection()

void imquic_close_connection ( imquic_connection * conn,
uint64_t error,
const char * reason )

Helper method to close a QUIC connection.

Note
Closing a server connection will keep the server alive, without impacting other connections to the same server and waiting for more connections. Closing a client connection will make that client instance unusable from that point forward.
Parameters
[in]connThe imquic_connection to close
[in]errorThe application error code to send, if any
[in]reasonA string description of why the connection was closed, if any

◆ imquic_config_str()

const char * imquic_config_str ( imquic_config type)

Helper function to serialize to string the name of a imquic_config property.

Parameters
typeThe imquic_config property
Returns
The type name as a string, if valid, or NULL otherwise

◆ imquic_connection_ref()

void imquic_connection_ref ( imquic_connection * conn)

Increase a reference to a imquic_connection instance.

Note
This should be used at least once, the first time the library notifies you about a new connection, so that the library knows you'll be managing it. Other references can be added/removed contextually.
Parameters
connThe imquic_connection instance to increase a reference for

◆ imquic_connection_unref()

void imquic_connection_unref ( imquic_connection * conn)

Decrease a reference to a imquic_connection instance.

Note
As an application, you should decrease all references you previously increased. The last reference should be decreased only when you know you won't need the connection anymore (e.g., in the callback the library invokes to notify you the connection is over).
Parameters
connThe imquic_connection instance to decrease a reference for

◆ imquic_create_client()

imquic_client * imquic_create_client ( const char * name,
... )

Method to create a new QUIC client, using variable arguments to dictate what the client should do (e.g., address to connect to, ALPN, etc.). Variable arguments are in the form of a sequence of name-value started with a IMQUIC_CONFIG_INIT and ended by a IMQUIC_CONFIG_DONE , e.g.:

       imquic_client *client = imquic_create_client("echo-client",
        IMQUIC_CONFIG_INIT,
        IMQUIC_CONFIG_TLS_CERT, cert_pem,
        IMQUIC_CONFIG_TLS_KEY, cert_key,
        IMQUIC_CONFIG_TLS_PASSWORD, cert_pwd,
        IMQUIC_CONFIG_REMOTE_HOST, "127.0.0.1",
        IMQUIC_CONFIG_REMOTE_PORT, 9000,
        IMQUIC_CONFIG_ALPN, "doq",
        IMQUIC_CONFIG_DONE, NULL);

to create a QUIC client advertising the "doq" (DNS Over QUIC) ALPN. Notice that this will only create the resource, but not actually start it: before doing that, you'll need to configure the callbacks for the events you're interested in, and then use imquic_start_endpoint to start the QUIC client (which will attempt a connection).

Note
This creates just the QUIC (or WebTransport) stack, to negotiate the provided ALPN, but all application details are up to you. If you want imquic to handle a protocol natively for you, you'll need to use a different creator, like imquic_create_moq_server for MoQ or imquic_create_roq_server for RoQ.
Parameters
[in]nameThe endpoint name (if NULL, a default value will be set)
Returns
A pointer to a imquic_server object, if successful, NULL otherwise

◆ imquic_create_server()

imquic_server * imquic_create_server ( const char * name,
... )

Method to create a new QUIC server, using variable arguments to dictate what the server should do (e.g., port to bind to, ALPN, etc.). Variable arguments are in the form of a sequence of name-value started with a IMQUIC_CONFIG_INIT and ended by a IMQUIC_CONFIG_DONE , e.g.:

       imquic_server *server = imquic_create_server("echo-server",
        IMQUIC_CONFIG_INIT,
        IMQUIC_CONFIG_TLS_CERT, cert_pem,
        IMQUIC_CONFIG_TLS_KEY, cert_key,
        IMQUIC_CONFIG_TLS_PASSWORD, cert_pwd,
        IMQUIC_CONFIG_LOCAL_PORT, 9000,
        IMQUIC_CONFIG_ALPN, "doq",
        IMQUIC_CONFIG_DONE, NULL);

to create a QUIC server advertising the "doq" (DNS Over QUIC) ALPN. Notice that this will only create the resource, but not actually start it: before doing that, you'll need to configure the callbacks for the events you're interested in, and then use imquic_start_endpoint to start the QUIC server (which will wait for incoming connections).

Note
This creates just the QUIC (or WebTransport) stack, to negotiate the provided ALPN, but all application details are up to you. If you want imquic to handle a protocol natively for you, you'll need to use a different creator, like imquic_create_moq_server for MoQ or imquic_create_roq_server for RoQ.
Parameters
[in]nameThe endpoint name (if NULL, a default value will be set)
Returns
A pointer to a imquic_server object, if successful, NULL otherwise

◆ imquic_deinit()

void imquic_deinit ( void )

Uninitialize the imquic library.

◆ imquic_get_build_sha()

const char * imquic_get_build_sha ( void )

Get info on the git commit was compiled in this build.

Returns
A string description of the git commit

◆ imquic_get_build_time()

const char * imquic_get_build_time ( void )

Get info on when this shared object was built.

Returns
A string description of the build time

◆ imquic_get_connection_alpn()

const char * imquic_get_connection_alpn ( imquic_connection * conn)

Helper function to get the ALPN of a connection.

Parameters
connThe imquic_connection to query
Returns
The ALPN, if successful, or NULL otherwise

◆ imquic_get_connection_name()

const char * imquic_get_connection_name ( imquic_connection * conn)

Helper function to get the display name of a connection.

Note
The display name is the concatenation of the the endpoint name, a slash character, and a monotonically increasing identifier.
Parameters
connThe imquic_connection to query
Returns
The display name, if successful, or NULL otherwise

◆ imquic_get_endpoint_alpn()

const char * imquic_get_endpoint_alpn ( imquic_endpoint * endpoint)

Helper function to get the ALPN a local client or server is configured to negotiate.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to query
Returns
The ALPN, if successful, or NULL otherwise

◆ imquic_get_endpoint_name()

const char * imquic_get_endpoint_name ( imquic_endpoint * endpoint)

Helper function to get the endpoint name of a local client or server.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to query
Returns
The endpoint name, if successful, or NULL otherwise

◆ imquic_get_endpoint_port()

uint16_t imquic_get_endpoint_port ( imquic_endpoint * endpoint)

Helper function to get the local port a client or server is bound to.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to query
Returns
The local port number

◆ imquic_get_endpoint_subprotocol()

const char * imquic_get_endpoint_subprotocol ( imquic_endpoint * endpoint)

Helper function to get the WebTransport protocol a local client or server is configured to negotiate.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to query
Returns
The subprotocol, if successful, or NULL otherwise

◆ imquic_get_version()

uint32_t imquic_get_version ( void )

Get the current version of the library as a number.

Note
This is computed by shifting major and minor version numbers by 24 and 16 bits respectively, while the patch is left as is
Returns
A numeric version of the library

◆ imquic_get_version_major()

int imquic_get_version_major ( void )

Get the current major version of the library as a number.

Returns
The major version number of the library

◆ imquic_get_version_minor()

int imquic_get_version_minor ( void )

Get the current minor version of the library as a number.

Returns
The minor version number of the library

◆ imquic_get_version_patch()

int imquic_get_version_patch ( void )

Get the current patch version of the library as a number.

Returns
The patch version number of the library

◆ imquic_get_version_release()

const char * imquic_get_version_release ( void )

Get the current release type of the library as a string.

Note
We use this to mark versions as, e.g., alpha, dev or stable
Returns
A string release type of the library

◆ imquic_get_version_string()

const char * imquic_get_version_string ( void )

Get the current version of the library as a string.

Returns
A string version of the library

◆ imquic_get_version_string_full()

const char * imquic_get_version_string_full ( void )

Get the current version of the library, including release type, as a string.

Returns
A string full version of the library

◆ imquic_init()

int imquic_init ( const char * secrets_log)

Initialize the imquic library.

Note
Must only be called once
Parameters
secrets_logFile to use to store QUIC secret, e.g., for Wireshark debugging (see SSLKEYLOGFILE)
Returns
0 in case of success, a negative integer otherwise

◆ imquic_is_endpoint_server()

gboolean imquic_is_endpoint_server ( imquic_endpoint * endpoint)

Helper function to check whether a local endpoint is a server.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to query
Returns
TRUE if the endpoint is a server, or FALSE otherwise

◆ imquic_new_stream_id()

int imquic_new_stream_id ( imquic_connection * conn,
gboolean bidirectional,
uint64_t * stream_id )

Helper method to ask for the next usable locally originated stream ID on this connection.

Parameters
[in]connThe imquic_connection to query
[in]bidirectionalWhether the new stream should be bidirectional
[out]stream_idPointer where the new stream ID will be provided
Returns
0 if successful, a negative integer otherwise

◆ imquic_send_on_datagram()

int imquic_send_on_datagram ( imquic_connection * conn,
uint8_t * bytes,
uint64_t length )

Helper method to send data on a QUIC DATAGRAM.

Note
Datagrams support must have been negotiated on the connection. Notice that this method will queue the data for delivery, but not send it right away. The event loop will take care of that internally.
Parameters
[in]connThe imquic_connection to send data on
[in]bytesBuffer containing the data to send
[in]lengthSize of the buffer of data
Returns
0 if successful, a negative integer otherwise

◆ imquic_send_on_stream()

int imquic_send_on_stream ( imquic_connection * conn,
uint64_t stream_id,
uint8_t * bytes,
uint64_t offset,
uint64_t length,
gboolean complete )

Helper method to send data on a QUIC STREAM.

Note
The stream ID must already be known by the stack, either because created by the peer, or previously created via imquic_new_stream_id. Notice that this method will queue the data for delivery, but not send it right away. The event loop will take care of that internally.
Parameters
[in]connThe imquic_connection to send data on
[in]stream_idThe QUIC stream to use for sending data
[in]bytesBuffer containing the data to send
[in]offsetOffset value to put in the outgoing STREAM fragment
[in]lengthSize of the buffer of data
[in]completeWhether this (offset+length) is the end of the STREAM data
Returns
0 if successful, a negative integer otherwise

◆ imquic_set_connection_gone_cb()

void imquic_set_connection_gone_cb ( imquic_endpoint * endpoint,
void(*)(imquic_connection *conn) connection_gone )

Configure the callback function to be notified when an existing connection handled by this endpoint has been closed/shut down.

Note
This is a good place to release the last reference to the connection
Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to configure
connection_gonePointer to the function that will be invoked when a connection is gone

◆ imquic_set_datagram_incoming_cb()

void imquic_set_datagram_incoming_cb ( imquic_endpoint * endpoint,
void(*)(imquic_connection *conn, uint8_t *bytes, uint64_t length) datagram_incoming )

Configure the callback function to be notified about incoming DATAGRAM data on an existing connection handled by this endpoint.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to configure
datagram_incomingPointer to the function that will be invoked on the new DATAGRAM data

◆ imquic_set_lock_debugging()

void imquic_set_lock_debugging ( gboolean enabled)

Enable or disable lock/mutex debugging.

Parameters
enabledWhether debugging should now be enabled

◆ imquic_set_log_level()

void imquic_set_log_level ( int level)

Set the log level for the library.

Note
See debug.h for valid levels. The default is IMQUIC_LOG_VERB (5)
Parameters
levelDebugging level to use

◆ imquic_set_new_connection_cb()

void imquic_set_new_connection_cb ( imquic_endpoint * endpoint,
void(*)(imquic_connection *conn, void *user_data) new_connection )

Configure the callback function to be notified about new connections on the configured endpoint. For a server, it will be triggered any time a client successfully connects to the server; for a client, it will be triggered when the client successfully connects to the server.

Note
This is a good place to obtain the first reference to a connection
Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to configure
new_connectionPointer to the function that will be invoked on the new connection

◆ imquic_set_refcount_debugging()

void imquic_set_refcount_debugging ( gboolean enabled)

Enable or disable debugging of reference counters.

Parameters
enabledWhether debugging should now be enabled

◆ imquic_set_stream_incoming_cb()

void imquic_set_stream_incoming_cb ( imquic_endpoint * endpoint,
void(*)(imquic_connection *conn, uint64_t stream_id, uint8_t *bytes, uint64_t offset, uint64_t length, gboolean complete) stream_incoming )

Configure the callback function to be notified about incoming STREAM data on an existing connection handled by this endpoint.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to configure
stream_incomingPointer to the function that will be invoked on the new STREAM data

◆ imquic_shutdown_endpoint()

void imquic_shutdown_endpoint ( imquic_endpoint * endpoint)

Shutdown a previously started QUIC endpoint (client or server) In case of a server, it will terminate all client connections it's handling, and stop accepting new ones; in case of a client, it will terminate the active connection, if any.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to shutdown

◆ imquic_start_endpoint()

void imquic_start_endpoint ( imquic_endpoint * endpoint)

Start a QUIC stack previously created with imquic_create_server or imquic_create_client. In case of a server, it will start listening for incoming connections; in case of a client, it will attempt to connect to the provided remote address.

Parameters
endpointThe imquic_endpoint (imquic_server or imquic_client) to start

◆ imquic_stream_id_build()

uint64_t imquic_stream_id_build ( uint64_t id,
gboolean client_initiated,
gboolean bidirectional )

Build a QUIC stream ID out of its actual ID and its other properties.

Parameters
[in]idThe actual client/server uni/bidirectional ID
[in]client_initiatedWhether this stream is client initiated
[in]bidirectionalWhether this stream is bidirectional
Returns
The QUIC stream ID

◆ imquic_stream_id_parse()

void imquic_stream_id_parse ( uint64_t stream_id,
uint64_t * id,
gboolean * client_initiated,
gboolean * bidirectional )

Parse a QUIC stream ID to its actual ID and its other properties.

Parameters
[in]stream_idThe QUIC stream ID to parse
[out]idThe actual client/server uni/bidirectional ID
[out]client_initiatedWhether this stream is client initiated
[out]bidirectionalWhether this stream is bidirectional

◆ imquic_uint64_dup()

uint64_t * imquic_uint64_dup ( uint64_t num)

Helper to generate an allocated copy of a uint64_t number.

Note
While apparently silly, this is needed in order to make sure uint64_t values used as keys in GHashTable operations are not lost: using temporary uint64_t numbers in a g_hash_table_insert, for instance, will cause the key to contain garbage as soon as the temporary variable is lost, and all opererations on the key to fail
Parameters
numThe uint64_t number to duplicate
Returns
A pointer to a uint64_t number, if successful, NULL otherwise

◆ imquic_uint64_random()

uint64_t imquic_uint64_random ( void )

Helper to generate random 64 bit unsigned integers.

Note
This will fall back to a non-cryptographically safe PRNG in case the crypto library RAND_bytes() call fails.
Returns
A (mostly crypto-safe) random 64-bit unsigned integer

◆ imquic_varint_read()

uint64_t imquic_varint_read ( uint8_t * bytes,
size_t blen,
uint8_t * length )

Read a variable size integer from a buffer.

Note
You can use the return value to know how many bytes to skip in the buffer to read the next value. In case of issues in the parsing, length will have value 0.
Parameters
[in]bytesThe buffer to read
[in]blenThe size of the buffer
[out]lengthHow many bytes the variable size integer used
Returns
The variable size integer, if length is higher than 0

◆ imquic_varint_write()

uint8_t imquic_varint_write ( uint64_t number,
uint8_t * bytes,
size_t blen )

Write a variable size integer to a buffer.

Note
You can use the return value to know how many bytes to skip in the buffer to write the next value. In case of issues in the writing, length will have value 0.
Parameters
[in]numberThe number to write as a variable size integer
[in]bytesThe buffer to write to
[in]blenThe size of the buffer
Returns
How many bytes the variable size integer used, if successful, 0 otherwise

Variable Documentation

◆ imquic_lock_debug

gboolean imquic_lock_debug = FALSE

◆ imquic_log_colors

gboolean imquic_log_colors = TRUE

◆ imquic_log_level

int imquic_log_level = IMQUIC_LOG_VERB

◆ imquic_log_timestamps

gboolean imquic_log_timestamps = FALSE

◆ imquic_refcount_debug

gboolean imquic_refcount_debug = FALSE

◆ initialized

volatile int initialized = IMQUIC_NOT_INITIALIZED