Skip to content

Commit

Permalink
Merge pull request #10192 from MisterDA/windows-unix-domain-sockets-s…
Browse files Browse the repository at this point in the history
…ocketpair

Support Unix domain sockets and emulate socketpair on Windows
  • Loading branch information
dra27 committed Jun 23, 2021
2 parents 11c5f76 + fe2dab7 commit f68acd1
Show file tree
Hide file tree
Showing 21 changed files with 359 additions and 47 deletions.
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);
}

0 comments on commit f68acd1

Please sign in to comment.