| 65 | } |
| 66 | |
| 67 | void main_loop(void) { |
| 68 | fd_set fdr, fdw; |
| 69 | struct timeval tv = {0}; |
| 70 | FD_ZERO(&fdr); |
| 71 | FD_ZERO(&fdw); |
| 72 | FD_SET(listen_fd, &fdr); |
| 73 | FD_SET(client_fd, &fdr); |
| 74 | FD_SET(client_fd, &fdw); |
| 75 | if (peer_fd >= 0) FD_SET(peer_fd, &fdr); |
| 76 | select(64, &fdr, &fdw, NULL, &tv); |
| 77 | |
| 78 | // server: accept the incoming connection |
| 79 | if (peer_fd < 0 && FD_ISSET(listen_fd, &fdr)) { |
| 80 | struct sockaddr_in ca; |
| 81 | socklen_t cl = sizeof(ca); |
| 82 | peer_fd = accept(listen_fd, (struct sockaddr*)&ca, &cl); |
| 83 | if (peer_fd >= 0) { |
| 84 | set_nonblocking(peer_fd); |
| 85 | printf("accepted from %s:%u\n", inet_ntoa(ca.sin_addr), (unsigned)ntohs(ca.sin_port)); |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | // client: connect completion (retry while the listener is coming up) |
| 90 | if (!connected && FD_ISSET(client_fd, &fdw)) { |
| 91 | int err = 0; |
| 92 | socklen_t l = sizeof(err); |
| 93 | getsockopt(client_fd, SOL_SOCKET, SO_ERROR, &err, &l); |
| 94 | if (err == ECONNREFUSED || err == ECONNRESET) { |
| 95 | start_client(); |
| 96 | return; |
| 97 | } |
| 98 | assert(err == 0 && "connect failed"); |
| 99 | connected = true; |
| 100 | printf("connected\n"); |
| 101 | } |
| 102 | |
| 103 | // client: send ping |
| 104 | if (connected && !ping_sent && FD_ISSET(client_fd, &fdw)) { |
| 105 | if (send(client_fd, "ping", 4, 0) == 4) ping_sent = true; |
| 106 | } |
| 107 | |
| 108 | // server: echo ping -> pong |
| 109 | if (peer_fd >= 0 && !pong_sent && FD_ISSET(peer_fd, &fdr)) { |
| 110 | char buf[4]; |
| 111 | ssize_t n = recv(peer_fd, buf, sizeof(buf), 0); |
| 112 | if (n == 4 && memcmp(buf, "ping", 4) == 0) { |
| 113 | send(peer_fd, "pong", 4, 0); |
| 114 | pong_sent = true; |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | // client: receive pong |
| 119 | if (ping_sent && FD_ISSET(client_fd, &fdr)) { |
| 120 | char buf[4]; |
| 121 | ssize_t n = recv(client_fd, buf, sizeof(buf), 0); |
| 122 | if (n == 4 && memcmp(buf, "pong", 4) == 0) { |
| 123 | test_success(); |
| 124 | } else if (n == 0) { |
no test coverage detected