diff options
Diffstat (limited to 'proto_io.c')
-rw-r--r-- | proto_io.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/proto_io.c b/proto_io.c new file mode 100644 index 0000000..a903546 --- /dev/null +++ b/proto_io.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: Unlicense */ + +#include "proto_io.h" + +#include <arpa/inet.h> +#include <errno.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <stdio.h> + +static unsigned char g_udp_buffer[UINT16_MAX + 1u]; + +int ReceiveFrame(int fd, struct frame *frame) +{ + frame->type = FT_NONE; + struct sockaddr_in source_address; + socklen_t source_address_len = sizeof(source_address); + int const length = recvfrom( + fd, + g_udp_buffer, + sizeof(g_udp_buffer) - 1, + 0, + (struct sockaddr*)&source_address, + &source_address_len); + if (length == 0) { + return -EWOULDBLOCK; + } + if (length < 0) { + int const err = errno; + if (err != EWOULDBLOCK) { + perror("recvfrom failed"); + } + return -err; + } + uint32_t const addr = ntohl(source_address.sin_addr.s_addr); + uint16_t const port = ntohs(source_address.sin_port); + if (length) { + *frame = ParseFrame(g_udp_buffer, length); + frame->addr = addr; + frame->port = port; + } + if (LOG_TRACE) { + uint8_t const a0 = addr >> 24; + uint8_t const a1 = addr >> 16; + uint8_t const a2 = addr >> 8; + uint8_t const a3 = addr; + fprintf(stderr, "Received from %u.%u.%u.%u:%u\n", a0, a1, a2, a3, port); + } + return 0; +} + +int SendFrame(int const fd, struct frame const *const frame) +{ + g_udp_buffer[0] = frame->type; + struct sockaddr_in const sockaddr = { + .sin_family = AF_INET, + .sin_port = htons(frame->port), + .sin_addr.s_addr = htonl(frame->addr), + }; + if (LOG_TRACE) { + uint32_t const addr = frame->addr; + uint16_t const port = frame->port; + uint8_t const a0 = addr >> 24; + uint8_t const a1 = addr >> 16; + uint8_t const a2 = addr >> 8; + uint8_t const a3 = addr; + fprintf(stderr, "Sending to %u.%u.%u.%u:%u\n", a0, a1, a2, a3, port); + } + size_t const size = SerializeFrame(g_udp_buffer, UINT16_MAX + 1u, frame); + ssize_t const ret = sendto( + fd, g_udp_buffer, size, 0, (struct sockaddr const *)&sockaddr, sizeof(sockaddr)); + if (ret < 0) { + int const err = errno; + perror("sendto failed"); + return -err; + } + return 0; +} |