/* * UNIX socketpair() implementation. Why? Because Windows does not have it. * Return 0 on success, -1 on error. */ static int my_socketpair(struct conn *c, int sp[2]) { struct sockaddr_in sa; int sock, ret = -1; socklen_t len = sizeof(sa); (void) memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(0); sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { elog(E_LOG, c, "mysocketpair: socket(): %d", ERRNO); } else if (bind(sock, (struct sockaddr *) &sa, len) != 0) { elog(E_LOG, c, "mysocketpair: bind(): %d", ERRNO); (void) closesocket(sock); } else if (listen(sock, 1) != 0) { elog(E_LOG, c, "mysocketpair: listen(): %d", ERRNO); (void) closesocket(sock); } else if (getsockname(sock, (struct sockaddr *) &sa, &len) != 0) { elog(E_LOG, c, "mysocketpair: getsockname(): %d", ERRNO); (void) closesocket(sock); } else if ((sp[0] = socket(AF_INET, SOCK_STREAM, 6)) == -1) { elog(E_LOG, c, "mysocketpair: socket(): %d", ERRNO); (void) closesocket(sock); } else if (connect(sp[0], (struct sockaddr *) &sa, len) != 0) { elog(E_LOG, c, "mysocketpair: connect(): %d", ERRNO); (void) closesocket(sock); (void) closesocket(sp[0]); } else if ((sp[1] = accept(sock,(struct sockaddr *) &sa, &len)) == -1) { elog(E_LOG, c, "mysocketpair: accept(): %d", ERRNO); (void) closesocket(sock); (void) closesocket(sp[0]); } else { /* Success */ ret = 0; (void) closesocket(sock); (void) set_non_blocking_mode(sp[0]); (void) set_non_blocking_mode(sp[1]); } #ifndef _WIN32 (void) fcntl(sp[0], F_SETFD, FD_CLOEXEC); (void) fcntl(sp[1], F_SETFD, FD_CLOEXEC); #endif /* _WIN32*/ return (ret); }
static void close_socket_gracefully(SOCKET sock) { char buf[BUFSIZ]; int n; // Send FIN to the client (void) shutdown(sock, SHUT_WR); set_non_blocking_mode(sock); // Read and discard pending data. If we do not do that and close the // socket, the data in the send buffer may be discarded. This // behaviour is seen on Windows, when client keeps sending data // when server decide to close the connection; then when client // does recv() it gets no data back. do { n = pull(sock, buf, sizeof(buf)); } while (n > 0); // Now we know that our FIN is ACK-ed, safe to close (void) close(sock); }