Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Unix domain sockets and emulate socketpair on Windows #10192

Merged
merged 3 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Working version

### Other libraries:

- #10192: Add support for Unix domain sockets on Windows and use them
to emulate Unix.socketpair (only available on Windows 1803+)
(Antonin Décimo, review by David Allsopp)

### Tools:

### Manual and documentation:
Expand Down
28 changes: 28 additions & 0 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1391,7 +1391,8 @@ sockets=true
AS_CASE([$host],
[*-*-mingw32|*-pc-windows],
[cclibs="$cclibs -lws2_32"
AC_SEARCH_LIBS([socket], [ws2_32])],
AC_SEARCH_LIBS([socket], [ws2_32])
AC_CHECK_FUNC([socketpair], [AC_DEFINE([HAS_SOCKETPAIR])])],
[*-*-haiku],
[cclibs="$cclibs -lnetwork"
AC_SEARCH_LIBS([socket], [network])],
Expand Down Expand Up @@ -1420,6 +1421,13 @@ AS_CASE([$host],

AC_CHECK_FUNC([inet_aton], [AC_DEFINE([HAS_INET_ATON])])

## Unix domain sockets support on Windows

AS_CASE([$host],
[*-*-mingw32|*-pc-windows],
[AC_CHECK_HEADERS([afunix.h], [AC_DEFINE([HAS_AFUNIX_H])], [],
[#include <winsock2.h>])])

## IPv6 support

ipv6=true
Expand Down
2 changes: 1 addition & 1 deletion manual/src/library/libunix.etex
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ processes}
\entree{"getpwnam", "getpwuid"}{always raise "Not_found"}
\entree{"getgrnam", "getgrgid"}{always raise "Not_found"}
\entree{type "socket_domain"}{"PF_INET" is fully supported;
"PF_INET6" is fully supported (since 4.01.0); "PF_UNIX" is not supported }
"PF_INET6" is fully supported (since 4.01.0); "PF_UNIX" is supported since 4.14.0, but only works on Windows 10 1803 and later.}
\entree{"establish_server"}{not implemented; use threads}
\entree{terminal functions ("tc*")}{not implemented}
\entree{"setsid"}{not implemented}
Expand Down
6 changes: 0 additions & 6 deletions otherlibs/unix/socketaddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ void get_sockaddr(value mladr,
socklen_param_type * adr_len /*out*/)
{
switch(Tag_val(mladr)) {
#ifndef _WIN32
case 0: /* ADDR_UNIX */
{ value path;
mlsize_t len;
Expand All @@ -75,7 +74,6 @@ void get_sockaddr(value mladr,
+ len;
break;
}
#endif
case 1: /* ADDR_INET */
#ifdef HAS_IPV6
if (caml_string_length(Field(mladr, 0)) == 16) {
Expand Down Expand Up @@ -114,16 +112,13 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/,
socklen_param_type adr_len, int close_on_error)
{
value res;
#ifndef _WIN32
if (adr_len < offsetof(struct sockaddr, sa_data)) {
// Only possible for an unnamed AF_UNIX socket, in
// which case sa_family might be uninitialized.
return alloc_unix_sockaddr(caml_alloc_string(0));
}
#endif

switch(adr->s_gen.sa_family) {
#ifndef _WIN32
case AF_UNIX:
{ /* Based on recommendation in section BUGS of Linux unix(7). See
http://man7.org/linux/man-pages/man7/unix.7.html. */
Expand All @@ -147,7 +142,6 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/,
);
break;
}
#endif
case AF_INET:
{ value a = alloc_inet_addr(&adr->s_inet.sin_addr);
Begin_root (a);
Expand Down
24 changes: 21 additions & 3 deletions otherlibs/unix/socketaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,27 @@
#define CAML_SOCKETADDR_H

#include "caml/misc.h"
#ifndef _WIN32

#ifdef _WIN32

/* Code duplication with runtime/debugger.c is inevitable, because
* pulling winsock2.h creates many naming conflicts. */
#include <winsock2.h>
#ifdef HAS_AFUNIX_H
#include <afunix.h>
#else
#define UNIX_PATH_MAX 108

struct sockaddr_un {
ADDRESS_FAMILY sun_family;
char sun_path[UNIX_PATH_MAX];
};

#define SIO_AF_UNIX_GETPEERPID _WSAIOR(IOC_VENDOR, 256)

#endif

#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
Expand All @@ -27,9 +47,7 @@

union sock_addr_union {
struct sockaddr s_gen;
#ifndef _WIN32
struct sockaddr_un s_unix;
#endif
struct sockaddr_in s_inet;
#ifdef HAS_IPV6
struct sockaddr_in6 s_inet6;
Expand Down
3 changes: 2 additions & 1 deletion otherlibs/unix/unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -1403,7 +1403,8 @@ type socket_domain =
(** The type of socket domains. Not all platforms support
IPv6 sockets (type [PF_INET6]).

On Windows: [PF_UNIX] not implemented. *)
On Windows: [PF_UNIX] supported since 4.14.0 on Windows 10 1803
and later. *)

type socket_type =
SOCK_STREAM (** Stream socket *)
Expand Down
3 changes: 2 additions & 1 deletion otherlibs/unix/unixLabels.mli
Original file line number Diff line number Diff line change
Expand Up @@ -1403,7 +1403,8 @@ type socket_domain = Unix.socket_domain =
(** The type of socket domains. Not all platforms support
IPv6 sockets (type [PF_INET6]).

On Windows: [PF_UNIX] not implemented. *)
On Windows: [PF_UNIX] supported since 4.14.0 on Windows 10 1803
and later. *)

type socket_type = Unix.socket_type =
SOCK_STREAM (** Stream socket *)
Expand Down
2 changes: 1 addition & 1 deletion otherlibs/win32unix/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ WIN_FILES = accept.c bind.c channels.c close.c \
link.c listen.c lockf.c lseek.c nonblock.c \
mmap.c open.c pipe.c read.c readlink.c rename.c \
realpath.c select.c sendrecv.c \
shutdown.c sleep.c socket.c sockopt.c startup.c stat.c \
shutdown.c sleep.c socket.c socketpair.c sockopt.c startup.c stat.c \
symlink.c system.c times.c truncate.c unixsupport.c windir.c winwait.c \
write.c winlist.c winworker.c windbug.c utimes.c

Expand Down
5 changes: 1 addition & 4 deletions otherlibs/win32unix/accept.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ CAMLprim value unix_accept(value cloexec, value sock)
win32_maperr(err);
uerror("accept", Nothing);
}
/* This is a best effort, not guaranteed to work, so don't fail on error */
SetHandleInformation((HANDLE) snew,
HANDLE_FLAG_INHERIT,
unix_cloexec_p(cloexec) ? 0 : HANDLE_FLAG_INHERIT);
win_set_cloexec((HANDLE) snew, cloexec);
Begin_roots2 (fd, adr)
fd = win_alloc_socket(snew);
adr = alloc_sockaddr(&addr, addr_len, snew);
Expand Down
19 changes: 4 additions & 15 deletions otherlibs/win32unix/close_on.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,16 @@
#include "unixsupport.h"
#include <windows.h>

int win_set_inherit(value fd, BOOL inherit)
{
/* According to the MSDN, SetHandleInformation may not work
for console handles on WinNT4 and earlier versions. */
if (! SetHandleInformation(Handle_val(fd),
HANDLE_FLAG_INHERIT,
inherit ? HANDLE_FLAG_INHERIT : 0)) {
win32_maperr(GetLastError());
return -1;
}
return 0;
}

CAMLprim value win_set_close_on_exec(value fd)
{
if (win_set_inherit(fd, FALSE) == -1) uerror("set_close_on_exec", Nothing);
if (win_set_inherit(Handle_val(fd), FALSE) == -1)
uerror("set_close_on_exec", Nothing);
return Val_unit;
}

CAMLprim value win_clear_close_on_exec(value fd)
{
if (win_set_inherit(fd, TRUE) == -1) uerror("clear_close_on_exec", Nothing);
if (win_set_inherit(Handle_val(fd), TRUE) == -1)
uerror("clear_close_on_exec", Nothing);
return Val_unit;
}
5 changes: 1 addition & 4 deletions otherlibs/win32unix/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ CAMLprim value unix_socket(value cloexec, value domain, value type, value proto)
win32_maperr(WSAGetLastError());
uerror("socket", Nothing);
}
/* This is a best effort, not guaranteed to work, so don't fail on error */
SetHandleInformation((HANDLE) s,
HANDLE_FLAG_INHERIT,
unix_cloexec_p(cloexec) ? 0 : HANDLE_FLAG_INHERIT);
win_set_cloexec((HANDLE) s, cloexec);
return win_alloc_socket(s);
}