From dfc2f70876956531970b2ceb370a7004a7cb22ea Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 18 Nov 2019 18:08:47 +0100 Subject: [PATCH] socket: add support for opening socket pairs --- socket.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ socket.h | 1 + 2 files changed, 60 insertions(+) diff --git a/socket.c b/socket.c index 7126fab..acbc2c4 100644 --- a/socket.c +++ b/socket.c @@ -243,6 +243,30 @@ open_socket(int domain, int type, int flags) /* ================================================== */ +static int +open_socket_pair(int domain, int type, int flags, int *other_fd) +{ + int sock_fds[2]; + + if (socketpair(domain, type | get_open_flags(flags), 0, sock_fds) < 0) { + DEBUG_LOG("Could not open %s socket : %s", + domain_to_string(domain), strerror(errno)); + return INVALID_SOCK_FD; + } + + if (!set_socket_flags(sock_fds[0], flags) || !set_socket_flags(sock_fds[1], flags)) { + close(sock_fds[0]); + close(sock_fds[1]); + return INVALID_SOCK_FD; + } + + *other_fd = sock_fds[1]; + + return sock_fds[0]; +} + +/* ================================================== */ + static int set_socket_options(int sock_fd, int flags) { @@ -520,6 +544,22 @@ error: /* ================================================== */ +static int +open_unix_socket_pair(int type, int flags, int *other_fd) +{ + int sock_fd; + + sock_fd = open_socket_pair(AF_UNIX, type, flags, other_fd); + if (sock_fd < 0) + return INVALID_SOCK_FD; + + DEBUG_LOG("Opened Unix socket pair fd1=%d fd2=%d", sock_fd, *other_fd); + + return sock_fd; +} + +/* ================================================== */ + static int get_recv_flags(int flags) { @@ -1159,6 +1199,25 @@ SCK_OpenUnixStreamSocket(const char *remote_addr, const char *local_addr, int fl /* ================================================== */ +int +SCK_OpenUnixSocketPair(int flags, int *other_fd) +{ + int sock_fd; + + /* Prefer SEQPACKET sockets over DGRAM in order to receive a zero-length + message (end of file) when the other end is unexpectedly closed */ + if ( +#ifdef SOCK_SEQPACKET + (sock_fd = open_unix_socket_pair(SOCK_SEQPACKET, flags, other_fd)) < 0 && +#endif + (sock_fd = open_unix_socket_pair(SOCK_DGRAM, flags, other_fd)) < 0) + return INVALID_SOCK_FD; + + return sock_fd; +} + +/* ================================================== */ + int SCK_SetIntOption(int sock_fd, int level, int name, int value) { diff --git a/socket.h b/socket.h index 47b9b5b..9d4a38e 100644 --- a/socket.h +++ b/socket.h @@ -98,6 +98,7 @@ extern int SCK_OpenUnixDatagramSocket(const char *remote_addr, const char *local int flags); extern int SCK_OpenUnixStreamSocket(const char *remote_addr, const char *local_addr, int flags); +extern int SCK_OpenUnixSocketPair(int flags, int *other_fd); /* Set and get a socket option of int size */ extern int SCK_SetIntOption(int sock_fd, int level, int name, int value);