summaryrefslogtreecommitdiff
path: root/proto_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto_io.c')
-rw-r--r--proto_io.c78
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;
+}