From c33f52741b2d1b483e508b0a9de16cf00c1e7b22 Mon Sep 17 00:00:00 2001 From: Felix Walter Date: Wed, 22 Oct 2025 13:19:39 +0200 Subject: [PATCH 1/6] test_program: Fix typo in Makefile --- test_program/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_program/Makefile b/test_program/Makefile index 0678a45..0becd82 100644 --- a/test_program/Makefile +++ b/test_program/Makefile @@ -103,7 +103,7 @@ help: @echo "For DTN2: make DTN2_DIR= UNIFIED_API_DIR=" @echo "For ION: make ION_DIR= UNIFIED_API_DIR=" @echo "For IBRDTN: make IBRDTN_DIR= UNIFIED_API_DIR=" - @echo "For UD3TN: make UD3DTN_DIR= UNIFIED_API_DIR=" + @echo "For UD3TN: make UD3TN_DIR= UNIFIED_API_DIR=" @echo "For Unibo-BP: make UNIBO_BP=1 UNIFIED_API_DIR=" @echo " The implementation dirs (DTN2_DIR, ION_DIR, ...) can be combined to make" @echo " an executable that runs with multiple BP implementations." -- GitLab From ef5bcebda49dbb9cae68054ad3fd2b1ef36613fc Mon Sep 17 00:00:00 2001 From: Felix Walter Date: Wed, 22 Oct 2025 10:29:34 +0200 Subject: [PATCH 2/6] test_program: Link to uD3TN library This enables the use of the updated uD3TN integration. --- test_program/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_program/Makefile b/test_program/Makefile index 0becd82..27d8c5d 100644 --- a/test_program/Makefile +++ b/test_program/Makefile @@ -59,8 +59,7 @@ endif ifneq ($(strip $(UD3TN_DIR)),) # UD3TN HAVE_IMPL := 1 -LIB_BP := $(LIB_BP) -lsqlite3 -lud3tn -#LIB_BP := $(LIB_BP) $(UD3TN_DIR)/build/posix/libud3tn.a -lsqlite3 +LIB_BP := $(LIB_BP) $(UD3TN_DIR)/build/posix/libud3tn.a -lsqlite3 -ljansson UNIFIED_API_LIB_NAME := $(UNIFIED_API_LIB_NAME)_vUD3TN BIN_NAME := $(BIN_NAME)_vUD3TN endif -- GitLab From 0cc84e777a06ea96cf18653c6bfd6eb600ed7f47 Mon Sep 17 00:00:00 2001 From: Felix Walter Date: Wed, 22 Oct 2025 10:01:44 +0200 Subject: [PATCH 3/6] bp/unibo-bp: Fix function declaration when not compiling with Unibo BP The function declaration for bp_unibo_bp_is_running() did not match with the header in case UNIBOBP_IMPLEMENTATION is not defined. --- src/bp/unibo-bp/bp_unibo_bp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/bp/unibo-bp/bp_unibo_bp.c b/src/bp/unibo-bp/bp_unibo_bp.c index 28e6740..1c73783 100644 --- a/src/bp/unibo-bp/bp_unibo_bp.c +++ b/src/bp/unibo-bp/bp_unibo_bp.c @@ -560,9 +560,7 @@ void bp_unibo_bp_free_extensions(al_types_bundle_spec* spec) { #else -bool bp_unibo_bp_is_running(const char *directory) { - (void) directory; // unused - +bool bp_unibo_bp_is_running() { return false; } -- GitLab From bb9676589c19da39a8ca05e34c31bdbf0307526d Mon Sep 17 00:00:00 2001 From: Felix Walter Date: Thu, 13 Nov 2025 16:45:35 +0100 Subject: [PATCH 4/6] bp/ud3tn: Implement based on upstream AAP2 client uD3TN now ships with an AAP2 client based on the code provided by DTNsuite. This adapts the corresponding files to make use of the upstream code. Much of the code that is "deleted" here has been migrated to the new uD3TN AAP2 client implementation. We decided for some adaptations of the API, such that users may e.g. choose to only use a socket for a single direction (send/receive). The code in `ud3tn_c_api` is an adaptation layer to these changes. It may be merged with bp_ud3tn.c in the future. Two notable extensions are made: - A function to randomly generate the uD3TN connection secret is introduced. - The Keepalive (Ping) mechanism is implemented for AAP2. See also: https://gitlab.com/d3tn/ud3tn/-/merge_requests/238 --- Makefile | 2 +- src/bp/ud3tn/ud3tn_c_api/aap2_backend.c | 867 +++++------------- src/bp/ud3tn/ud3tn_c_api/aap2_backend_types.h | 46 +- 3 files changed, 259 insertions(+), 656 deletions(-) diff --git a/Makefile b/Makefile index 9082240..159794c 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ ifneq ($(strip $(UD3TN_DIR)),) $(info Making for uD3TN) HAVE_IMPL := 1 UNIFIED_API_LIB_NAME := $(UNIFIED_API_LIB_NAME)_vUD3TN -INC := $(INC) -I$(UD3TN_DIR)/include -I$(UD3TN_DIR)/generated/aap2 -I$(UD3TN_DIR)/include/cla/posix/ -I$(UD3TN_DIR)/include/ud3tn -I$(UD3TN_DIR)/external/nanopb +INC := $(INC) -I$(UD3TN_DIR)/include -I$(UD3TN_DIR)/generated -I$(UD3TN_DIR)/include/ud3tn -I$(UD3TN_DIR)/external/nanopb OPT := $(OPT) -DUD3TN_IMPLEMENTATION endif diff --git a/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c b/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c index db1d85d..6cdd74c 100644 --- a/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c +++ b/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c @@ -27,290 +27,41 @@ #include "aap2_backend.h" #include "aap2_backend_types.h" #include "bp_ud3tn_debug_utils.h" -#include "cla_tcp_util.h" + +#include "aap2/aap2_client.h" +#include "ud3tn/eid.h" #include -#include -#include -#include -#include -#include +#include #include +#include #include #include -#include -#include #include /* --------------- PRIVATE FUNCTIONS --------------- */ -// Representation of AAP 2.0 BundleADUFlags repeated enum field. -struct bundle_adu_flags { - bool bpdu; - bool with_bdm_auth; -}; - -static size_t set_adu_flags( - aap2_BundleADUFlags *flags_field, struct bundle_adu_flags flags) -{ - size_t count = 0; - - if (flags.bpdu) - flags_field[count++] = aap2_BundleADUFlags_BUNDLE_ADU_BPDU; - if (flags.with_bdm_auth) - flags_field[count++] = (aap2_BundleADUFlags_BUNDLE_ADU_WITH_BDM_AUTH); - - return count; -} - -/** - * @note BB: callback functions for nanopb I/O. - */ -static bool pb_recv_callback(pb_istream_t *stream, uint8_t *buf, size_t count) -{ - if (count == 0) - return true; - - const int sock = (intptr_t) stream->state; - ssize_t recvd = tcp_recv_all(sock, buf, count); - - // EOF? - if (!recvd) - stream->bytes_left = 0; - else if (recvd < 0) - DEBUG_ERR("AAP2Client recv() error"); - - return (size_t) recvd == count; -} - -static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count) -{ - struct tcp_write_to_socket_param *const wsp = stream->state; - - tcp_write_to_socket(wsp, buf, count); - - return !wsp->errno_; -} - -/** - * @note BB: utility functions for sending and receiving messages - */ - -/** - * @brief Used for sending a message to the AAP socket. - * - * @param socket_fd [INPUT] Socket on which to send the message - * @param fields [INPUT] Message description as provided by nanopb - * @param src_struct [INPUT] Message to send - * @return int 0 if successful, errno otherwise - */ -static int -send_mesg_aap2(const int socket_fd, const pb_msgdesc_t *const fields, const void *const src_struct) +// @brief Generate a random string consisting of valid ASCII characters != '\0' +static bool +generate_random_ascii_string(uint8_t *buf, size_t buf_len) { - struct tcp_write_to_socket_param wsp = { - .socket_fd = socket_fd, - .errno_ = 0, - }; + //ASSERT(buf_len != 0 && buf_len <= (size_t)SSIZE_MAX); - pb_ostream_t stream = { - &write_callback, - &wsp, - SIZE_MAX, - 0, - NULL, - }; + const int fd = open("/dev/urandom", O_RDONLY); - const bool ret = pb_encode_ex( - &stream, - fields, - src_struct, - PB_ENCODE_DELIMITED); + if (fd < 0) + return false; - if (wsp.errno_) { - DEBUG_ERR("AAP2Client, send() error"); - } else if (!ret) { - DEBUG_ERR("AAP2Client: Protobuf encode error"); - } + const ssize_t bytes_read = read(fd, buf, buf_len); - return wsp.errno_; -} + if (bytes_read != (ssize_t)buf_len) + return false; -/** - * @note BB: this function receives the first welcome message - */ -static ud3tn_error_t -recv_welcome_mesg_aap2(int input_fd, pb_istream_t *input, aap2_AAPMessage *out_mesg) -{ - // throwaway read for incompatibility byte - uint8_t byte; - int inc = read(input_fd, &byte, 1); - (void) inc; - - bool success = pb_decode_ex( - input, - aap2_AAPMessage_fields, - out_mesg, - PB_DECODE_DELIMITED); - - if (!success) { - DEBUG_ERR("AAP2Agent: Protobuf decode error: %d\n", success); - return UD3TN_EINTERNAL; - } + // Ensure that it is an ASCII character != '\0' + for (ssize_t c = 0; c < bytes_read; c++) + buf[c] = (buf[c] % 127) + 1; - // moved deallocation as pb_release would delete all dynamically generated message contents, including strings. - return UD3TN_SUCCESS; -} - -/** - * @note BB: new function made to receive aap2 message and response types. - * recv_adu_mesg_aap2, listed below, has the specific purpose of receiving ADU responses with a timeout. - * This function is not identical to send_mesg_aap2: that is because of the fact that the output stream has to be - * created everytime, whereas input streams are created once and saved in the UD3TNClientInfo struct. - */ - -static ud3tn_error_t -recv_mesg_aap2(pb_istream_t *input, const pb_msgdesc_t *const fields, void * dest_struct) -{ - const bool success = pb_decode_ex( - input, - fields, - dest_struct, - PB_DECODE_DELIMITED); - - if (!success) { - DEBUG_ERR("Protobuf decode error: %d\n", success); - return UD3TN_EINTERNAL; - } - - return UD3TN_SUCCESS; -} - -/** - * @brief Used for receiving a bundle from the AAP socket. The data is received - * and then returned to the public function that called this. - * @param handle [INPUT] Structure that defines a connection with the AAP - * @param timeout [INPUT] Timeout at which to stop waiting for a bundle - * @param payload [INPUT] Pointer to payload that is only modified in case message is BundleADU - * @param mesg [OUTPUT] Bundle content incapsulated in an aap_message struct - * (type is AAP_INVALID on error) - * @return ud3tn_error_t UD3TN_SUCCESS on success, UD3TN_EINTERNAL on error, - * UD3TN_ETIMEOUT if the timeout expires - * BB changes to recv_mesg: - * removed some information (eid, payload_length) contained in out_mesg since now not all messages contain it. - */ - -static ud3tn_error_t -recv_adu_mesg_aap2(int input_fd, pb_istream_t *input, ud3tn_timeval_t timeout, aap2_AAPMessage *out_mesg) -{ - DEBUG_MSG("Entering %s\n", __FUNCTION__); - - // Used to handle select() - fd_set read_fds_mask; // Mask of file descriptors to be monitored for read - struct timeval tout; // Timeout for select() - int ready_fds; // Number of file descriptors ready for read - - do { - // Select modifies timeout and mask every time, need to reset them everytime - FD_ZERO(&read_fds_mask); - FD_SET(input_fd, &read_fds_mask); - tout.tv_sec = timeout / 1000; - tout.tv_usec = (timeout % 1000) * 1000; - printf("%ld", tout.tv_sec); - - // select() will block until either the socket is ready to be read or - // the timeout expires If timeout is NULL, then select() waits - // indefinitely until the socket is ready to be read - if ((ready_fds = select(input_fd + 1, &read_fds_mask, NULL, NULL, - timeout == UD3TN_NO_TIMEOUT ? NULL : (&tout))) - <= 0) { - DEBUG_ERR("select(): %s\n", ready_fds == 0 ? "Timed out" : strerror(errno)); - return ready_fds == 0 ? UD3TN_ETIMEOUT : UD3TN_EINTERNAL; - } - - bool success = pb_decode_ex( - input, - aap2_AAPMessage_fields, - out_mesg, - PB_DECODE_DELIMITED); - - if (!success) { - DEBUG_ERR("recv(): Protobuf decode error (-> assuming connection was closed)"); - // pb_release(aap2_AAPMessage_fields, out_mesg); nothing to deallocate as pb_decode_ex does this automatically - return UD3TN_ERECV; - } - - DEBUG_MSG("Done: EID: %s, Payload length: %lu, Type: %d\n", out_mesg->msg.adu.src_eid, - out_mesg->msg.adu.payload_length, out_mesg->which_msg); - break; - - } while (true); - - return UD3TN_SUCCESS; -} - -/** - * @note BB: this function receives the payload of a bundle. Note that this is because the payload and BundleADU are sent - * separately. - */ -static uint8_t *receive_payload(pb_istream_t *istream, size_t payload_length) -{ - if (payload_length > BUNDLE_MAX_SIZE) { - DEBUG_ERR("AAP2Client: Payload too large!"); - return NULL; - } - - uint8_t *payload = malloc(payload_length); - - if (!payload) { - DEBUG_ERR("AAP2Client: Payload alloc error!"); - return NULL; - } - - const bool success = pb_read(istream, payload, payload_length); - - if (!success) { - free(payload); - payload = NULL; - DEBUG_ERR("AAP2Client: Payload read error!"); - } - - return payload; -} - -/** - * @note BB: this function connects to the socket. - */ -static int -connect_to_socket(int domain, void *const addr, socklen_t sz, ud3tn_sockets *sockets) -{ - int sock_fd = socket(domain, SOCK_STREAM, 0); - if (sock_fd < 0) { - DEBUG_ERR("socket(): %s\n", strerror(errno)); - return -1; - } - - if (connect(sock_fd, (struct sockaddr *) addr, sz) < 0) { - DEBUG_ERR("connect(): %s\n", strerror(errno)); - close(sock_fd); - return -1; - } - - sockets->one = sock_fd; - - sock_fd = socket(domain, SOCK_STREAM, 0); - if (sock_fd < 0) { - DEBUG_ERR("socket(): %s\n", strerror(errno)); - return -1; - } - - if (connect(sock_fd, (struct sockaddr *) addr, sz) < 0) { - DEBUG_ERR("connect(): %s\n", strerror(errno)); - close(sock_fd); - return -1; - } - - sockets->two = sock_fd; - return 0; + return true; } /* --------------- PUBLIC FUNCTIONS --------------- */ @@ -325,11 +76,9 @@ ud3tn_close(ud3tn_handle_t handle) DEBUG_ERR("Invalid input param\n"); return UD3TN_ENULLPNTR; } - // close(handle->socket); - shutdown(handle->input_socket, SHUT_RDWR); - shutdown(handle->output_socket, SHUT_RDWR); - close(handle->input_socket); - close(handle->output_socket); + + aap2_client_close(handle->input_client); + aap2_client_close(handle->output_client); free(handle); return UD3TN_SUCCESS; } @@ -343,71 +92,32 @@ ud3tn_error_t ud3tn_open(ud3tn_handle_t *out_handle, char* sock_path) { DEBUG_MSG("Entering %s\n", __FUNCTION__); - struct _aap2_AAPMessage welcome_mesg = aap2_AAPMessage_init_default; - struct sockaddr_un aap2_addr; - ud3tn_error_t recv_err; - DEBUG_MSG("Using AAP UNIX socket path: %s\n", sock_path); - *out_handle = (UD3TNClientInfo *) malloc(sizeof(UD3TNClientInfo)); - if (!out_handle) { + UD3TNClientInfo *const out_client = malloc(sizeof(UD3TNClientInfo)); + if (!out_client) { DEBUG_ERR("malloc(): %s\n", strerror(errno)); *out_handle = NULL; return UD3TN_EINTERNAL; } - aap2_addr.sun_family = AF_UNIX; - strncpy(aap2_addr.sun_path, sock_path, sizeof(aap2_addr.sun_path) - 1); - - ud3tn_sockets *fds = (ud3tn_sockets *) malloc(sizeof(ud3tn_sockets)); - if ((connect_to_socket(AF_UNIX, &aap2_addr, sizeof aap2_addr, fds)) < 0) - return UD3TN_EOPEN; - (*out_handle)->input_socket = fds->one; - (*out_handle)->output_socket = fds->two; - - (*out_handle)->input_socket_in = (pb_istream_t) { - &pb_recv_callback, - (void *) (intptr_t) (*out_handle)->input_socket, - SIZE_MAX, - NULL, - }; - - (*out_handle)->output_socket_in = (pb_istream_t) { - &pb_recv_callback, - (void *) (intptr_t) (*out_handle)->output_socket, - SIZE_MAX, - NULL, + *out_client = (UD3TNClientInfo){ + aap2_client_open_socket(sock_path, 0), + aap2_client_open_socket(sock_path, 0) }; - recv_err = recv_welcome_mesg_aap2((*out_handle)->input_socket, &(*out_handle)->input_socket_in, &welcome_mesg); - if (welcome_mesg.which_msg != aap2_AAPMessage_welcome_tag || recv_err != UD3TN_SUCCESS) { - if (recv_err != UD3TN_SUCCESS) - DEBUG_ERR("Error in receiving input welcome message\n"); - else - DEBUG_ERR("AAP2 did not welcome the input connection request\n"); - pb_release(aap2_AAPMessage_fields, &welcome_mesg); - ud3tn_close(*out_handle); - return UD3TN_EOPEN; - } - - recv_err = recv_welcome_mesg_aap2((*out_handle)->output_socket, &(*out_handle)->output_socket_in, &welcome_mesg); - if (welcome_mesg.which_msg != aap2_AAPMessage_welcome_tag || recv_err != UD3TN_SUCCESS) { - if (recv_err != UD3TN_SUCCESS) - DEBUG_ERR("Error in receiving output welcome message\n"); - else - DEBUG_ERR("AAP2 did not welcome the output connection request\n"); - pb_release(aap2_AAPMessage_fields, &welcome_mesg); - ud3tn_close(*out_handle); + if (!out_client->input_client || !out_client->output_client) { + DEBUG_ERR("Opening AAP2 client connections failed\n"); + aap2_client_close(out_client->input_client); + aap2_client_close(out_client->output_client); + free(out_client); + *out_handle = NULL; return UD3TN_EOPEN; } - strncpy((*out_handle)->nodeID, welcome_mesg.msg.welcome.node_id, sizeof((*out_handle)->nodeID) - 1); - - // deallocation is here in order to keep welcome_mesg accessible to open - pb_release(aap2_AAPMessage_fields, &welcome_mesg); - - DEBUG_MSG("Got welcome message back: Connected to the AAP2 through a UNIX socket\n"); - DEBUG_MSG("Node ID: %s\n", (*out_handle)->nodeID); + DEBUG_MSG("Connected to AAP2 through a UNIX socket\n"); + DEBUG_MSG("Node ID: %s\n", aap2_client_get_node_id(out_client->input_client)); + *out_handle = out_client; return UD3TN_SUCCESS; } @@ -417,7 +127,7 @@ ud3tn_open_with_ip(const char *const addr, int port, ud3tn_handle_t *out_handle) DEBUG_MSG("Entering %s\n", __FUNCTION__); // Params check - if (port < 0) { + if (port < 0 || port > (int)UINT16_MAX) { DEBUG_ERR("Invalid port number: %d\n", port); *out_handle = NULL; return UD3TN_EINVAL; @@ -429,82 +139,42 @@ ud3tn_open_with_ip(const char *const addr, int port, ud3tn_handle_t *out_handle) return UD3TN_EINVAL; } - struct hostent *aap2_hostent; - struct _aap2_AAPMessage welcome_mesg = aap2_AAPMessage_init_default; - struct sockaddr_in aap2_addr; - ud3tn_error_t recv_err; + char service[6]; + const int port_chars_written = snprintf(service, 6, "%d", port); - *out_handle = (UD3TNClientInfo *) malloc(sizeof(UD3TNClientInfo)); - if (!out_handle) { + if (port_chars_written <= 0 || port_chars_written >= 6) { + DEBUG_ERR("Failed to convert port number: %d\n", port); + return UD3TN_EINVAL; + } + + UD3TNClientInfo *const out_client = malloc(sizeof(UD3TNClientInfo)); + + if (!out_client) { DEBUG_ERR("malloc(): %s\n", strerror(errno)); *out_handle = NULL; return UD3TN_EINTERNAL; } - aap2_hostent = gethostbyname(addr); - if (!aap2_hostent) { - DEBUG_ERR("gethostbyname(): %s\n", strerror(h_errno)); - ud3tn_close(*out_handle); - return UD3TN_ENOTFOUND; - } - - // AAP2 INET construction - memset(&aap2_addr, 0, sizeof aap2_addr); - aap2_addr.sin_family = AF_INET; - aap2_addr.sin_port = htons(port); - memcpy(&aap2_addr.sin_addr.s_addr, aap2_hostent->h_addr, aap2_hostent->h_length); - - ud3tn_sockets *fds = (ud3tn_sockets *) malloc(sizeof(ud3tn_sockets)); - if ((connect_to_socket(AF_INET, &aap2_addr, sizeof aap2_addr, fds)) < 0) - return UD3TN_EOPEN; - (*out_handle)->input_socket = fds->one; - (*out_handle)->output_socket = fds->two; - - (*out_handle)->input_socket_in = (pb_istream_t) { - &pb_recv_callback, - (void *) (intptr_t) (*out_handle)->input_socket, - SIZE_MAX, - NULL, - }; - - (*out_handle)->output_socket_in = (pb_istream_t) { - &pb_recv_callback, - (void *) (intptr_t) (*out_handle)->output_socket, - SIZE_MAX, - NULL, + *out_client = (UD3TNClientInfo){ + aap2_client_open_tcp(addr, service, 0), + aap2_client_open_tcp(addr, service, 0) }; - recv_err = recv_welcome_mesg_aap2((*out_handle)->input_socket, &(*out_handle)->input_socket_in, &welcome_mesg); - if (welcome_mesg.which_msg != aap2_AAPMessage_welcome_tag || recv_err != UD3TN_SUCCESS) { - if (recv_err != UD3TN_SUCCESS) - DEBUG_ERR("Error in receiving input welcome message\n"); - else - DEBUG_ERR("AAP2 did not welcome the input connection request\n"); - pb_release(aap2_AAPMessage_fields, &welcome_mesg); - ud3tn_close(*out_handle); + if (!out_client->input_client || !out_client->output_client) { + DEBUG_ERR("Opening AAP2 client connections failed\n"); + aap2_client_close(out_client->input_client); + aap2_client_close(out_client->output_client); + free(out_client); return UD3TN_EOPEN; } - recv_err = recv_welcome_mesg_aap2((*out_handle)->output_socket, &(*out_handle)->output_socket_in, &welcome_mesg); - if (welcome_mesg.which_msg != aap2_AAPMessage_welcome_tag || recv_err != UD3TN_SUCCESS) { - if (recv_err != UD3TN_SUCCESS) - DEBUG_ERR("Error in receiving output welcome message\n"); - else - DEBUG_ERR("AAP2 did not welcome the output connection request\n"); - pb_release(aap2_AAPMessage_fields, &welcome_mesg); - ud3tn_close(*out_handle); - return UD3TN_EOPEN; - } - - strncpy((*out_handle)->nodeID, welcome_mesg.msg.welcome.node_id, sizeof((*out_handle)->nodeID) - 1); - - // deallocation is here in order to keep welcome_mesg accessible to open - pb_release(aap2_AAPMessage_fields, &welcome_mesg); - DEBUG_MSG( - "Got welcome message back: Connected to the AAP through a INET socket towards: %s:%d\n", - addr, port); - DEBUG_MSG("Node ID: %s\n", (*out_handle)->nodeID); + "Connected to AAP2 through a INET socket towards: %s:%d\n", + addr, + port + ); + DEBUG_MSG("Node ID: %s\n", aap2_client_get_node_id(out_client->input_client)); + *out_handle = out_client; return UD3TN_SUCCESS; } @@ -517,73 +187,59 @@ ud3tn_open_with_ip(const char *const addr, int port, ud3tn_handle_t *out_handle) ud3tn_error_t ud3tn_register(ud3tn_handle_t handle, ud3tn_reg_info_t *const reg_info) { + DEBUG_MSG("Entering %s\n", __FUNCTION__); + // Params check - if (!handle || !reg_info /* || !out_reg_id */) { + if (!handle || !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)) { DEBUG_ERR("Invalid input param(s)\n"); return UD3TN_EINVAL; } - DEBUG_MSG("Entering %s\n", __FUNCTION__); + // Generate a random secret. + // As we only want to send/receive bundles, the sole requirement is that both secrets match. + char secret[64]; - int error; - aap2_AAPMessage reg_mesg = aap2_AAPMessage_init_default; - aap2_AAPResponse resp_mesg = aap2_AAPResponse_init_default; - - reg_mesg.which_msg = aap2_AAPMessage_config_tag; - reg_mesg.msg.config.endpoint_id = (char *) calloc(256, sizeof(char)); - ud3tn_error_t recv_err; - - if (!reg_mesg.msg.config.endpoint_id) { - DEBUG_ERR("calloc() [eid]: %s\n", strerror(errno)); - return UD3TN_EINTERNAL; - } - - strcpy(reg_mesg.msg.config.endpoint_id, reg_info->endpoint.uri); - - // reg.mesg.msg.config.is_subscriber = reg_info->is_subscriber; - reg_mesg.msg.config.auth_type = reg_info->auth_type; - reg_mesg.msg.config.is_subscriber = false; // false means you can only send bundles - // hardcoded for now. to be implemented in upper layers - reg_mesg.msg.config.secret = (char *) calloc(6, sizeof(char)); - strcpy(reg_mesg.msg.config.secret, "hello"); - - // Sending the registration message to the AAP2 - if ((error = send_mesg_aap2(handle->output_socket, aap2_AAPMessage_fields, ®_mesg)) > 0) { - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(error)); - pb_release(aap2_AAPMessage_fields, ®_mesg); + if (!generate_random_ascii_string((uint8_t *)secret, 64)) { + DEBUG_ERR("Cannot generate random secret for AAP2 connection\n"); return UD3TN_EREG; } - // Receiving the response from AAP2 - recv_err = recv_mesg_aap2(&handle->output_socket_in, aap2_AAPResponse_fields, &resp_mesg); - if (resp_mesg.response_status != aap2_ResponseStatus_RESPONSE_STATUS_SUCCESS || recv_err != UD3TN_SUCCESS) { - DEBUG_ERR("AAP2 did not ACK the registration\n"); - pb_release(aap2_AAPResponse_fields, &resp_mesg); - return UD3TN_EREG; - } + const enum aap2_client_error error_code_output = aap2_client_register( + handle->output_client, + (struct aap2_client_spec){ + reg_info->endpoint.uri, + secret, + false, + reg_info->keepalive_seconds, + }, + 0 + ); - // only changing is_subscriber param - reg_mesg.msg.config.is_subscriber = true; // true means you can receive bundles - - // Sending the registration message to the AAP2 - if ((error = send_mesg_aap2(handle->input_socket, aap2_AAPMessage_fields, ®_mesg)) > 0) { - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(error)); - pb_release(aap2_AAPMessage_fields, ®_mesg); + if (error_code_output < 0) { + DEBUG_ERR("Registration of output client failed with status code: %d\n", error_code_output); return UD3TN_EREG; } - // Receiving the response from AAP2 - recv_err = recv_mesg_aap2(&handle->input_socket_in, aap2_AAPResponse_fields, &resp_mesg); - if (resp_mesg.response_status != aap2_ResponseStatus_RESPONSE_STATUS_SUCCESS || recv_err != UD3TN_SUCCESS) { - DEBUG_ERR("AAP2 did not ACK the registration\n"); - pb_release(aap2_AAPResponse_fields, &resp_mesg); + const enum aap2_client_error error_code_input = aap2_client_register( + handle->input_client, + (struct aap2_client_spec){ + reg_info->endpoint.uri, + secret, + true, + reg_info->keepalive_seconds, + }, + 0 + ); + + if (error_code_input < 0) { + DEBUG_ERR("Registration of input client failed with status code: %d\n", error_code_input); return UD3TN_EREG; } - pb_release(aap2_AAPMessage_fields, ®_mesg); - pb_release(aap2_AAPResponse_fields, &resp_mesg); - - DEBUG_MSG("Got ACK back: Successfully registered to AAP2\n"); + DEBUG_MSG("Successfully registered to AAP2\n"); return UD3TN_SUCCESS; } @@ -598,84 +254,52 @@ ud3tn_send(ud3tn_handle_t handle, ud3tn_bundle_spec_t *const spec, DEBUG_MSG("Entering %s\n", __FUNCTION__); // Params check - if (!handle || !spec || !payload) { + if (!handle || !handle->output_client || !spec || !payload || + !aap2_client_is_configured(handle->output_client) || + aap2_client_is_subscriber(handle->output_client)) { DEBUG_ERR("Invalid input param(s)\n"); return UD3TN_EINVAL; } - aap2_AAPMessage send_mesg = aap2_AAPMessage_init_default; - struct bundle_adu_flags flags = { - .bpdu = (spec->proc_flags == BUNDLE_FLAG_ADMINISTRATIVE_RECORD), - .with_bdm_auth = spec->bdm_auth_validated, + 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->is_bpdu, + .is_status_report = false, // the AAP2 client cannot itself send status reports + .with_bdm_auth = spec->bdm_auth_validated, + }, }; - send_mesg.which_msg = aap2_AAPMessage_adu_tag; - send_mesg.msg.adu.dst_eid = spec->dest.uri; - send_mesg.msg.adu.src_eid = spec->source.uri; - send_mesg.msg.adu.payload_length = payload->buf.buf_len; - send_mesg.msg.adu.adu_flags_count = set_adu_flags( - send_mesg.msg.adu.adu_flags, flags); - - int send_result = send_mesg_aap2( - handle->output_socket, - aap2_AAPMessage_fields, - &send_mesg); - - if (send_result < 0) { - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(send_result)); - return UD3TN_ESEND; - } - - struct tcp_write_to_socket_param wsp = { - .socket_fd = handle->output_socket, - .errno_ = 0, - }; - - pb_ostream_t ostream = (pb_ostream_t) { - &write_callback, - &wsp, - SIZE_MAX, + const enum aap2_client_error error_code = aap2_client_send( + handle->output_client, + aap2_cspec, + (uint8_t *)payload->buf.buf_val, + payload->buf.buf_len, 0, - NULL, - }; - - const bool ret = pb_write(&ostream, (const unsigned char *) payload->buf.buf_val, payload->buf.buf_len); - - if (wsp.errno_) { - DEBUG_ERR("AAP2Client send() error: %d", wsp.errno_); - send_result = -1; - } else if (!ret) { - DEBUG_ERR( - "AAP2Agent: pb_write() error: %s", - PB_GET_ERROR(&ostream)); - send_result = -1; - } + &aap2_cspec // fine if contents are overwritten + ); - if (send_result < 0) { - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(send_result)); - return UD3TN_ESEND; - } - - aap2_AAPResponse res_mesg = aap2_AAPResponse_init_default; - send_result = recv_mesg_aap2(&handle->output_socket_in, aap2_AAPResponse_fields, &res_mesg); - if (res_mesg.response_status != aap2_ResponseStatus_RESPONSE_STATUS_SUCCESS || send_result != UD3TN_SUCCESS) { - DEBUG_ERR("AAP did not confirm the bundle sent\n"); - pb_release(aap2_AAPResponse_fields, &res_mesg); + switch (error_code) { + case AAP2_CLIENT_OK: + break; + default: + // NOTE: We may want to handle the individual error codes differently. + DEBUG_ERR("Failed sending ADU via AAP2, code = %d\n", error_code); return UD3TN_ESEND; } DEBUG_MSG("Got SUCCESS back. Successfully sent bundle\n"); - // retrieve timestamp and seqno from response - if (!res_mesg.has_bundle_headers) { - DEBUG_ERR("Error in received response.\n"); - pb_release(aap2_AAPResponse_fields, &res_mesg); - return UD3TN_ESEND; - } - - spec->creation_ts.time = res_mesg.bundle_headers.creation_timestamp_ms; - spec->creation_ts.seqno = res_mesg.bundle_headers.sequence_number; - pb_release(aap2_AAPResponse_fields, &res_mesg); +#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; } @@ -686,75 +310,68 @@ 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) { - int error; + DEBUG_MSG("Entering %s\n", __FUNCTION__); + // Params check - if (!handle || !out_spec || !out_payload) { + if (!handle || !handle->input_client || !out_spec || !out_payload || + !aap2_client_is_configured(handle->input_client) || + !aap2_client_is_subscriber(handle->input_client)) { DEBUG_ERR("Invalid input param(s)\n"); return UD3TN_EINVAL; } - DEBUG_MSG("Entering %s\n", __FUNCTION__); - - aap2_AAPMessage recv_mesg = aap2_AAPMessage_init_default; - aap2_AAPResponse res_mesg = aap2_AAPResponse_init_default; - res_mesg.has_bundle_headers = false; - res_mesg.has_dispatch_result = true; - ud3tn_error_t recv_err; - + // NOTE: ud3tn_timeval_t is defined as uint64_t. if (timeout == UD3TN_NO_TIMEOUT) DEBUG_MSG("About to recv with no timeout\n"); else DEBUG_MSG("About to start recv with timeout: %lu\n", timeout); - recv_err = recv_adu_mesg_aap2(handle->input_socket, &handle->input_socket_in, timeout, &recv_mesg); - - if (recv_err != UD3TN_SUCCESS) { - DEBUG_ERR("recv_adu_mesg_aap2(): %s\n", - recv_err == UD3TN_ETIMEOUT ? "Timeout" : "Could not receive"); - - // setting response parameters - res_mesg.response_status = (recv_err == UD3TN_ETIMEOUT ? aap2_ResponseStatus_RESPONSE_STATUS_TIMEOUT : aap2_ResponseStatus_RESPONSE_STATUS_ERROR); - pb_release(aap2_AAPMessage_fields, &recv_mesg); - - // sending faulty response - if ((error = send_mesg_aap2(handle->input_socket, aap2_AAPResponse_fields, &res_mesg)) > 0) { - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(error)); - return UD3TN_ERECV; - } - return recv_err; - } + 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 error_code; - DEBUG_MSG("Got a message back. Type is: %d\n", recv_mesg.which_msg); - - // Read payload - uint8_t *payload_data; - payload_data = receive_payload( - &handle->input_socket_in, - recv_mesg.msg.adu.payload_length); - - out_payload->buf.buf_len = recv_mesg.msg.adu.payload_length; - out_payload->buf.buf_val = (char *) payload_data; - strncpy(out_spec->source.uri, recv_mesg.msg.adu.src_eid, sizeof(out_spec->source.uri) - 1); - out_spec->creation_ts.time = recv_mesg.msg.adu.creation_timestamp_ms; - out_spec->creation_ts.seqno = recv_mesg.msg.adu.sequence_number; - - // after bundle has been received, ack has to be sent back. - res_mesg.response_status = aap2_ResponseStatus_RESPONSE_STATUS_SUCCESS; - //setting bundle headers - res_mesg.has_bundle_headers = true; - res_mesg.bundle_headers.creation_timestamp_ms = recv_mesg.msg.adu.creation_timestamp_ms; - res_mesg.bundle_headers.sequence_number = recv_mesg.msg.adu.sequence_number; - res_mesg.bundle_headers.dst_eid = recv_mesg.msg.adu.src_eid; - res_mesg.bundle_headers.src_eid = recv_mesg.msg.adu.dst_eid; - - if ((error = send_mesg_aap2(handle->input_socket, aap2_AAPResponse_fields, &res_mesg)) > 0) { - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(error)); - pb_release(aap2_AAPMessage_fields, &res_mesg); - return UD3TN_EREG; + do { + error_code = aap2_client_recv( + handle->input_client, + &aap2_cspec, + &payload, + &payload_len, + timeout + ); + } while (error_code == AAP2_CLIENT_EAGAIN); // auto-retry if wrong message type was received + + switch (error_code) { + case AAP2_CLIENT_OK: + break; + default: + // NOTE: We may want to handle the individual error codes differently. + DEBUG_ERR("Failed receiving ADU via AAP2, code = %d\n", error_code); + return UD3TN_ERECV; } - pb_release(aap2_AAPMessage_fields, &recv_mesg); - + out_payload->buf.buf_len = payload_len; + out_payload->buf.buf_val = (char *)payload; + out_payload->status_report = NULL; + snprintf( + out_spec->source.uri, + UD3TN_TYPES_MAX_EID_LENGTH, + "%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; + out_spec->is_bpdu = aap2_cspec.flags.is_bpdu; + out_spec->is_status_report = aap2_cspec.flags.is_status_report; + out_spec->bdm_auth_validated = aap2_cspec.flags.with_bdm_auth; return UD3TN_SUCCESS; } @@ -765,39 +382,49 @@ ud3tn_build_local_eid(ud3tn_handle_t handle, ud3tn_endpoint_id_t *out_local_eid, DEBUG_MSG("Entering %s\n", __FUNCTION__); // Params check - if (!handle || !out_local_eid || !service_tag) { + if (!handle || !handle->input_client || !out_local_eid || !service_tag) { DEBUG_ERR("Invalid input param(s)\n"); return UD3TN_EINVAL; } - char pch[30]; - switch (eid_scheme) { - case UD3TN_DTN_SCHEME: - if (!strncmp(handle->nodeID, "dtn", 3)) { - sprintf(out_local_eid->uri, "%s%s", handle->nodeID, service_tag); - return UD3TN_SUCCESS; - } + 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) { DEBUG_ERR("Cannot register as DTN as the node EID is not dtn\n"); return UD3TN_EINVAL; - // uD3TN in the node ID includes the delimiter ud3tn daemon does not - // start if the dtn eid is not followed by the delimiter (e.g. - // dtn:/a.dtn/) - case UD3TN_IPN_SCHEME: - if (!strncmp(handle->nodeID, "ipn", 3)) { - strcpy(pch, handle->nodeID); - strcpy(pch, strtok(pch, ".")); // extract from ipn:node.0 ipn:n - sprintf(out_local_eid->uri, "%s.%s", pch, - service_tag); // concatenate "." and the service tag - return UD3TN_SUCCESS; - } - + } + break; + case UD3TN_IPN_SCHEME: + if (auto_determined_scheme != EID_SCHEME_IPN) { DEBUG_ERR("Cannot register as IPN as the node EID is not ipn\n"); return UD3TN_EINVAL; - default: - DEBUG_ERR("Wrong EID scheme: %d\n", eid_scheme); - return UD3TN_EINVAL; + } + break; + default: + DEBUG_ERR("Wrong EID scheme: %d\n", eid_scheme); + return UD3TN_EINVAL; + } + + char *eid = aap2_client_get_eid_for_agent(nodeID, service_tag); + + if (!eid) { + DEBUG_ERR("Failed to determine EID for registered AAP2 client\n"); + return UD3TN_EINVAL; + } + + const int copied_chars = snprintf(out_local_eid->uri, UD3TN_TYPES_MAX_EID_LENGTH, "%s", eid); + + if (copied_chars <= 0 || copied_chars >= (int)UD3TN_TYPES_MAX_EID_LENGTH) { + DEBUG_ERR("Failed to copy resulting EID to dest buffer (too long?)\n"); + free(eid); + return UD3TN_EINVAL; } + + free(eid); + return UD3TN_SUCCESS; } ud3tn_error_t @@ -810,7 +437,16 @@ ud3tn_copy_eid(ud3tn_endpoint_id_t *dst, ud3tn_endpoint_id_t *const src) } memset(dst->uri, 0, sizeof(dst->uri)); - strncpy(dst->uri, src->uri, sizeof(dst->uri)); + + if (src->uri[0] == '\0') + return UD3TN_SUCCESS; + + const int copied_chars = snprintf(dst->uri, UD3TN_TYPES_MAX_EID_LENGTH, "%s", src->uri); + + if (copied_chars <= 0 || copied_chars >= (int)UD3TN_TYPES_MAX_EID_LENGTH) { + DEBUG_ERR("Failed to copy EID (too long?)\n"); + return UD3TN_EINVAL; + } return UD3TN_SUCCESS; } @@ -824,7 +460,13 @@ ud3tn_parse_eid_string(ud3tn_endpoint_id_t *out_eid, const char *const str) } memset(out_eid->uri, 0, sizeof(out_eid->uri)); - strncpy(out_eid->uri, str, sizeof(out_eid->uri) - 1); + + const int copied_chars = snprintf(out_eid->uri, UD3TN_TYPES_MAX_EID_LENGTH, "%s", str); + + if (copied_chars <= 0 || copied_chars >= (int)UD3TN_TYPES_MAX_EID_LENGTH) { + DEBUG_ERR("Failed to copy EID (too long?)\n"); + return UD3TN_EINVAL; + } return UD3TN_SUCCESS; } @@ -833,11 +475,13 @@ ud3tn_set_payload(ud3tn_bundle_payload_t *out_payload, const uint8_t *const buf, uint32_t buf_length) { // Params check - if (!out_payload || !buf || buf_length < 0) { + if (!out_payload || !out_payload->buf.buf_val || !buf) { DEBUG_ERR("Invalid input param(s)\n"); return UD3TN_EINVAL; } + // FIXME: Dangerous API. Implicitly assumes that out_payload->buf.buf_val is allocated with + // len == buf_length. Should be adapted in Unified API backend. memcpy(out_payload->buf.buf_val, buf, buf_length); out_payload->buf.buf_len = buf_length; return UD3TN_SUCCESS; @@ -856,50 +500,39 @@ void ud3tn_free_payload(ud3tn_bundle_payload_t *const payload) */ free(payload->buf.buf_val); + payload->buf.buf_val = NULL; payload->buf.buf_len = 0; } -/*legacy code, never called*/ -#ifdef UNIFIED_API_FUNCTION_WORKING_WHEN_AAP2 ud3tn_error_t ud3tn_ping_aap(ud3tn_handle_t handle) { DEBUG_MSG("Entering %s\n", __FUNCTION__); // Params check - if (!handle) { - DEBUG_ERR("Invalid input param\n"); + if (!handle->output_client || + !aap2_client_is_configured(handle->output_client) || + aap2_client_is_subscriber(handle->output_client)) { + DEBUG_ERR("Invalid input param(s)\n"); return UD3TN_EINVAL; } - int error; - struct aap_message ping_mesg = { .type = AAP_MESSAGE_PING }; + const enum aap2_client_error error_code = aap2_client_keepalive( + handle->output_client, + 0 + ); - if ((error = send_mesg_aap2(handle->socket, &ping_mesg)) > 0) { // Sends ping to AAP - DEBUG_ERR("send_mesg_aap2(): %s\n", strerror(error)); + switch (error_code) { + case AAP2_CLIENT_OK: + break; + default: + // NOTE: We may want to handle the individual error codes differently. + DEBUG_ERR("Failed sending keepalive via AAP2, code = %d\n", error_code); return UD3TN_ESEND; } - aap_message_clear(&ping_mesg); - - aap_parser_init(&(handle->parser)); - - error = recv_adu_mesg_aap2(handle, UD3TN_NO_TIMEOUT, &ping_mesg); // Waits for response - if (ping_mesg.type != AAP_MESSAGE_PING || error != UD3TN_SUCCESS) { - DEBUG_ERR("AAP did not pong the ping\n"); - return UD3TN_ERECV; - } - - aap_parser_deinit(&(handle->parser)); - - DEBUG_MSG("Got pong from AAP: Type is: %d\n", ping_mesg.type); + DEBUG_MSG("Got reply. AAP2 connection is still alive.\n"); return UD3TN_SUCCESS; } -#else -ud3tn_error_t -ud3tn_ping_aap(ud3tn_handle_t handle) -{ - return UD3TN_ENOTIMPL; -} -#endif // UNIFIED_API_FUNCTION_WORKING_WHEN_AAP2 + #endif // UD3TN_IMPLEMENTATION diff --git a/src/bp/ud3tn/ud3tn_c_api/aap2_backend_types.h b/src/bp/ud3tn/ud3tn_c_api/aap2_backend_types.h index 4631f2c..3d8cae3 100644 --- a/src/bp/ud3tn/ud3tn_c_api/aap2_backend_types.h +++ b/src/bp/ud3tn/ud3tn_c_api/aap2_backend_types.h @@ -26,8 +26,7 @@ #pragma once -#include "aap2.pb.h" -#include "bundle.h" +#include "aap2/aap2_client.h" /////////////////////////////////////////////////////////// #include #include @@ -35,7 +34,7 @@ #include /////////////////////////////////////////////////////////// -#define UD3TN_NO_TIMEOUT -1 +#define UD3TN_NO_TIMEOUT 0 #define UD3TN_TYPES_MAX_EID_LENGTH 256 /** @@ -48,25 +47,6 @@ */ #define AAP2_UNIX_SOCKPATH "UD3TN_SOCKET" -/** - * @brief Used to specify the initial receive buffer capacity in bytes - * @note Only used in recv_mesg_aap() - */ -#define RECV_BUF_INITIAL_CAP_BYTES 10 * 1000// 10 KB - -/** - * @brief Used to specify the resize factor used when remalloc-ing the recv - * buffer - * @note Only used in recv_mesg_aap() - */ -#define RECV_BUF_RESIZE_FACTOR 2 - -// Used internally -struct write_socket_param { - int socket_fd; - int errno_; -}; - // EXISTING UD3TN TYPES /** @@ -75,28 +55,16 @@ struct write_socket_param { */ typedef struct { - int input_socket; - int output_socket; - pb_istream_t output_socket_in; - pb_istream_t input_socket_in; - char myEID[UD3TN_TYPES_MAX_EID_LENGTH]; - char nodeID[UD3TN_TYPES_MAX_EID_LENGTH]; + struct aap2_client *input_client, *output_client; } UD3TNClientInfo; typedef UD3TNClientInfo *ud3tn_handle_t; -typedef struct { - int one; - int two; -} ud3tn_sockets; - typedef struct { char uri[UD3TN_TYPES_MAX_EID_LENGTH]; } ud3tn_endpoint_id_t; typedef uint64_t ud3tn_timeval_t; -typedef uint32_t ud3tn_reg_token_t; -typedef uint32_t ud3tn_reg_id_t; typedef int ud3tn_bundle_payload_location_t; // Only memory @@ -114,11 +82,12 @@ typedef struct { * 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; + bool bdm_auth_validated; + bool is_bpdu; + bool is_status_report; } ud3tn_bundle_spec_t; // Needed by status_report_t @@ -165,7 +134,8 @@ typedef struct { uint32_t flags; char *secret; bool is_subscriber; - aap2_AuthType auth_type; + aap2_AuthType auth_type; // NOTE: handling not implemented at the moment + int keepalive_seconds; } ud3tn_reg_info_t; typedef enum -- GitLab From 0feb6e0817f3a7bdc9156a33459842af6b5b17a3 Mon Sep 17 00:00:00 2001 From: Felix Walter Date: Fri, 14 Nov 2025 11:52:58 +0100 Subject: [PATCH 5/6] ud3tn: Make implementation independent from uD3TN's eid.h We plan changes to that rather internal API, which would impact this implementation in the future. We should thus only rely on the stable AAP2 client API. Moreover, using uD3TN's eid.h introduces a second type for the EID scheme enum, which can be confusing. --- src/bp/ud3tn/ud3tn_c_api/aap2_backend.c | 34 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c b/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c index 6cdd74c..b821def 100644 --- a/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c +++ b/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c @@ -29,7 +29,6 @@ #include "bp_ud3tn_debug_utils.h" #include "aap2/aap2_client.h" -#include "ud3tn/eid.h" #include #include @@ -64,6 +63,28 @@ generate_random_ascii_string(uint8_t *buf, size_t buf_len) return true; } +// @brief Detect the scheme of an EID provided as a C string. +static bool +detect_eid_scheme(const char *const eid, ud3tn_scheme_t *const out_scheme) +{ + if (!eid || !out_scheme) + return false; + + const size_t len = strlen(eid); + + if (len >= UD3TN_TYPES_MAX_EID_LENGTH) + return false; + + if (len >= 4 && !memcmp(eid, "dtn:", 4)) + *out_scheme = UD3TN_DTN_SCHEME; + else if (len >= 4 && !memcmp(eid, "ipn:", 4)) + *out_scheme = UD3TN_IPN_SCHEME; + else + return false; + + return true; +} + /* --------------- PUBLIC FUNCTIONS --------------- */ ud3tn_error_t @@ -388,17 +409,22 @@ ud3tn_build_local_eid(ud3tn_handle_t handle, ud3tn_endpoint_id_t *out_local_eid, } const char *nodeID = aap2_client_get_node_id(handle->input_client); - const enum eid_scheme auto_determined_scheme = get_eid_scheme(nodeID); + ud3tn_scheme_t auto_determined_scheme; + + if (!detect_eid_scheme(nodeID, &auto_determined_scheme)) { + DEBUG_ERR("Cannot detect EID scheme of provided node EID\n"); + return UD3TN_EINVAL; + } switch (eid_scheme) { case UD3TN_DTN_SCHEME: - if (auto_determined_scheme != EID_SCHEME_DTN) { + if (auto_determined_scheme != UD3TN_DTN_SCHEME) { DEBUG_ERR("Cannot register as DTN as the node EID is not dtn\n"); return UD3TN_EINVAL; } break; case UD3TN_IPN_SCHEME: - if (auto_determined_scheme != EID_SCHEME_IPN) { + if (auto_determined_scheme != UD3TN_IPN_SCHEME) { DEBUG_ERR("Cannot register as IPN as the node EID is not ipn\n"); return UD3TN_EINVAL; } -- GitLab From 0cd1a17e92cb7fd5995fc5668e84ca24ea0e1c9a Mon Sep 17 00:00:00 2001 From: Felix Walter Date: Fri, 14 Nov 2025 11:54:57 +0100 Subject: [PATCH 6/6] ud3tn: Close fd after using it --- src/bp/ud3tn/ud3tn_c_api/aap2_backend.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c b/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c index b821def..6b2e2b6 100644 --- a/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c +++ b/src/bp/ud3tn/ud3tn_c_api/aap2_backend.c @@ -53,6 +53,8 @@ generate_random_ascii_string(uint8_t *buf, size_t buf_len) const ssize_t bytes_read = read(fd, buf, buf_len); + close(fd); + if (bytes_read != (ssize_t)buf_len) return false; -- GitLab