This is like socketpair but uses tcp. The function guarantees that nobody * else can attach to the socket, or if they do that this function fails and * the socket gets closed. Returns 0 on success, -1 on failure. The resulting * file descriptors are symmetrical. Currently only for RSYNC_CONNECT_PROG. */
| 742 | * the socket gets closed. Returns 0 on success, -1 on failure. The resulting |
| 743 | * file descriptors are symmetrical. Currently only for RSYNC_CONNECT_PROG. */ |
| 744 | static int socketpair_tcp(int fd[2]) |
| 745 | { |
| 746 | int listener; |
| 747 | struct sockaddr_in sock; |
| 748 | struct sockaddr_in sock2; |
| 749 | socklen_t socklen = sizeof sock; |
| 750 | int connect_done = 0; |
| 751 | |
| 752 | fd[0] = fd[1] = listener = -1; |
| 753 | |
| 754 | memset(&sock, 0, sizeof sock); |
| 755 | |
| 756 | if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) |
| 757 | goto failed; |
| 758 | |
| 759 | memset(&sock2, 0, sizeof sock2); |
| 760 | #ifdef HAVE_SOCKADDR_IN_LEN |
| 761 | sock2.sin_len = sizeof sock2; |
| 762 | #endif |
| 763 | sock2.sin_family = PF_INET; |
| 764 | sock2.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 765 | |
| 766 | if (bind(listener, (struct sockaddr *)&sock2, sizeof sock2) != 0 |
| 767 | || listen(listener, 1) != 0 |
| 768 | || getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0 |
| 769 | || (fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) |
| 770 | goto failed; |
| 771 | |
| 772 | set_nonblocking(fd[1]); |
| 773 | |
| 774 | sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 775 | |
| 776 | if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) == -1) { |
| 777 | if (errno != EINPROGRESS) |
| 778 | goto failed; |
| 779 | } else |
| 780 | connect_done = 1; |
| 781 | |
| 782 | if ((fd[0] = accept(listener, (struct sockaddr *)&sock2, &socklen)) == -1) |
| 783 | goto failed; |
| 784 | |
| 785 | close(listener); |
| 786 | listener = -1; |
| 787 | |
| 788 | set_blocking(fd[1]); |
| 789 | |
| 790 | if (connect_done == 0) { |
| 791 | if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0 && errno != EISCONN) |
| 792 | goto failed; |
| 793 | } |
| 794 | |
| 795 | /* all OK! */ |
| 796 | return 0; |
| 797 | |
| 798 | failed: |
| 799 | if (fd[0] != -1) |
| 800 | close(fd[0]); |
| 801 | if (fd[1] != -1) |
no test coverage detected