// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0 #include "aap2/aap2_util.h" #include "aap2/aap2.pb.h" #include "cla/posix/cla_tcp_util.h" #include "platform/hal_io.h" #include "ud3tn/common.h" #include #include #include #include #include #include // SENDING 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_; } int aap2_send_message(const int socket_fd, const pb_msgdesc_t *const fields, const void *const src_struct) { struct tcp_write_to_socket_param wsp = { .socket_fd = socket_fd, .errno_ = 0, }; pb_ostream_t stream = { &write_callback, &wsp, SIZE_MAX, 0, NULL, }; const bool ret = pb_encode_ex( &stream, fields, src_struct, PB_ENCODE_DELIMITED ); if (wsp.errno_) { LOG_ERRNO_WARN("AAP2", "send()", wsp.errno_); } else if (!ret) { LOGF_WARN( "AAP2: Protobuf encode error: %s", PB_GET_ERROR(&stream) ); wsp.errno_ = EIO; } return -wsp.errno_; } // RECEIVING bool aap2_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) LOG_ERRNO_WARN("AAP2", "recv()", errno); return (size_t)recvd == count; } int aap2_recv_message(pb_istream_t *stream, const pb_msgdesc_t *const fields, void *dest_struct) { const bool success = pb_decode_ex( stream, fields, dest_struct, PB_DECODE_DELIMITED ); if (!success) { if (stream->bytes_left == 0) LOG_WARN("AAP2: Connection closed by peer."); else LOGF_WARN( "AAP2: Protobuf decode error: %s", PB_GET_ERROR(stream) ); return -1; } return 0; } // ADU FLAGS HANDLING size_t aap2_set_adu_flags(aap2_BundleADUFlags *flags_field, struct aap2_bundle_adu_flags flags) { size_t count = 0; if (flags.is_bpdu) flags_field[count++] = aap2_BundleADUFlags_BUNDLE_ADU_BPDU; if (flags.with_bdm_auth) flags_field[count++] = ( aap2_BundleADUFlags_BUNDLE_ADU_WITH_BDM_AUTH ); if (flags.is_status_report) flags_field[count++] = ( aap2_BundleADUFlags_BUNDLE_ADU_STATUS_REPORT ); ASSERT(count <= AAP2_BUNDLE_ADU_FLAGS_COUNT); return count; } struct aap2_bundle_adu_flags aap2_get_adu_flags(const aap2_BundleADUFlags *flags_field, size_t flags_count) { struct aap2_bundle_adu_flags rv = {}; for (size_t i = 0; i < flags_count; i++) { switch (flags_field[i]) { case aap2_BundleADUFlags_BUNDLE_ADU_BPDU: rv.is_bpdu = true; break; case aap2_BundleADUFlags_BUNDLE_ADU_STATUS_REPORT: rv.is_status_report = true; break; case aap2_BundleADUFlags_BUNDLE_ADU_WITH_BDM_AUTH: rv.with_bdm_auth = true; break; default: break; } } return rv; }