diff options
author | Oxore <oxore@protonmail.com> | 2023-12-14 23:08:02 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-12-14 23:08:02 +0300 |
commit | 4faf778b6ec4b9d8ab0c19e22d27c76f4c67ab28 (patch) | |
tree | 3b82c8b7b464ba9f19370fc5725014b7590617c4 | |
parent | 574ef210268681aab4c6729cb7556793d89f4b5a (diff) |
Impl mutual exchange of UDP messages
-rw-r--r-- | client.c | 41 | ||||
-rw-r--r-- | server.c | 138 |
2 files changed, 148 insertions, 31 deletions
@@ -3,17 +3,21 @@ #include <netinet/in.h> #include <stdbool.h> #include <stdint.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> +static unsigned char udp_buffer[UINT16_MAX]; + static inline bool IsDigit(char c) { return c >= '0' && c <= '9'; } -static unsigned ParseAddress(char const *str, FILE *log_stream) +static uint32_t ParseAddress(char const *str, FILE *log_stream) { - unsigned addr = 0, byte_counter = 0, byte = 0, digits_counter = 0; + uint32_t addr = 0; + unsigned byte_counter = 0, byte = 0, digits_counter = 0; for (size_t i = 0;; i++) { char const c = str[i]; if (c == '\0') { @@ -74,7 +78,7 @@ int main(int const argc, char *const argv[]) } int const port = atoi(argv[2]); if (port <= 0 || port > UINT16_MAX) { - fprintf(stderr, "Invalid port specifed\n"); + fprintf(stderr, "Invalid port specified\n"); return 1; } int const fd = socket(AF_INET, SOCK_DGRAM, 0); @@ -87,14 +91,29 @@ int main(int const argc, char *const argv[]) .sin_port = htons(port), .sin_addr.s_addr = htonl(addr), }; - for (int i = 0; i < 4; i++) { - ssize_t const ret = sendto( - fd, "hello", 5, 0, (struct sockaddr const *)&serveraddr, sizeof(serveraddr)); - if (ret < 0) { - perror("sendto failed"); - break; - } - printf("message sent\n"); + ssize_t const ret = sendto( + fd, "\x2a", 1, 0, (struct sockaddr const *)&serveraddr, sizeof(serveraddr)); + if (ret < 0) { + perror("sendto failed"); + return 1; } + printf("message sent\n"); + struct sockaddr_in source_address; + socklen_t source_address_len = sizeof(source_address); + int const length = recvfrom( + fd, + udp_buffer, + sizeof(udp_buffer) - 1, + 0, + (struct sockaddr*)&source_address, + &source_address_len); + (void) length; + uint32_t const addr2 = ntohl(source_address.sin_addr.s_addr); + uint8_t const a0 = addr2 >> 24; + uint8_t const a1 = addr2 >> 16; + uint8_t const a2 = addr2 >> 8; + uint8_t const a3 = addr2; + uint16_t const port2 = ntohs(source_address.sin_port); + printf("Received: %u from %u.%u.%u.%u:%u\n", udp_buffer[0], a0, a1, a2, a3, port2); close(fd); } @@ -1,11 +1,90 @@ // Initially based on https://stackoverflow.com/a/35570418 +#include <errno.h> +#include <fcntl.h> #include <netinet/in.h> +#include <poll.h> +#include <stdbool.h> +#include <stdint.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> +enum frame_type { + FT_NONE = 0, + FT_HELLO = 42, +}; + +struct frame { + uint32_t addr; + uint16_t port; + enum frame_type type; +}; + +static unsigned char udp_buffer[UINT16_MAX]; + +static int ReceiveFrame(int const fd, struct frame *const frame) +{ + frame->type = FT_NONE; + struct sockaddr_in source_address; + socklen_t source_address_len = sizeof(source_address); + int const length = recvfrom( + fd, + udp_buffer, + sizeof(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); + uint32_t const port = ntohs(source_address.sin_port); + if (length) { + unsigned char frame_type = udp_buffer[0]; + if (frame_type == FT_HELLO) { + *frame = (struct frame){ + .addr = addr, + .port = port, + .type = frame_type, + }; + } + } + uint8_t const a0 = addr >> 24; + uint8_t const a1 = addr >> 16; + uint8_t const a2 = addr >> 8; + uint8_t const a3 = addr; + printf("Received %u from %u.%u.%u.%u:%u\n", udp_buffer[0], a0, a1, a2, a3, port); + return 0; +} + +static int SendFrame(int const fd, struct frame const *const frame) +{ + udp_buffer[0] = frame->type; + struct sockaddr_in const addr = { + .sin_family = AF_INET, + .sin_port = htons(frame->port), + .sin_addr.s_addr = htonl(frame->addr), + }; + ssize_t const ret = sendto( + fd, udp_buffer, 1, 0, (struct sockaddr const *)&addr, sizeof(addr)); + if (ret < 0) { + int const err = errno; + perror("sendto failed"); + return -err; + } + printf("message sent\n"); + return 0; +} + int main(void) { int const fd = socket(AF_INET, SOCK_DGRAM, 0); @@ -13,6 +92,7 @@ int main(void) perror("socket failed"); return 1; } + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); struct sockaddr_in const serveraddr = { .sin_family = AF_INET, .sin_port = htons(50037u), @@ -22,28 +102,46 @@ int main(void) perror("bind failed"); return 1; } + struct pollfd fds[1] = { { .fd = fd, .events = POLLIN, }, }; for (;;) { - struct sockaddr_in source_address; - char buffer[200]; - socklen_t source_address_len = sizeof(source_address); - int const length = recvfrom( - fd, - buffer, - sizeof(buffer) - 1, - 0, - (struct sockaddr*)&source_address, - &source_address_len); - if (length < 0) { - perror("recvfrom failed"); - break; + int const timeout_msecs = 500; + int const pollret = poll(fds, sizeof(fds)/sizeof(*fds), timeout_msecs); + if (pollret > 0) { + if (fds[0].revents & POLLIN) { + while (1) { + struct frame frame = { .type = FT_NONE, }; + int const ret = ReceiveFrame(fd, &frame); + if (ret) { + break; + } + if (frame.type == FT_HELLO) { + SendFrame(fd, &frame); + } + } + } + if (fds[0].revents & POLLRDNORM) { + printf("POLLRDNORM, ignoring...\n"); + } + if (fds[0].revents & POLLRDBAND) { + printf("POLLRDBAND, ignoring...\n"); + } + if (fds[0].revents & POLLPRI) { + printf("POLLPRI, ignoring...\n"); + } + if (fds[0].revents & POLLPRI) { + printf("POLLPRI, ignoring...\n"); + } + if (fds[0].revents & POLLHUP) { + printf("POLLHUP, ignoring...\n"); + } + if (fds[0].revents & POLLERR) { + printf("POLLERR, ignoring...\n"); + } + if (fds[0].revents & POLLNVAL) { + printf("POLLNVAL, exiting...\n"); + return 1; + } } - uint32_t const addr = ntohl(source_address.sin_addr.s_addr); - uint8_t const a0 = addr >> 24; - uint8_t const a1 = addr >> 16; - uint8_t const a2 = addr >> 8; - uint8_t const a3 = addr; - printf("%d bytes: '%.*s' from %u.%u.%u.%u:%u\n", - length, (int)length, buffer, a0, a1, a2, a3, source_address.sin_port); } close(fd); } |