Skip to content

Commit

Permalink
PR#5676: add ipv6 support on Windows.
Browse files Browse the repository at this point in the history
Patch by Jérôme Vouillon <Jerome.Vouillon@pps.jussieu.fr>

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@12710 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
  • Loading branch information
Jonathan Protzenko authored and Jonathan Protzenko committed Jul 13, 2012
1 parent 776c46f commit 7bb9ab2
Show file tree
Hide file tree
Showing 20 changed files with 124 additions and 29 deletions.
1 change: 1 addition & 0 deletions config/s-nt.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@
#define HAS_PUTENV
#define HAS_LOCALE
#define HAS_BROKEN_PRINTF
#define HAS_IPV6
35 changes: 35 additions & 0 deletions otherlibs/unix/addrofstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
/* $Id$ */

#include <mlvalues.h>
#include <memory.h>
#include <fail.h>
#include "unixsupport.h"

Expand All @@ -24,6 +25,39 @@
CAMLprim value unix_inet_addr_of_string(value s)
{
#if defined(HAS_IPV6)
#ifdef _WIN32
CAMLparam1(s);
CAMLlocal1(vres);
struct addrinfo hints;
struct addrinfo * res;
int retcode;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
retcode = getaddrinfo(String_val(s), NULL, &hints, &res);
if (retcode != 0) failwith("inet_addr_of_string");
switch (res->ai_addr->sa_family) {
case AF_INET:
{
vres =
alloc_inet_addr(&((struct sockaddr_in *) res->ai_addr)->sin_addr);
break;
}
case AF_INET6:
{
vres =
alloc_inet6_addr(&((struct sockaddr_in6 *) res->ai_addr)->sin6_addr);
break;
}
default:
{
freeaddrinfo(res);
failwith("inet_addr_of_string");
}
}
freeaddrinfo(res);
CAMLreturn (vres);
#else
struct in_addr address;
struct in6_addr address6;
if (inet_pton(AF_INET, String_val(s), &address) > 0)
Expand All @@ -32,6 +66,7 @@ CAMLprim value unix_inet_addr_of_string(value s)
return alloc_inet6_addr(&address6);
else
failwith("inet_addr_of_string");
#endif
#elif defined(HAS_INET_ATON)
struct in_addr address;
if (inet_aton(String_val(s), &address) == 0)
Expand Down
4 changes: 1 addition & 3 deletions otherlibs/unix/gethostname.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
#include <mlvalues.h>
#include <alloc.h>
#include <fail.h>
#if defined (_WIN32)
#include <winsock.h>
#else
#ifndef _WIN32
#include <sys/param.h>
#endif
#include "unixsupport.h"
Expand Down
2 changes: 0 additions & 2 deletions otherlibs/unix/getproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

#ifndef _WIN32
#include <netdb.h>
#else
#include <winsock.h>
#endif

static value alloc_proto_entry(struct protoent *entry)
Expand Down
2 changes: 0 additions & 2 deletions otherlibs/unix/getserv.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#else
#include <winsock.h>
#endif

static value alloc_service_entry(struct servent *entry)
Expand Down
24 changes: 24 additions & 0 deletions otherlibs/unix/strofaddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ CAMLprim value unix_string_of_inet_addr(value a)
{
char * res;
#ifdef HAS_IPV6
#ifdef _WIN32
char buffer[64];
union sock_addr_union sa;
int len;
int retcode;
if (string_length(a) == 16) {
memset(&sa.s_inet6, 0, sizeof(struct sockaddr_in6));
sa.s_inet6.sin6_family = AF_INET6;
sa.s_inet6.sin6_addr = GET_INET6_ADDR(a);
len = sizeof(struct sockaddr_in6);
} else {
memset(&sa.s_inet, 0, sizeof(struct sockaddr_in));
sa.s_inet.sin_family = AF_INET;
sa.s_inet.sin_addr = GET_INET_ADDR(a);
len = sizeof(struct sockaddr_in);
}
retcode = getnameinfo
(&sa.s_gen, len, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST);
if (retcode != 0)
res = NULL;
else
res = buffer;
#else
char buffer[64];
if (string_length(a) == 16)
res = (char *)
Expand All @@ -35,6 +58,7 @@ CAMLprim value unix_string_of_inet_addr(value a)
res = (char *)
inet_ntop(AF_INET, (const void *) &GET_INET_ADDR(a),
buffer, sizeof(buffer));
#endif
#else
res = inet_ntoa(GET_INET_ADDR(a));
#endif
Expand Down
3 changes: 2 additions & 1 deletion otherlibs/win32unix/Makefile.nt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ WIN_FILES = accept.c bind.c channels.c close.c \
# Files from the ../unix directory
UNIX_FILES = access.c addrofstr.c chdir.c chmod.c cst2constr.c \
cstringv.c envir.c execv.c execve.c execvp.c \
exit.c getcwd.c gethost.c gethostname.c getproto.c \
exit.c getaddrinfo.c getcwd.c gethost.c gethostname.c \
getnameinfo.c getproto.c \
getserv.c gmtime.c putenv.c rmdir.c \
socketaddr.c strofaddr.c time.c unlink.c utimes.c

Expand Down
2 changes: 1 addition & 1 deletion otherlibs/win32unix/close_on.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
/* $Id$ */

#include <mlvalues.h>
#include <windows.h>
#include "unixsupport.h"
#include <windows.h>

int win_set_inherit(value fd, BOOL inherit)
{
Expand Down
2 changes: 1 addition & 1 deletion otherlibs/win32unix/createprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

/* $Id$ */

#include "unixsupport.h"
#include <windows.h>
#include <mlvalues.h>
#include <osdeps.h>
#include "unixsupport.h"

static int win_has_console(void);

Expand Down
2 changes: 1 addition & 1 deletion otherlibs/win32unix/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

/* $Id$ */

#include "unixsupport.h"
#include <windows.h>
#include <mlvalues.h>
#include <fail.h>
#include "unixsupport.h"

typedef
BOOL (WINAPI *tCreateHardLink)(
Expand Down
5 changes: 1 addition & 4 deletions otherlibs/win32unix/select.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@

/* $Id$ */

#include "winworker.h"
#include <mlvalues.h>
#include <alloc.h>
#include <memory.h>
#include <fail.h>
#include <signals.h>
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include "unixsupport.h"
#include "windbug.h"
#include "winworker.h"
#include "winlist.h"

/* This constant define the maximum number of objects that
Expand Down
9 changes: 8 additions & 1 deletion otherlibs/win32unix/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
#include "unixsupport.h"

int socket_domain_table[] = {
PF_UNIX, PF_INET /*, PF_INET6 */
PF_UNIX, PF_INET,
#if defined(HAS_IPV6)
PF_INET6
#else
0
#endif
};

int socket_type_table[] = {
Expand All @@ -29,11 +34,13 @@ CAMLprim value unix_socket(domain, type, proto)
{
SOCKET s;

#ifndef HAS_IPV6
/* IPv6 requires WinSock2, we must raise an error on PF_INET6 */
if (Int_val(domain) >= sizeof(socket_domain_table)/sizeof(int)) {
win32_maperr(WSAEPFNOSUPPORT);
uerror("socket", Nothing);
}
#endif

s = socket(socket_domain_table[Int_val(domain)],
socket_type_table[Int_val(type)],
Expand Down
8 changes: 8 additions & 0 deletions otherlibs/win32unix/socketaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
union sock_addr_union {
struct sockaddr s_gen;
struct sockaddr_in s_inet;
#ifdef HAS_IPV6
struct sockaddr_in6 s_inet6;
#endif
};

extern union sock_addr_union sock_addr;
Expand All @@ -35,3 +38,8 @@ CAMLprim value alloc_sockaddr (union sock_addr_union * addr /*in*/,
socklen_param_type addr_len, int close_on_error);
CAMLprim value alloc_inet_addr (struct in_addr * inaddr);
#define GET_INET_ADDR(v) (*((struct in_addr *) (v)))

#ifdef HAS_IPV6
CAMLexport value alloc_inet6_addr (struct in6_addr * inaddr);
#define GET_INET6_ADDR(v) (*((struct in6_addr *) (v)))
#endif
3 changes: 1 addition & 2 deletions otherlibs/win32unix/startup.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@
/* */
/***********************************************************************/

#include "winworker.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <mlvalues.h>
#include "unixsupport.h"
#include "winworker.h"
#include "windbug.h"

value val_process_id;
Expand Down
3 changes: 2 additions & 1 deletion otherlibs/win32unix/times.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "unixsupport.h"
#include <windows.h>
#include <mlvalues.h>
#include "unixsupport.h"
#include <alloc.h>


double to_sec(FILETIME ft) {
Expand Down
36 changes: 29 additions & 7 deletions otherlibs/win32unix/unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,11 @@ type getaddrinfo_option =
| AI_CANONNAME
| AI_PASSIVE

let getaddrinfo node service opts =
external getaddrinfo_system
: string -> string -> getaddrinfo_option list -> addr_info list
= "unix_getaddrinfo"

let getaddrinfo_emulation node service opts =
(* Parse options *)
let opt_socktype = ref None
and opt_protocol = ref 0
Expand Down Expand Up @@ -720,6 +724,12 @@ let getaddrinfo node service opts =
addresses)
ports)

let getaddrinfo node service opts =
try
List.rev(getaddrinfo_system node service opts)
with Invalid_argument _ ->
getaddrinfo_emulation node service opts

type name_info =
{ ni_hostname : string;
ni_service : string }
Expand All @@ -731,7 +741,11 @@ type getnameinfo_option =
| NI_NUMERICSERV
| NI_DGRAM

let getnameinfo addr opts =
external getnameinfo_system
: sockaddr -> getnameinfo_option list -> name_info
= "unix_getnameinfo"

let getnameinfo_emulation addr opts =
match addr with
| ADDR_UNIX f ->
{ ni_hostname = ""; ni_service = f } (* why not? *)
Expand All @@ -752,6 +766,12 @@ let getnameinfo addr opts =
string_of_int p in
{ ni_hostname = hostname; ni_service = service }

let getnameinfo addr opts =
try
getnameinfo_system addr opts
with Invalid_argument _ ->
getnameinfo_emulation addr opts

(* High-level process management (system, popen) *)

external win_create_process : string -> string -> string option ->
Expand Down Expand Up @@ -874,12 +894,14 @@ external select :
(* High-level network functions *)

let open_connection sockaddr =
let domain =
match sockaddr with ADDR_UNIX _ -> PF_UNIX | ADDR_INET(_,_) -> PF_INET in
let sock =
socket domain SOCK_STREAM 0 in
connect sock sockaddr;
(in_channel_of_descr sock, out_channel_of_descr sock)
socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in
try
connect sock sockaddr;
set_close_on_exec sock;
(in_channel_of_descr sock, out_channel_of_descr sock)
with exn ->
close sock; raise exn

let shutdown_connection inchan =
shutdown (descr_of_in_channel inchan) SHUTDOWN_SEND
Expand Down
6 changes: 5 additions & 1 deletion otherlibs/win32unix/unixsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
#include <direct.h>
#include <process.h>
#include <sys/types.h>
#include <winsock.h>
#include <winsock2.h>
#ifdef HAS_IPV6
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif

struct filedescr {
union {
Expand Down
2 changes: 1 addition & 1 deletion otherlibs/win32unix/winwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@

/* $Id$ */

#include "unixsupport.h"
#include <windows.h>
#include <mlvalues.h>
#include <alloc.h>
#include <memory.h>
#include "unixsupport.h"
#include <sys/types.h>
#include <signals.h>

Expand Down
3 changes: 2 additions & 1 deletion otherlibs/win32unix/winworker.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
#include "windbug.h"
#include <mlvalues.h>
#include <alloc.h>
#include "unixsupport.h"
#include <memory.h>
#include <signals.h>

typedef enum {
WORKER_CMD_NONE = 0,
Expand Down
1 change: 1 addition & 0 deletions otherlibs/win32unix/winworker.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define _WINWORKER_H

#define _WIN32_WINNT 0x0400
#include "unixsupport.h"
#include <windows.h>

/* Pool of worker threads.
Expand Down

0 comments on commit 7bb9ab2

Please sign in to comment.