mirror of
https://gitlab.com/d3tn/ud3tn.git
synced 2026-08-13 12:33:27 +02:00
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:
parent
f684fabc5a
commit
4b82854901
5 changed files with 0 additions and 911 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue