// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0 #ifndef AAP2_CLIENT_H_INCLUDED #define AAP2_CLIENT_H_INCLUDED #include "aap2/aap2_util.h" #include #include #include #ifdef __cplusplus extern "C" { #endif // __cplusplus /** * @brief The opaque structure to store AAP2 client state. Members of this data structure are only * accessed internally by AAP2 client methods. */ struct aap2_client; /** * @brief Represents possible error states of the AAP2 client. All errors have negative values. */ enum aap2_client_error { /** * @brief Success. */ AAP2_CLIENT_OK = 0, /** * @brief General error - the intended action failed. */ AAP2_CLIENT_EFAIL = -1, /** * @brief A provided argument or parameter is invalid. */ AAP2_CLIENT_EARGUMENT = -2, /** * @brief The intended action timed out. */ AAP2_CLIENT_ETIMEOUT = -3, /** * @brief The intended action was interrupted and should be retried if desired. */ AAP2_CLIENT_EAGAIN = -4, /** * @brief The intended action was not authorized by the server. */ AAP2_CLIENT_EUNAUTHORIZED = -5, }; /** * @brief Closes all connections and releases memory allocated for the given AAP2 client. * * @param client A pointer to the AAP2 client to be released. If NULL, this operation is a no-op. */ void aap2_client_close(struct aap2_client *client); /** * @brief Opens a new Unix Domain Socket connection to AAP2. * * @param sock_path The path to the socket file that should be opened. * @param timeout_ms A timeout, in ms, for receiving the Welcome message (zero or any value larger * than INT32_MAX mean infinite). * @return A pointer to the AAP2 client instance, or NULL on error. If a pointer is returned, it * must be released using aap2_client_close. */ struct aap2_client *aap2_client_open_socket(const char *sock_path, uint64_t timeout_ms); /** * @brief Opens a new TCP connection to AAP2. * * @param node The node parameter passed to getaddrinfo, e.g., a hostname or IP address. * @param service The service parameter passed to getaddrinfo, e.g., the TCP port number. * @param timeout_ms A timeout, in ms, for receiving the Welcome message (zero or any value larger * than INT32_MAX mean infinite). * @return A pointer to the AAP2 client instance, or NULL on error. If a pointer is returned, it * must be released using aap2_client_close. */ struct aap2_client *aap2_client_open_tcp(const char *node, const char *service, uint64_t timeout_ms); /** * @brief A data structure defining the parameters that can be configured by aap2_client_register. */ struct aap2_client_spec { /** * @brief The full endpoint identifier to be registered. Usually, the EID must be derived * from the node identifier of the connected bundle node, e.g., using the function * aap2_client_get_eid_for_agent. */ char *eid; /** * @brief A C string containing the AAP2 secret to be passed to the connected bundle node. * If it only intends to send and receive (normal) bundles, the client may choose * this arbitrarily, though the node may impose additional constraints such as a * minimum length. It is advisable to choose a cryptographically secure, unique, * and long secret for protecting the endpoint registration. */ char *secret; /** * @brief Whether the client intends to send (false) or receive (true) bundle ADUs. */ bool is_subscriber; /** * @brief The period, in seconds, expected between two Keepalive messages. The peer * may terminate the connection in case an expected Keepalive message is not * received. For non-subscribers, in case the feature is turned on, Keepalive * messages have to be generated using the corresponding function. For subscribers, * the reception logic of the client will automatically acknowledge incoming * Keepalive messages, but will require the caller to retry reception. * A value of 0 (default) means that the keepalive mechanism is turned off. */ uint32_t keepalive_timeout_s; }; /** * @brief Configures the given AAP2 client connection, registering an endpoint. Note that this * operation can only be executed once per client instance, for multiple endpoint * registrations individual client connections should be used. * * @param client The AAP2 client instance to be configured. Must not be configured already. * @param client_spec The settings to be configured on registration. * @param timeout_ms A timeout, in ms, for receiving the acknowledgment (zero or any value larger * than INT32_MAX mean infinite). * @return AAP2_CLIENT_OK on success, a value indicating the error on failure. */ enum aap2_client_error aap2_client_register(struct aap2_client *client, const struct aap2_client_spec client_spec, uint64_t timeout_ms); /** * @brief Returns the node identifier of the connected bundle node. * * @param client A valid, connected, AAP2 client instance (that does not need to be configured yet). * @return The node identifier provided by the node in its Welcome message, or NULL on error. */ const char *aap2_client_get_node_id(const struct aap2_client *client); /** * @brief Returns the registered EID for a configured AAP2 client. * * @param client A valid, connected and configured, AAP2 client instance. * @return The registered endpoint identifier (EID), or NULL on error. */ const char *aap2_client_get_registered_eid(const struct aap2_client *client); /** * @brief Returns a value indicating whether the provided AAP2 client is configured. * * @param client A valid, connected, AAP2 client instance. * @return A value indicating whether the provided AAP2 client is valid and configured. */ bool aap2_client_is_configured(const struct aap2_client *client); /** * @brief Returns a value indicating whether the provided AAP2 client is in subscriber mode (i.e. * allows for receiving bundles). * * @param client A valid, connected and configured, AAP2 client instance. * @return A value indicating whether the provided AAP2 client is valid, connected, and in * subscriber mode. */ bool aap2_client_is_subscriber(const struct aap2_client *client); /** * @brief Combines the given node identifier and agent identifier and returns a heap-allocated * C string that can be used for registering an EID with an AAP2 client. * * @param node_id The node identifier to be used as a basis. Has to be a valid EID (URI) of either * the `dtn`or `ipn` scheme. * @param agent_id The agent identifier, i.e., the `dtn` demux part or `ipn` service number, in * C string format. * @return A heap-allocated EID string, or NULL on error. */ char *aap2_client_get_eid_for_agent(const char *node_id, const char *agent_id); /** * @brief Represents a bundle ADU for transmission via AAP2. This data structure is passed to the * AAP2 send function and returned by the AAP2 receive function. * * @note When sending bundles, source_eid, creation_timestamp_dtn_ms, and sequence_number may be * NULL and/or zero. These values are then derived automatically by the connected bundle node. */ struct aap2_client_bundle_spec { /** * @brief The source EID of the bundle ADU. Must match the one registered by the AAP2 * client when sending bundles (if not authorized using the administrative secret). */ char *source_eid; /** * @brief The destination EID of the bundle ADU. When receiving, this is usually the EID * registered by the AAP2 client. */ char *dest_eid; /** * @brief The report-to EID of the bundle ADU. */ char *report_to_eid; /** * @brief The bundle creation timestamp, a DTN timestamp as defined in RFC9171, in ms. * Set automatically if zero when sending bundles. */ uint64_t creation_timestamp_dtn_ms; /** * @brief The bundle sequence number. Set automatically if zero when sending bundles. */ uint64_t sequence_number; /** * @brief The AAP2 flags set on the bundle. These flags specify, e.g., if the payload * is a BPDU or status report, or the administrative authorization flag for the * ADU is set or requested. */ struct aap2_bundle_adu_flags flags; }; /** * @brief Send a bundle ADU via the provided AAP2 client. * * @param client The AAP2 client to be used. Must be valid, connected, configured (registered), * and not be a subscriber. * @param spec Metadata of the bundle to be created. * @param payload A pointer to the ADU payload data. * @param payload_length The length, in bytes, of the ADU payload. * @param timeout_ms A timeout, in ms, for receiving the acknowledgment (zero or any value larger * than INT32_MAX mean infinite). * @param out_spec A pointer to an optional structure to return metadata of the created bundle. * Can be set to NULL when this data is not needed. Note that the flags and * report-to EID are always unset as they are not returned by AAP 2.0. * @return AAP2_CLIENT_OK on success, a value indicating the error on failure. */ enum aap2_client_error aap2_client_send(struct aap2_client *client, const struct aap2_client_bundle_spec spec, const uint8_t *payload, size_t payload_length, uint64_t timeout_ms, struct aap2_client_bundle_spec *out_spec); /** * @brief Wait for the next AAP2 message and, in case it is a bundle ADU, return it. * * @param client The AAP2 client to be used. Must be valid, connected, configured (registered), * and be a subscriber. * @param out_spec A pointer to a structure to return metadata of the received bundle ADU. * @param out_payload Where to store the pointer to the heap-allocated ADU payload data. * @param out_payload_length Where to store the length, in bytes, of the ADU payload. * @param timeout_ms A timeout, in ms, for receiving the bundle ADU (zero or any value larger * than INT32_MAX mean infinite). * @return AAP2_CLIENT_OK on success, AAP2_CLIENT_EAGAIN when the server sends a message that does * not contain a bundle, a value indicating the error on failure. * @note Keepalive messages are handled (acknowledged) automatically, but interrupt the receiving * process (AAP2_CLIENT_EAGAIN is returned). The caller should retry in this case. */ enum aap2_client_error aap2_client_recv(struct aap2_client *client, struct aap2_client_bundle_spec *out_spec, uint8_t **out_payload, size_t *out_payload_length, uint64_t timeout_ms); /** * @brief Send a Keepalive (Ping) message via the provided AAP2 client. * * @param client The AAP2 client to be used. Must be valid, connected, configured (registered), * and not be a subscriber. * @param timeout_ms A timeout, in ms, for receiving the acknowledgment (zero or any value larger * than INT32_MAX mean infinite). * @return AAP2_CLIENT_OK on success, a value indicating the error on failure. */ enum aap2_client_error aap2_client_keepalive(struct aap2_client *client, uint64_t timeout_ms); /** * @brief Frees the heap-allocated fields of the aap2_client_bundle_spec structure. */ void aap2_client_free_bundle_spec_fields(struct aap2_client_bundle_spec *spec); #ifdef __cplusplus } #endif // __cplusplus #endif // AAP2_CLIENT_H_INCLUDED