summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-12-14 23:08:02 +0300
committerOxore <oxore@protonmail.com>2023-12-14 23:08:02 +0300
commit4faf778b6ec4b9d8ab0c19e22d27c76f4c67ab28 (patch)
tree3b82c8b7b464ba9f19370fc5725014b7590617c4
parent574ef210268681aab4c6729cb7556793d89f4b5a (diff)
Impl mutual exchange of UDP messages
-rw-r--r--client.c41
-rw-r--r--server.c138
2 files changed, 148 insertions, 31 deletions
diff --git a/client.c b/client.c
index 007bf2d..8f4d5ff 100644
--- a/client.c
+++ b/client.c
@@ -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);
}
diff --git a/server.c b/server.c
index 7288eca..ffb7c42 100644
--- a/server.c
+++ b/server.c
@@ -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);
}