| 128 | } |
| 129 | |
| 130 | int main(void) { |
| 131 | listen_fd = socket(AF_INET, SOCK_STREAM, 0); |
| 132 | assert(listen_fd >= 0); |
| 133 | |
| 134 | #ifndef NO_EXPLICIT_BIND |
| 135 | struct sockaddr_in addr; |
| 136 | memset(&addr, 0, sizeof(addr)); |
| 137 | addr.sin_family = AF_INET; |
| 138 | addr.sin_port = htons(0); // ephemeral |
| 139 | inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); |
| 140 | if (bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) { |
| 141 | perror("bind"); |
| 142 | return 1; |
| 143 | } |
| 144 | #endif |
| 145 | // With NO_EXPLICIT_BIND, listen() must auto-bind an ephemeral port (POSIX), |
| 146 | // and getsockname() below must still report it. |
| 147 | if (listen(listen_fd, 4) != 0) { |
| 148 | perror("listen"); |
| 149 | return 1; |
| 150 | } |
| 151 | |
| 152 | // The OS-assigned ephemeral port must be readable synchronously. |
| 153 | struct sockaddr_in la; |
| 154 | socklen_t ll = sizeof(la); |
| 155 | if (getsockname(listen_fd, (struct sockaddr*)&la, &ll) != 0) { |
| 156 | perror("getsockname"); |
| 157 | return 1; |
| 158 | } |
| 159 | assert(ntohs(la.sin_port) != 0); |
| 160 | printf("listening on 127.0.0.1:%u\n", (unsigned)ntohs(la.sin_port)); |
| 161 | set_nonblocking(listen_fd); |
| 162 | |
| 163 | memset(&dest, 0, sizeof(dest)); |
| 164 | dest.sin_family = AF_INET; |
| 165 | dest.sin_port = la.sin_port; |
| 166 | inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr); |
| 167 | start_client(); |
| 168 | |
| 169 | #ifdef __EMSCRIPTEN__ |
| 170 | emscripten_set_main_loop(main_loop, 0, 0); |
| 171 | #else |
| 172 | while (1) { |
| 173 | main_loop(); |
| 174 | usleep(1000); |
| 175 | } |
| 176 | #endif |
| 177 | return 0; |
| 178 | } |
nothing calls this directly
no test coverage detected