| 91 | } |
| 92 | |
| 93 | int main(void) { |
| 94 | server_fd = socket(AF_INET, SOCK_DGRAM, 0); |
| 95 | client_fd = socket(AF_INET, SOCK_DGRAM, 0); |
| 96 | assert(server_fd >= 0 && client_fd >= 0); |
| 97 | |
| 98 | struct sockaddr_in addr; |
| 99 | memset(&addr, 0, sizeof(addr)); |
| 100 | addr.sin_family = AF_INET; |
| 101 | addr.sin_port = htons(0); // ephemeral |
| 102 | inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); |
| 103 | if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) { |
| 104 | perror("bind"); |
| 105 | return 1; |
| 106 | } |
| 107 | |
| 108 | // The OS-assigned ephemeral port must be readable synchronously. |
| 109 | struct sockaddr_in la; |
| 110 | socklen_t ll = sizeof(la); |
| 111 | if (getsockname(server_fd, (struct sockaddr*)&la, &ll) != 0) { |
| 112 | perror("getsockname"); |
| 113 | return 1; |
| 114 | } |
| 115 | assert(ntohs(la.sin_port) != 0); |
| 116 | printf("listening on 127.0.0.1:%u\n", (unsigned)ntohs(la.sin_port)); |
| 117 | |
| 118 | // Datagram socket options round-trip on the bound socket. |
| 119 | int ttl = 64, on = 1, rcv = 131072, got; |
| 120 | socklen_t gl = sizeof(got); |
| 121 | assert(setsockopt(server_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == 0); |
| 122 | assert(setsockopt(server_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == 0); |
| 123 | assert(setsockopt(server_fd, SOL_SOCKET, SO_RCVBUF, &rcv, sizeof(rcv)) == 0); |
| 124 | assert(getsockopt(server_fd, IPPROTO_IP, IP_TTL, &got, &gl) == 0 && got == 64); |
| 125 | assert(getsockopt(server_fd, SOL_SOCKET, SO_BROADCAST, &got, &gl) == 0 && got != 0); |
| 126 | assert(getsockopt(server_fd, SOL_SOCKET, SO_RCVBUF, &got, &gl) == 0 && got > 0); |
| 127 | |
| 128 | set_nonblocking(server_fd); |
| 129 | set_nonblocking(client_fd); |
| 130 | |
| 131 | memset(&dest, 0, sizeof(dest)); |
| 132 | dest.sin_family = AF_INET; |
| 133 | dest.sin_port = la.sin_port; |
| 134 | inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr); |
| 135 | |
| 136 | #ifdef __EMSCRIPTEN__ |
| 137 | emscripten_set_main_loop(main_loop, 0, 0); |
| 138 | #else |
| 139 | while (1) { |
| 140 | main_loop(); |
| 141 | usleep(1000); |
| 142 | } |
| 143 | #endif |
| 144 | return 0; |
| 145 | } |
nothing calls this directly
no test coverage detected