// Initially based on https://stackoverflow.com/a/35570418 #include #include #include #include #include #include #include #include #include #include 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); if (fd < 0) { 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), .sin_addr.s_addr = htonl(INADDR_ANY), }; if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { perror("bind failed"); return 1; } struct pollfd fds[1] = { { .fd = fd, .events = POLLIN, }, }; for (;;) { 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; } } } close(fd); }