aap2_client: Move Unified API backend code to upstream

This removes the Unified-API-specific code from the AAP2 client. As
dicussed in !238, it fits better in the upstream repo.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This commit is contained in:
Felix Walter 2025-11-13 15:46:54 +01:00
parent f684fabc5a
commit 4b82854901
5 changed files with 0 additions and 911 deletions

View file

@ -1,502 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/** \file ud3tn_unified_api_backend.c
*
* \brief This file contains the functions that implement a C API on top of the
* ud3tn AAP2. Destined to be moved to ud3tn official code.
*
* \copyright (c) 2024 Alma Mater Studiorum, University of Bologna.
*
* \par License
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \author Fabio Colonna, fabio.colonna3@studio.unibo.it
* \author Beatrice Barbieri, beatrice.barbieri7@studio.unibo.it
*/
#include "aap2/aap2_client.h"
#include "aap2/aap2_unified_api_backend.h"
#include "platform/hal_io.h"
#include "ud3tn/eid.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
/* --------------- PUBLIC FUNCTIONS --------------- */
ud3tn_error_t ud3tn_close(ud3tn_handle_t handle)
{
LOGF_DEBUG("Entering %s", __func__);
aap2_client_close(handle->input_client);
aap2_client_close(handle->output_client);
free(handle);
return UD3TN_SUCCESS;
}
/**
* @note This function creates two connections on two different sockets in order to perform
* bidirectional communication.
*/
ud3tn_error_t ud3tn_open(ud3tn_handle_t *out_handle, char *sock_path)
{
LOGF_DEBUG("Entering %s", __func__);
*out_handle = NULL;
LOGF_DEBUG("Using AAP2 UNIX socket path: %s", sock_path);
UD3TNClientInfo *const out_client = malloc(sizeof(UD3TNClientInfo));
if (!out_client) {
LOG_ERROR("Could not allocate memory for client");
return UD3TN_EOPEN;
}
*out_client = (UD3TNClientInfo){
aap2_client_open_socket(sock_path, 0),
aap2_client_open_socket(sock_path, 0)
};
if (!out_client->input_client || !out_client->output_client) {
LOG_WARN("Opening AAP2 client connections failed");
aap2_client_close(out_client->input_client);
aap2_client_close(out_client->output_client);
free(out_client);
*out_handle = NULL;
return UD3TN_EOPEN;
}
LOG_DEBUG("Connected to AAP2 through a UNIX socket");
LOGF_DEBUG("Node ID: %s", aap2_client_get_node_id(out_client->input_client));
*out_handle = out_client;
return UD3TN_SUCCESS;
}
ud3tn_error_t ud3tn_open_with_ip(const char *const addr, int port, ud3tn_handle_t *out_handle)
{
LOGF_DEBUG("Entering %s", __func__);
*out_handle = NULL;
// Params check
if (port < 0 || port > (int)UINT16_MAX) {
LOGF_WARN("Invalid port number: %d", port);
return UD3TN_EINVAL;
}
if (!addr) {
LOG_WARN("INET address is null");
return UD3TN_EINVAL;
}
char service[6];
const int rv = snprintf(service, 6, "%d", port);
if (rv <= 0 || rv >= 6) {
LOGF_WARN("Failed to convert port number: %d", port);
return UD3TN_EINVAL;
}
UD3TNClientInfo *const out_client = malloc(sizeof(UD3TNClientInfo));
if (!out_client) {
LOG_ERROR("Could not allocate memory for client");
return UD3TN_EOPEN;
}
*out_client = (UD3TNClientInfo){
aap2_client_open_tcp(addr, service, 0),
aap2_client_open_tcp(addr, service, 0)
};
if (!out_client->input_client || !out_client->output_client) {
LOG_WARN("Opening AAP2 client connections failed");
aap2_client_close(out_client->input_client);
aap2_client_close(out_client->output_client);
free(out_client);
return UD3TN_EOPEN;
}
LOGF_DEBUG(
"Connected to AAP2 through a INET socket towards: %s:%d",
addr,
port
);
LOGF_DEBUG("Node ID: %s", aap2_client_get_node_id(out_client->input_client));
*out_handle = out_client;
return UD3TN_SUCCESS;
}
// Generate a random string consisting of valid ASCII characters != '\0'
static bool generate_random_ascii_string(uint8_t *buf, size_t buf_len)
{
ASSERT(buf_len != 0 && buf_len <= (size_t)SSIZE_MAX);
const int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
return false;
const ssize_t rv = read(fd, buf, buf_len);
if (rv != (ssize_t)buf_len)
return false;
// Ensure that it is an ASCII character != '\0'
for (ssize_t c = 0; c < rv; c++)
buf[c] = (buf[c] % 127) + 1;
return true;
}
/**
* @note This function performs the configuration of both connections.
* One where the client is passive (to receive AAPMessage
* sent by the AA) and one where the client is active (to send AAPMessage to the AA).
*/
ud3tn_error_t ud3tn_register(ud3tn_handle_t handle, ud3tn_reg_info_t *const reg_info)
{
// Params check
if (!handle->input_client || !handle->output_client || !reg_info ||
reg_info->keepalive_seconds < 0 ||
aap2_client_is_configured(handle->input_client) ||
aap2_client_is_configured(handle->output_client)) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
LOGF_DEBUG("Entering %s", __func__);
// Generate a random secret.
// As we only want to send/receive bundles, the sole requirement is that both secrets match.
char secret[64];
if (!generate_random_ascii_string((uint8_t *)secret, 64)) {
LOG_WARN("Cannot generate random secret for AAP2 connection");
return UD3TN_EREG;
}
const enum aap2_client_error rv_output = aap2_client_register(
handle->output_client,
(struct aap2_client_spec){
reg_info->endpoint.uri,
secret,
false,
reg_info->keepalive_seconds,
},
0
);
if (rv_output < 0) {
LOGF_WARN("Registration of output client failed with status code: %d", rv_output);
return UD3TN_EREG;
}
const enum aap2_client_error rv_input = aap2_client_register(
handle->input_client,
(struct aap2_client_spec){
reg_info->endpoint.uri,
secret,
true,
reg_info->keepalive_seconds,
},
0
);
if (rv_input < 0) {
LOGF_WARN("Registration of input client failed with status code: %d", rv_input);
return UD3TN_EREG;
}
LOG_DEBUG("Successfully registered to AAP2");
return UD3TN_SUCCESS;
}
/**
* @note This function fills a BundleADU with input parameters, sends it along with its payload
* and retreives the timestamp and seqno from the response.
*/
ud3tn_error_t ud3tn_send(ud3tn_handle_t handle, ud3tn_bundle_spec_t *const spec,
ud3tn_bundle_payload_t *const payload)
{
LOGF_DEBUG("Entering %s", __func__);
// Params check
if (!handle->output_client || !spec || !payload ||
!aap2_client_is_configured(handle->output_client) ||
aap2_client_is_subscriber(handle->output_client)) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
struct aap2_client_bundle_spec aap2_cspec = {
.source_eid = spec->source.uri,
.dest_eid = spec->dest.uri,
.creation_timestamp_dtn_ms = 0, // assign automatically
.sequence_number = 0, // assign automatically
.flags = (struct aap2_bundle_adu_flags){
.is_bpdu = (spec->proc_flags == BUNDLE_FLAG_ADMINISTRATIVE_RECORD),
.with_bdm_auth = spec->bdm_auth_validated,
},
};
const enum aap2_client_error rv = aap2_client_send(
handle->output_client,
aap2_cspec,
(uint8_t *)payload->buf.buf_val,
payload->buf.buf_len,
0,
&aap2_cspec // fine if contents are overwritten
);
switch (rv) {
case AAP2_CLIENT_OK:
break;
default:
// NOTE: We may want to handle the individual error codes differently.
LOGF_WARN("Failed sending ADU via AAP2, code = %d", rv);
return UD3TN_ESEND;
}
LOG_DEBUG("Got SUCCESS back. Successfully sent bundle");
#ifndef __clang_analyzer__
// NOTE: clang-tidy reports a false positive for a double free here.
free(aap2_cspec.source_eid); // unused
free(aap2_cspec.dest_eid); // unused
#endif // __clang_analyzer__
spec->creation_ts.time = aap2_cspec.creation_timestamp_dtn_ms;
spec->creation_ts.seqno = aap2_cspec.sequence_number;
return UD3TN_SUCCESS;
}
/**
* @note This function receives a BundleADU and its payload.
*/
ud3tn_error_t ud3tn_recv(ud3tn_handle_t handle, ud3tn_bundle_spec_t *out_spec,
ud3tn_bundle_payload_t *out_payload, ud3tn_timeval_t timeout)
{
// Params check
if (!handle->input_client || !out_spec || !out_payload ||
!aap2_client_is_configured(handle->input_client) ||
!aap2_client_is_subscriber(handle->input_client)) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
LOGF_DEBUG("Entering %s", __func__);
if (timeout == UD3TN_NO_TIMEOUT || timeout == 0)
LOG_DEBUG("About to recv with no timeout");
else
LOGF_DEBUG("About to start recv with timeout: %lu", timeout);
struct aap2_client_bundle_spec aap2_cspec = {
.source_eid = NULL,
.dest_eid = NULL,
.creation_timestamp_dtn_ms = 0,
.sequence_number = 0,
.flags = (struct aap2_bundle_adu_flags){false, false, false},
};
uint8_t *payload;
size_t payload_len;
enum aap2_client_error rv;
do {
rv = aap2_client_recv(
handle->input_client,
&aap2_cspec,
&payload,
&payload_len,
timeout
);
} while (rv == AAP2_CLIENT_EAGAIN); // auto-retry if wrong message type was received
switch (rv) {
case AAP2_CLIENT_OK:
break;
default:
// NOTE: We may want to handle the individual error codes differently.
LOGF_WARN("Failed receiving ADU via AAP2, code = %d", rv);
return UD3TN_ERECV;
}
out_payload->buf.buf_len = payload_len;
out_payload->buf.buf_val = (char *)payload;
out_payload->status_report = NULL;
snprintf(
out_spec->source.uri,
ARRAY_LENGTH(out_spec->source.uri),
"%s",
aap2_cspec.source_eid
);
free(aap2_cspec.source_eid);
free(aap2_cspec.dest_eid);
out_spec->creation_ts.time = aap2_cspec.creation_timestamp_dtn_ms;
out_spec->creation_ts.seqno = aap2_cspec.sequence_number;
return UD3TN_SUCCESS;
}
ud3tn_error_t ud3tn_build_local_eid(ud3tn_handle_t handle, ud3tn_endpoint_id_t *out_local_eid,
const char *const service_tag, ud3tn_scheme_t eid_scheme)
{
LOGF_DEBUG("Entering %s", __func__);
// Params check
if (!handle->input_client || !out_local_eid || !service_tag) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
const char *nodeID = aap2_client_get_node_id(handle->input_client);
const enum eid_scheme auto_determined_scheme = get_eid_scheme(nodeID);
switch (eid_scheme) {
case UD3TN_DTN_SCHEME:
if (auto_determined_scheme != EID_SCHEME_DTN) {
LOG_WARN("Cannot register as DTN as the node EID is not dtn");
return UD3TN_EINVAL;
}
break;
case UD3TN_IPN_SCHEME:
if (auto_determined_scheme != EID_SCHEME_IPN) {
LOG_WARN("Cannot register as IPN as the node EID is not ipn");
return UD3TN_EINVAL;
}
break;
default:
LOGF_WARN("Wrong EID scheme: %d", eid_scheme);
return UD3TN_EINVAL;
}
char *eid = aap2_client_get_eid_for_agent(nodeID, service_tag);
if (!eid) {
LOG_WARN("Failed to determine EID for registered AAP2 client");
return UD3TN_EINVAL;
}
const int rv = snprintf(out_local_eid->uri, ARRAY_LENGTH(out_local_eid->uri), "%s", eid);
if (rv <= 0 || rv >= (int)ARRAY_LENGTH(out_local_eid->uri)) {
LOG_WARN("Failed to copy resulting EID to dest buffer (too long?)");
free(eid);
return UD3TN_EINVAL;
}
free(eid);
return UD3TN_SUCCESS;
}
ud3tn_error_t ud3tn_copy_eid(ud3tn_endpoint_id_t *dst, ud3tn_endpoint_id_t *const src)
{
// Params check
if (!dst || !src) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
memset(dst->uri, 0, sizeof(dst->uri));
if (src->uri[0] == '\0')
return UD3TN_SUCCESS;
const int rv = snprintf(dst->uri, ARRAY_LENGTH(dst->uri), "%s", src->uri);
if (rv <= 0 || rv >= (int)ARRAY_LENGTH(dst->uri)) {
LOG_WARN("Failed to copy EID (too long?)");
return UD3TN_EINVAL;
}
return UD3TN_SUCCESS;
}
ud3tn_error_t ud3tn_parse_eid_string(ud3tn_endpoint_id_t *out_eid, const char *const str)
{
// Params check
if (!str || !out_eid) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
memset(out_eid->uri, 0, sizeof(out_eid->uri));
const int rv = snprintf(out_eid->uri, ARRAY_LENGTH(out_eid->uri), "%s", str);
if (rv <= 0 || rv >= (int)ARRAY_LENGTH(out_eid->uri)) {
LOG_WARN("Failed to copy EID (too long?)");
return UD3TN_EINVAL;
}
return UD3TN_SUCCESS;
}
ud3tn_error_t ud3tn_set_payload(ud3tn_bundle_payload_t *out_payload, const uint8_t *const buf,
uint32_t buf_length)
{
// Params check
if (!out_payload || !out_payload->buf.buf_val || !buf) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
// FIXME: Dangerous API. Implicitly assumes that out_payload->buf.buf_val is allocated with
// len == buf_length. Should be adapted in upstream Unified API backend.
memcpy(out_payload->buf.buf_val, buf, buf_length);
out_payload->buf.buf_len = buf_length;
return UD3TN_SUCCESS;
}
void ud3tn_free_payload(ud3tn_bundle_payload_t *const payload)
{
LOGF_DEBUG("Entering %s", __func__);
free(payload->buf.buf_val);
payload->buf.buf_val = NULL;
payload->buf.buf_len = 0;
}
ud3tn_error_t ud3tn_ping_aap(ud3tn_handle_t handle)
{
LOGF_DEBUG("Entering %s", __func__);
// Params check
if (!handle->output_client ||
!aap2_client_is_configured(handle->output_client) ||
aap2_client_is_subscriber(handle->output_client)) {
LOG_WARN("Invalid input param(s)");
return UD3TN_EINVAL;
}
const enum aap2_client_error rv = aap2_client_keepalive(
handle->output_client,
0
);
switch (rv) {
case AAP2_CLIENT_OK:
break;
default:
// NOTE: We may want to handle the individual error codes differently.
LOGF_WARN("Failed sending keepalive via AAP2, code = %d", rv);
return UD3TN_ESEND;
}
LOG_DEBUG("Got reply. AAP2 connection is still alive.");
return UD3TN_SUCCESS;
}

View file

@ -1,152 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
#ifndef AAP2_UNIFIED_API_BACKEND_H_INCLUDED
#define AAP2_UNIFIED_API_BACKEND_H_INCLUDED
/** \file ud3tn_unified_api_backend.h
*
* \brief This file contains the prototypes of the functions that implement a C
* API on top of the ud3tn AAP
* \brief This file contains the functions that implement a C API on top of the
* ud3tn AAP2. Destined to be moved to ud3tn official code.
*
* \copyright (c) 2024 Alma Mater Studiorum, University of Bologna.
*
* \par License
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \author Fabio Colonna, fabio.colonna3@studio.unibo.it
* \author Beatrice Barbieri, beatrice.barbieri7@studio.unibo.it
*/
#include "aap2/aap2_unified_api_backend_types.h"
/**
* @brief Closes the connection with the AAP
*
* @param handle [INPUT] Structure that defines a connection with the AAP, that
* is about to end
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_close(ud3tn_handle_t handle);
/**
* @brief Creates a UNIX socket that is used to communicate with the AAP
*
* @param out_handle [OUTPUT] Structure that defines a connection with the AAP.
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_open(ud3tn_handle_t *out_handle, char *sock_path);
/**
* @brief Creates a INET socket that is used to communicate with the AAP
*
* @param addr [INPUT] Address at which the AAP is listening
* @param port [INPUT] Port at which the AAP is listening
* @param out_handle [OUTPUT] Structure that defines a connection with the AAP
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_open_with_ip(const char *const addr, int port, ud3tn_handle_t *out_handle);
/**
* @brief Allows an application to register an EID to the AAP
*
* @param handle [INPUT] Structure that defines a connection with the AAP
* @param reg_info [INPUT] Registration information
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_register(ud3tn_handle_t handle, ud3tn_reg_info_t *const reg_info);
/**
* @brief Sends the bundle taken as input to the AAP
*
* @param handle [INPUT] Structure that defines a connection with the AAP
* @param spec [INPUT/OUTPUT] Bundle specifications (source & destination EIDs).
* Its timestamp & sequence number will be set after the function returns.
* @param payload [INPUT] Data to be sent
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_send(ud3tn_handle_t handle, ud3tn_bundle_spec_t *const spec,
ud3tn_bundle_payload_t *const payload);
/**
* @brief Awaits for a bundle to be received from the AAP, until a timeout (if
* present) expires
*
* @param handle Structure that defines a connection with the AAP
* @param out_spec [OUTPUT] It will contain the source EID of the received
* bundle
* @param out_payload [OUTPUT] Data received from AAP
* @param timeout [INPUT] Timeout at which to stop waiting for a bundle
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_recv(ud3tn_handle_t handle, ud3tn_bundle_spec_t *out_spec,
ud3tn_bundle_payload_t *out_payload, ud3tn_timeval_t timeout);
/**
* @brief Builds the EID of the node
*
* @param handle [INPUT] Structure that defines a connection with the AAP
* @param out_local_eid [OUTPUT] EID built
* @param service_tag [INPUT] Service tag
* @param eid_scheme [INPUT] EID Scheme (dtn or ipn)
* @return ud3tn_error_t UD3TN_SUCCESS or UD3TN_EINVAL if the EID scheme of the
* node does not match eid_scheme
*/
ud3tn_error_t ud3tn_build_local_eid(ud3tn_handle_t handle, ud3tn_endpoint_id_t *out_local_eid,
const char *const service_tag, ud3tn_scheme_t eid_scheme);
/**
* @brief Copies the source EID of a bundle into the destination EID
*
* @param dst [OUTPUT] Destination EID
* @param src [INPUT] Source EID
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_copy_eid(ud3tn_endpoint_id_t *dst, ud3tn_endpoint_id_t *const src);
/**
* @brief Parses a string into an EID
*
* @param out_eid [OUTPUT] EID
* @param str [INPUT] String to be parsed
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_parse_eid_string(ud3tn_endpoint_id_t *out_eid, const char *const str);
/**
* @brief Sets the payload of a bundle
*
* @param out_payload [OUTPUT] Payload of the bundle
* @param buf [INPUT] Data to be set as payload
* @param buf_length [INPUT] Length of the data to be set as payload
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_set_payload(ud3tn_bundle_payload_t *out_payload, const uint8_t *const buf,
uint32_t buf_length);
/**
* @brief Frees the memory allocated for the payload of a bundle
*
* @param payload [INPUT] Payload of the bundle that is about to be freed
*/
void ud3tn_free_payload(ud3tn_bundle_payload_t *const payload);
/**
* @brief Pings the AAP2 server using a KEEPALIVE message and waits for an acknowledgment
*
* @param handle [INPUT] Structure that defines a connection with the AAP
* @return ud3tn_error_t
*/
ud3tn_error_t ud3tn_ping_aap(ud3tn_handle_t handle);
#endif // AAP2_UNIFIED_API_BACKEND_H_INCLUDED

View file

@ -1,138 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
#ifndef AAP2_UNIFIED_API_BACKEND_TYPES_H_INCLUDED
#define AAP2_UNIFIED_API_BACKEND_TYPES_H_INCLUDED
/** \file ud3tn_unified_api_backend_types.h
*
* \brief This file contains the ud3tn C API types
*
* \brief This file contains the functions that implement a C API on top of the
* ud3tn AAP2. Destined to be moved to ud3tn official code.
*
* \copyright (c) 2024 Alma Mater Studiorum, University of Bologna.
*
* \par License
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \author Fabio Colonna, fabio.colonna3@studio.unibo.it
* \author Beatrice Barbieri, beatrice.barbieri7@studio.unibo.it
*/
#include "aap2/aap2.pb.h"
#include "ud3tn/bundle.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// NOTE: The timeout type is unsigned!
#define UD3TN_NO_TIMEOUT 0
#define UD3TN_TYPES_MAX_EID_LENGTH 256
// EXISTING UD3TN TYPES
/**
* @note BB: ClientInfo contains all relevant information regarding a connection. The connections
* are made to be bidirectional and thus require two separate sockets and input streams.
*/
typedef struct {
struct aap2_client *input_client, *output_client;
} UD3TNClientInfo;
typedef UD3TNClientInfo *ud3tn_handle_t;
typedef struct {
char uri[UD3TN_TYPES_MAX_EID_LENGTH];
} ud3tn_endpoint_id_t;
typedef uint64_t ud3tn_timeval_t;
// FColonna: added timestamp & seqno support through new types.
typedef struct {
uint64_t time;
uint64_t seqno;
} ud3tn_creation_timestamp_t;
/**
* @note BB:
* there's still several separate structs, one to represent the payload and
* others for additional data
* protocol_version has not been added because it's currently
* not required anywhere
*/
typedef struct ud3tn_bundle_spec_t {
enum bundle_proc_flags proc_flags;
ud3tn_endpoint_id_t source;
ud3tn_endpoint_id_t dest;
ud3tn_creation_timestamp_t creation_ts;
bool bdm_auth_validated;
} ud3tn_bundle_spec_t;
typedef struct ud3tn_bundle_payload_t {
struct {
uint32_t buf_len;
char *buf_val;
} buf;
// Status report parsing is not implemented in the client. This will be set to NULL.
void *status_report;
} ud3tn_bundle_payload_t;
/**
* @note BB: this struct contains all information that a client may require to configure a
* connection.
* @note FW: See `aap2_client.c` and `aap2.proto` for documentation of the fields.
*/
typedef struct {
ud3tn_endpoint_id_t endpoint;
uint32_t flags;
char *secret;
bool is_subscriber;
aap2_AuthType auth_type; // NOTE: handling not implemented at the moment
int keepalive_seconds;
} ud3tn_reg_info_t;
typedef enum {
UD3TN_SUCCESS,
UD3TN_EINVAL,
UD3TN_ECONNECT,
UD3TN_ETIMEOUT,
UD3TN_ESIZE,
UD3TN_ENOTFOUND,
UD3TN_EINTERNAL,
UD3TN_EBUSY,
UD3TN_ENOSPACE,
#ifndef UNIFIED_API_FUNCTION_WORKING_WHEN_AAP2
UD3TN_ENOTIMPL,
#endif // UNIFIED_API_FUNCTION_WORKING_WHEN_AAP2
/*
* FColonna: now the C interface propagates new errors to the upper layers,
* so I added them here. I also added them in the bp_ud3tn_error() function
* in the bp_ud3tn.c file, so that they can be converted to the respective
* Unified AP error types and propagated.
*/
UD3TN_ESEND,
UD3TN_ERECV,
UD3TN_EOPEN,
UD3TN_EREG,
UD3TN_ENULLPNTR
} ud3tn_error_t;
typedef enum {
UD3TN_IPN_SCHEME = 0,
UD3TN_DTN_SCHEME,
} ud3tn_scheme_t;
#endif // AAP2_UNIFIED_API_BACKEND_TYPES_H_INCLUDED

View file

@ -1,6 +1,5 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "aap2/aap2_client.h"
#include "aap2/aap2_unified_api_backend.h"
#include "testud3tn_unity.h"
@ -57,115 +56,7 @@ TEST(aapv2_client, aap2_client_get_eid_for_agent)
TEST_ASSERT_NULL(aap2_client_get_eid_for_agent("ipn:12.0", "abc"));
}
// --- TESTS FOR UNIFIED API BACKEND ---
static char *mk_filled(size_t n, char c)
{
char *p = (char *)malloc(n + 1);
TEST_ASSERT_NOT_NULL(p);
memset(p, c, n);
p[n] = '\0';
return p;
}
static void assert_zero_tail(const char *buf, size_t written, size_t total)
{
for (size_t i = written; i < total; ++i)
TEST_ASSERT_EQUAL_UINT8(0, (uint8_t)buf[i]);
}
TEST(aapv2_client, aap2_uapi_ud3tn_copy_eid)
{
// Success + zeroed tail
ud3tn_endpoint_id_t src, dst;
memset(&src, 0, sizeof(src));
memset(&dst, 0xCC, sizeof(dst));
const char *const s = "dtn://node/service";
int n = snprintf(src.uri, sizeof(src.uri), "%s", s);
TEST_ASSERT_EQUAL_INT(strlen(s), n);
const ud3tn_error_t rv = ud3tn_copy_eid(&dst, &src);
TEST_ASSERT_EQUAL(UD3TN_SUCCESS, rv);
TEST_ASSERT_EQUAL_STRING(s, dst.uri);
assert_zero_tail(dst.uri, (size_t)n, sizeof(dst.uri));
// NULL params
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_copy_eid(NULL, &src));
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_copy_eid(&dst, NULL));
}
TEST(aapv2_client, aap2_uapi_ud3tn_parse_eid_string)
{
// Success + zeroed tail
ud3tn_endpoint_id_t out;
memset(&out, 0xEE, sizeof(out));
const char *const s = "ipn:42.0";
ud3tn_error_t rv = ud3tn_parse_eid_string(&out, s);
TEST_ASSERT_EQUAL(UD3TN_SUCCESS, rv);
TEST_ASSERT_EQUAL_STRING(s, out.uri);
assert_zero_tail(out.uri, strlen(s), sizeof(out.uri));
// NULL params
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_parse_eid_string(NULL, "x"));
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_parse_eid_string(&out, NULL));
// Too long input
char *const too_long = mk_filled(sizeof(out.uri), 'A');
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_parse_eid_string(&out, too_long));
free(too_long);
// Empty string rejected (snprintf("") == 0 leads to EINVAL)
memset(&out, 0xEE, sizeof(out));
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_parse_eid_string(&out, ""));
}
TEST(aapv2_client, aap2_uapi_ud3tn_set_payload)
{
// Success copy and length
const uint8_t src[] = {1, 2, 3, 4, 5};
const uint32_t n = (uint32_t)ARRAY_LENGTH(src);
uint8_t *const dst_buf = (uint8_t *)malloc(n);
TEST_ASSERT_NOT_NULL(dst_buf);
memset(dst_buf, 0x00, n);
ud3tn_bundle_payload_t p = {0};
p.buf.buf_val = (char *)dst_buf;
p.buf.buf_len = 0;
p.status_report = NULL;
const ud3tn_error_t rv = ud3tn_set_payload(&p, src, n);
TEST_ASSERT_EQUAL(UD3TN_SUCCESS, rv);
TEST_ASSERT_EQUAL_UINT32(n, p.buf.buf_len);
TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst_buf, n);
// NULL out_payload
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_set_payload(NULL, src, n));
// NULL buf
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_set_payload(&p, NULL, n));
// NULL out_payload->buf.buf_val
p.buf.buf_val = NULL;
TEST_ASSERT_EQUAL(UD3TN_EINVAL, ud3tn_set_payload(&p, src, n));
free(dst_buf);
}
TEST_GROUP_RUNNER(aapv2_client)
{
RUN_TEST_CASE(aapv2_client, aap2_client_get_eid_for_agent);
RUN_TEST_CASE(aapv2_client, aap2_uapi_ud3tn_copy_eid);
RUN_TEST_CASE(aapv2_client, aap2_uapi_ud3tn_parse_eid_string);
RUN_TEST_CASE(aapv2_client, aap2_uapi_ud3tn_set_payload);
}

View file

@ -17,15 +17,5 @@ aap2_Bundle
aap2_Keepalive
aap2_AAPMessage
aap2_AAPResponse
UD3TNClientInfo
ud3tn_handle_t
ud3tn_endpoint_id_t
ud3tn_timeval_t
ud3tn_creation_timestamp_t
ud3tn_bundle_spec_t
ud3tn_bundle_payload_t
ud3tn_reg_info_t
ud3tn_error_t
ud3tn_scheme_t
agent_no_t
sqlite3