From 0524526e41036f809a6522e7c651d9d382148c6a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Oct 2025 17:26:40 +0900 Subject: [PATCH] mruby-socket: introduce HAL for platform abstraction separate platform-specific socket operations into HAL implementations for POSIX (Linux/macOS/BSD/Unix) and Windows platforms to improve portability and maintainability Co-authored-by: Claude --- mrbgems/hal-posix-socket/mrbgem.rake | 8 + mrbgems/hal-posix-socket/src/socket_hal.c | 158 ++++++++++++++++++++ mrbgems/hal-win-socket/mrbgem.rake | 12 ++ mrbgems/hal-win-socket/src/socket_hal.c | 174 ++++++++++++++++++++++ mrbgems/mruby-socket/include/socket_hal.h | 83 +++++++++++ mrbgems/mruby-socket/mrbgem.rake | 32 +++- mrbgems/mruby-socket/src/socket.c | 135 +++-------------- 7 files changed, 478 insertions(+), 124 deletions(-) create mode 100644 mrbgems/hal-posix-socket/mrbgem.rake create mode 100644 mrbgems/hal-posix-socket/src/socket_hal.c create mode 100644 mrbgems/hal-win-socket/mrbgem.rake create mode 100644 mrbgems/hal-win-socket/src/socket_hal.c create mode 100644 mrbgems/mruby-socket/include/socket_hal.h diff --git a/mrbgems/hal-posix-socket/mrbgem.rake b/mrbgems/hal-posix-socket/mrbgem.rake new file mode 100644 index 000000000..14dca040a --- /dev/null +++ b/mrbgems/hal-posix-socket/mrbgem.rake @@ -0,0 +1,8 @@ +MRuby::Gem::Specification.new('hal-posix-socket') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'POSIX HAL for mruby-socket (Linux, macOS, BSD, Unix)' + + # HAL gem depends on feature gem - brings in mruby-socket automatically + spec.add_dependency 'mruby-socket', core: 'mruby-socket' +end diff --git a/mrbgems/hal-posix-socket/src/socket_hal.c b/mrbgems/hal-posix-socket/src/socket_hal.c new file mode 100644 index 000000000..858b0e9b7 --- /dev/null +++ b/mrbgems/hal-posix-socket/src/socket_hal.c @@ -0,0 +1,158 @@ +/* +** socket_hal.c - POSIX HAL implementation for mruby-socket +** +** See Copyright Notice in mruby.h +** +** POSIX implementation for socket operations using standard POSIX APIs. +** Supported platforms: Linux, macOS, BSD, Unix +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Socket HAL Initialization/Finalization + */ + +void +mrb_socket_hal_init(mrb_state *mrb) +{ + (void)mrb; + /* No initialization needed for POSIX sockets */ +} + +void +mrb_socket_hal_final(mrb_state *mrb) +{ + (void)mrb; + /* No cleanup needed for POSIX sockets */ +} + +/* + * Socket Control Operations + */ + +int +mrb_socket_hal_set_nonblock(mrb_state *mrb, int fd, int nonblock) +{ + (void)mrb; + + int flags = fcntl(fd, F_GETFL, 0); + if (flags == -1) { + return -1; + } + + if (nonblock) { + flags |= O_NONBLOCK; + } + else { + flags &= ~O_NONBLOCK; + } + + if (fcntl(fd, F_SETFL, flags) == -1) { + return -1; + } + + return 0; +} + +/* + * Address Conversion Functions + */ + +const char* +mrb_socket_hal_inet_ntop(int af, const void *src, char *dst, size_t size) +{ + return inet_ntop(af, src, dst, (socklen_t)size); +} + +int +mrb_socket_hal_inet_pton(int af, const char *src, void *dst) +{ + return inet_pton(af, src, dst); +} + +/* + * Platform-Specific Socket Features + */ + +mrb_value +mrb_socket_hal_sockaddr_un(mrb_state *mrb, const char *path, size_t pathlen) +{ + struct sockaddr_un *sunp; + + if (pathlen > sizeof(sunp->sun_path) - 1) { + mrb_raisef(mrb, mrb_class_get_id(mrb, MRB_SYM(ArgumentError)), + "too long unix socket path (max: %d bytes)", + (int)sizeof(sunp->sun_path) - 1); + } + + mrb_value s = mrb_str_new_capa(mrb, sizeof(struct sockaddr_un)); + sunp = (struct sockaddr_un*)RSTRING_PTR(s); + +#ifdef HAVE_SA_LEN + sunp->sun_len = sizeof(struct sockaddr_un); +#endif + + sunp->sun_family = AF_UNIX; + memcpy(sunp->sun_path, path, pathlen); + sunp->sun_path[pathlen] = '\0'; + mrb_str_resize(mrb, s, sizeof(struct sockaddr_un)); + + return s; +} + +int +mrb_socket_hal_socketpair(mrb_state *mrb, int domain, int type, int protocol, int sv[2]) +{ + (void)mrb; + return socketpair(domain, type, protocol, sv); +} + +mrb_value +mrb_socket_hal_unix_path(mrb_state *mrb, const char *sockaddr, size_t socklen) +{ + const struct sockaddr *sa = (const struct sockaddr*)sockaddr; + + if (sa->sa_family != AF_UNIX) { + mrb_raise(mrb, mrb_class_get_id(mrb, MRB_SYM(SocketError)), "need AF_UNIX address"); + } + + if (socklen < offsetof(struct sockaddr_un, sun_path) + 1) { + return mrb_str_new(mrb, "", 0); + } + + return mrb_str_new_cstr(mrb, ((const struct sockaddr_un*)sockaddr)->sun_path); +} + +/* + * Gem initialization + */ + +void +mrb_hal_posix_socket_gem_init(mrb_state *mrb) +{ + (void)mrb; + /* HAL interface functions are called by mruby-socket gem */ +} + +void +mrb_hal_posix_socket_gem_final(mrb_state *mrb) +{ + (void)mrb; + /* Cleanup handled by mrb_socket_hal_final called from mruby-socket */ +} diff --git a/mrbgems/hal-win-socket/mrbgem.rake b/mrbgems/hal-win-socket/mrbgem.rake new file mode 100644 index 000000000..d959c87e6 --- /dev/null +++ b/mrbgems/hal-win-socket/mrbgem.rake @@ -0,0 +1,12 @@ +MRuby::Gem::Specification.new('hal-win-socket') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Windows HAL for mruby-socket (Windows, MinGW)' + + # HAL gem depends on feature gem - brings in mruby-socket automatically + spec.add_dependency 'mruby-socket', core: 'mruby-socket' + + # Link Windows socket libraries + spec.linker.libraries << "wsock32" + spec.linker.libraries << "ws2_32" +end diff --git a/mrbgems/hal-win-socket/src/socket_hal.c b/mrbgems/hal-win-socket/src/socket_hal.c new file mode 100644 index 000000000..b24efaa2b --- /dev/null +++ b/mrbgems/hal-win-socket/src/socket_hal.c @@ -0,0 +1,174 @@ +/* +** socket_hal.c - Windows HAL implementation for mruby-socket +** +** See Copyright Notice in mruby.h +** +** Windows implementation for socket operations using Winsock APIs. +** Supported platforms: Windows, MinGW +*/ + +#include +#include +#include +#include +#include +#include + +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include + +/* + * Socket HAL Initialization/Finalization + */ + +void +mrb_socket_hal_init(mrb_state *mrb) +{ + WSADATA wsaData; + int result = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (result != NO_ERROR) { + mrb_raise(mrb, mrb_class_get_id(mrb, MRB_SYM(RuntimeError)), "WSAStartup failed"); + } +} + +void +mrb_socket_hal_final(mrb_state *mrb) +{ + (void)mrb; + WSACleanup(); +} + +/* + * Socket Control Operations + */ + +int +mrb_socket_hal_set_nonblock(mrb_state *mrb, int fd, int nonblock) +{ + (void)mrb; + u_long mode = nonblock ? 1 : 0; + int result = ioctlsocket(fd, FIONBIO, &mode); + if (result != NO_ERROR) { + return -1; + } + return 0; +} + +/* + * Address Conversion Functions + */ + +const char* +mrb_socket_hal_inet_ntop(int af, const void *src, char *dst, size_t size) +{ + if (af == AF_INET) { + struct sockaddr_in in = {0}; + in.sin_family = AF_INET; + memcpy(&in.sin_addr, src, sizeof(struct in_addr)); + if (getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in), + dst, (DWORD)size, NULL, 0, NI_NUMERICHOST) == 0) { + return dst; + } + return NULL; + } + else if (af == AF_INET6) { + struct sockaddr_in6 in = {0}; + in.sin6_family = AF_INET6; + memcpy(&in.sin6_addr, src, sizeof(struct in6_addr)); + if (getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in6), + dst, (DWORD)size, NULL, 0, NI_NUMERICHOST) == 0) { + return dst; + } + return NULL; + } + return NULL; +} + +int +mrb_socket_hal_inet_pton(int af, const char *src, void *dst) +{ + struct addrinfo hints = {0}; + hints.ai_family = af; + hints.ai_flags = AI_NUMERICHOST; + + struct addrinfo *res; + if (getaddrinfo(src, NULL, &hints, &res) != 0) { + return 0; /* Invalid address */ + } + + if (res == NULL) { + return 0; + } + + if (af == AF_INET && res->ai_family == AF_INET) { + memcpy(dst, &((struct sockaddr_in*)res->ai_addr)->sin_addr, sizeof(struct in_addr)); + freeaddrinfo(res); + return 1; + } + else if (af == AF_INET6 && res->ai_family == AF_INET6) { + memcpy(dst, &((struct sockaddr_in6*)res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + freeaddrinfo(res); + return 1; + } + + freeaddrinfo(res); + return 0; +} + +/* + * Platform-Specific Socket Features + */ + +mrb_value +mrb_socket_hal_sockaddr_un(mrb_state *mrb, const char *path, size_t pathlen) +{ + (void)path; + (void)pathlen; + mrb_raise(mrb, mrb_class_get_id(mrb, MRB_SYM(NotImplementedError)), + "sockaddr_un unsupported on Windows"); + return mrb_nil_value(); +} + +int +mrb_socket_hal_socketpair(mrb_state *mrb, int domain, int type, int protocol, int sv[2]) +{ + (void)mrb; + (void)domain; + (void)type; + (void)protocol; + (void)sv; + /* socketpair is not supported on Windows */ + errno = ENOSYS; + return -1; +} + +mrb_value +mrb_socket_hal_unix_path(mrb_state *mrb, const char *sockaddr, size_t socklen) +{ + (void)sockaddr; + (void)socklen; + mrb_raise(mrb, mrb_class_get_id(mrb, MRB_SYM(NotImplementedError)), + "unix_path unsupported on Windows"); + return mrb_nil_value(); +} + +/* + * Gem initialization + */ + +void +mrb_hal_win_socket_gem_init(mrb_state *mrb) +{ + (void)mrb; + /* HAL interface functions are called by mruby-socket gem */ +} + +void +mrb_hal_win_socket_gem_final(mrb_state *mrb) +{ + (void)mrb; + /* Cleanup handled by mrb_socket_hal_final called from mruby-socket */ +} diff --git a/mrbgems/mruby-socket/include/socket_hal.h b/mrbgems/mruby-socket/include/socket_hal.h new file mode 100644 index 000000000..c9dbeed67 --- /dev/null +++ b/mrbgems/mruby-socket/include/socket_hal.h @@ -0,0 +1,83 @@ +/* +** socket_hal.h - Socket HAL (Hardware Abstraction Layer) interface +** +** See Copyright Notice in mruby.h +** +** This header defines the platform-independent socket HAL interface. +** Platform-specific implementations are provided by HAL gems: +** - hal-posix-socket: POSIX socket implementation (Linux, macOS, BSD, Unix) +** - hal-win-socket: Windows socket implementation (Windows, MinGW) +*/ + +#ifndef MRUBY_SOCKET_HAL_H +#define MRUBY_SOCKET_HAL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Socket HAL Initialization/Finalization + */ + +/* Initialize socket subsystem (e.g., WSAStartup on Windows) */ +void mrb_socket_hal_init(mrb_state *mrb); + +/* Finalize socket subsystem (e.g., WSACleanup on Windows) */ +void mrb_socket_hal_final(mrb_state *mrb); + +/* + * Socket Control Operations + */ + +/* Set non-blocking mode on socket + * Returns 0 on success, -1 on error (sets errno) */ +int mrb_socket_hal_set_nonblock(mrb_state *mrb, int fd, int nonblock); + +/* + * Address Conversion Functions + */ + +/* Convert network address to presentation format (string) + * af: address family (AF_INET, AF_INET6) + * src: network address in binary form + * dst: buffer for string result + * size: size of dst buffer + * Returns: dst on success, NULL on error */ +const char* mrb_socket_hal_inet_ntop(int af, const void *src, char *dst, size_t size); + +/* Convert presentation format (string) to network address + * af: address family (AF_INET, AF_INET6) + * src: string representation of address + * dst: buffer for network address result + * Returns: 1 on success, 0 if src is not valid, -1 on error */ +int mrb_socket_hal_inet_pton(int af, const char *src, void *dst); + +/* + * Platform-Specific Socket Features + */ + +/* Create Unix domain socket address structure + * path: Unix socket path + * Returns: packed sockaddr string, or raises exception if not supported */ +mrb_value mrb_socket_hal_sockaddr_un(mrb_state *mrb, const char *path, size_t pathlen); + +/* Create a pair of connected sockets + * domain: address family (e.g., AF_UNIX) + * type: socket type (e.g., SOCK_STREAM) + * protocol: protocol (usually 0) + * sv: array to receive the two socket descriptors + * Returns: 0 on success, -1 on error (sets errno) */ +int mrb_socket_hal_socketpair(mrb_state *mrb, int domain, int type, int protocol, int sv[2]); + +/* Get Unix socket path from sockaddr + * Returns: Unix socket path string, or raises exception if not supported */ +mrb_value mrb_socket_hal_unix_path(mrb_state *mrb, const char *sockaddr, size_t socklen); + +#ifdef __cplusplus +} +#endif + +#endif /* MRUBY_SOCKET_HAL_H */ diff --git a/mrbgems/mruby-socket/mrbgem.rake b/mrbgems/mruby-socket/mrbgem.rake index c3684cd0c..0702f5e0d 100644 --- a/mrbgems/mruby-socket/mrbgem.rake +++ b/mrbgems/mruby-socket/mrbgem.rake @@ -5,13 +5,33 @@ MRuby::Gem::Specification.new('mruby-socket') do |spec| #spec.cc.defines << "HAVE_SA_LEN=0" - # If Windows, use winsock - if spec.for_windows? - spec.linker.libraries << "wsock32" - spec.linker.libraries << "ws2_32" - end - spec.add_dependency('mruby-io', :core => 'mruby-io') spec.add_dependency('mruby-error', :core => 'mruby-error') # spec.add_dependency('mruby-mtest') + + # Check if HAL gem is loaded + # HAL gems must be explicitly specified in build config (recommended) or via auto-selection below + spec.build.gems.one? { |g| g.name =~ /^hal-.*-socket$/ } or begin + # No HAL found - determine appropriate error message or auto-load + suggested_hal = if spec.for_windows? + 'hal-win-socket' + elsif RUBY_PLATFORM =~ /linux|darwin|bsd/ + 'hal-posix-socket' + else + nil + end + + if suggested_hal + # Auto-load HAL gem for convenience (for development) + # This works because HAL gems declare dependency on mruby-socket + warn "mruby-socket: No HAL specified, loading #{suggested_hal} (explicit selection recommended)" + spec.build.gem core: suggested_hal + else + # Unknown platform - fail with helpful message + fail "mruby-socket: No HAL available for platform '#{RUBY_PLATFORM}'.\n" \ + "Please specify HAL gem explicitly in your build config:\n" \ + " conf.gem core: 'hal-posix-socket' # For Linux/macOS/BSD\n" \ + " conf.gem core: 'hal-win-socket' # For Windows" + end + end end diff --git a/mrbgems/mruby-socket/src/socket.c b/mrbgems/mruby-socket/src/socket.c index dba421c34..ebe4a62e7 100644 --- a/mrbgems/mruby-socket/src/socket.c +++ b/mrbgems/mruby-socket/src/socket.c @@ -6,12 +6,9 @@ #ifdef _WIN32 #define _WIN32_WINNT 0x0501 - #include #include #include - #include - #define SHUT_RDWR SD_BOTH typedef int fsize_t; #else @@ -42,6 +39,7 @@ #include #include +#include /* Address family information for compact lookup table */ typedef struct { @@ -137,53 +135,6 @@ static inline const char *get_pf_name(int family) { #define E_SOCKET_ERROR mrb_class_get_id(mrb, MRB_SYM(SocketError)) -#ifdef _WIN32 -/* Windows implementation of inet_ntop - converts network address to string */ -static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) -{ - if (af == AF_INET) { - struct sockaddr_in in = {0}; - - in.sin_family = AF_INET; - memcpy(&in.sin_addr, src, sizeof(struct in_addr)); - getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in), - dst, cnt, NULL, 0, NI_NUMERICHOST); - return dst; - } - else if (af == AF_INET6) { - struct sockaddr_in6 in = {0}; - - in.sin6_family = AF_INET6; - memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); - getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in6), - dst, cnt, NULL, 0, NI_NUMERICHOST); - return dst; - } - return NULL; -} - -/* Windows implementation of inet_pton - converts string address to network format */ -static int inet_pton(int af, const char *src, void *dst) -{ - struct addrinfo hints = {0}; - hints.ai_family = af; - - struct addrinfo *res; - if (getaddrinfo(src, NULL, &hints, &res) != 0) { - printf("Couldn't resolve host %s\n", src); - return -1; - } - - for (struct addrinfo *r = res; r; r = r->ai_next) { - memcpy(dst, r->ai_addr, r->ai_addrlen); - } - - freeaddrinfo(res); - return 0; -} - -#endif - struct gen_addrinfo_args { struct RClass *klass; struct addrinfo *addrinfo; @@ -306,7 +257,6 @@ mrb_addrinfo_getnameinfo(mrb_state *mrb, mrb_value self) return ary; } -#ifndef _WIN32 /* * call-seq: * addrinfo.unix_path -> string @@ -320,16 +270,12 @@ mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self) { mrb_value sastr = mrb_iv_get(mrb, self, MRB_IVSYM(sockaddr)); - if (!mrb_string_p(sastr) || ((struct sockaddr*)RSTRING_PTR(sastr))->sa_family != AF_UNIX) - mrb_raise(mrb, E_SOCKET_ERROR, "need AF_UNIX address"); - if (RSTRING_LEN(sastr) < (mrb_int)offsetof(struct sockaddr_un, sun_path) + 1) { - return mrb_str_new(mrb, "", 0); - } - else { - return mrb_str_new_cstr(mrb, ((struct sockaddr_un*)RSTRING_PTR(sastr))->sun_path); + if (!mrb_string_p(sastr)) { + mrb_raise(mrb, E_SOCKET_ERROR, "invalid sockaddr"); } + + return mrb_socket_hal_unix_path(mrb, RSTRING_PTR(sastr), (size_t)RSTRING_LEN(sastr)); } -#endif /* Helper to convert sockaddr to address list array [family, port, host, host] */ static mrb_value @@ -793,27 +739,13 @@ static mrb_value mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self) { mrb_bool nonblocking; -#ifdef _WIN32 - u_long mode = 1; -#endif mrb_get_args(mrb, "b", &nonblocking); int fd = socket_fd(mrb, self); -#ifdef _WIN32 - int flags = ioctlsocket(fd, FIONBIO, &mode); - if (flags != NO_ERROR) - mrb_sys_fail(mrb, "ioctlsocket"); -#else - int flags = fcntl(fd, F_GETFL, 0); - if (flags == 1) - mrb_sys_fail(mrb, "fcntl"); - if (nonblocking) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - if (fcntl(fd, F_SETFL, flags) == -1) - mrb_sys_fail(mrb, "fcntl"); -#endif + + if (mrb_socket_hal_set_nonblock(mrb, fd, nonblocking) == -1) + mrb_sys_fail(mrb, "set_nonblock"); + return mrb_nil_value(); } @@ -927,7 +859,7 @@ mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass) mrb_get_args(mrb, "is", &af, &addr, &n); if ((af == AF_INET && n != 4) || (af == AF_INET6 && n != 16) || - inet_ntop((int)af, addr, buf, sizeof(buf)) == NULL) + mrb_socket_hal_inet_ntop((int)af, addr, buf, sizeof(buf)) == NULL) mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address"); return mrb_str_new_cstr(mrb, buf); } @@ -954,13 +886,13 @@ mrb_ipsocket_pton(mrb_state *mrb, mrb_value klass) if (af == AF_INET) { struct in_addr in; - if (inet_pton(AF_INET, buf, (void*)&in.s_addr) != 1) + if (mrb_socket_hal_inet_pton(AF_INET, buf, (void*)&in.s_addr) != 1) goto invalid; return mrb_str_new(mrb, (char*)&in.s_addr, 4); } else if (af == AF_INET6) { struct in6_addr in6; - if (inet_pton(AF_INET6, buf, (void*)&in6.s6_addr) != 1) + if (mrb_socket_hal_inet_pton(AF_INET6, buf, (void*)&in6.s6_addr) != 1) goto invalid; return mrb_str_new(mrb, (char*)&in6.s6_addr, 16); } @@ -1156,28 +1088,10 @@ mrb_socket_sockaddr_family(mrb_state *mrb, mrb_value klass) static mrb_value mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass) { -#ifdef _WIN32 - mrb_raise(mrb, E_NOTIMP_ERROR, "sockaddr_un unsupported on Windows"); - return mrb_nil_value(); -#else mrb_value path; - struct sockaddr_un *sunp; mrb_get_args(mrb, "S", &path); - if ((size_t)RSTRING_LEN(path) > sizeof(sunp->sun_path) - 1) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "too long unix socket path (max: %d bytes)", (int)sizeof(sunp->sun_path) - 1); - } - mrb_value s = mrb_str_new_capa(mrb, sizeof(struct sockaddr_un)); - sunp = (struct sockaddr_un*)RSTRING_PTR(s); -#if HAVE_SA_LEN - sunp->sun_len = sizeof(struct sockaddr_un); -#endif - sunp->sun_family = AF_UNIX; - memcpy(sunp->sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); - sunp->sun_path[RSTRING_LEN(path)] = '\0'; - mrb_str_resize(mrb, s, sizeof(struct sockaddr_un)); - return s; -#endif + return mrb_socket_hal_sockaddr_un(mrb, RSTRING_PTR(path), (size_t)RSTRING_LEN(path)); } /* @@ -1193,24 +1107,19 @@ mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass) static mrb_value mrb_socket_socketpair(mrb_state *mrb, mrb_value klass) { -#ifdef _WIN32 - mrb_raise(mrb, E_NOTIMP_ERROR, "socketpair unsupported on Windows"); - return mrb_nil_value(); -#else mrb_int domain, type, protocol; int sv[2]; mrb_get_args(mrb, "iii", &domain, &type, &protocol); - mrb_value ary = mrb_ary_new_capa(mrb, 2); - if (socketpair(domain, type, protocol, sv) == -1) { + if (mrb_socket_hal_socketpair(mrb, (int)domain, (int)type, (int)protocol, sv) == -1) { mrb_sys_fail(mrb, "socketpair"); } + mrb_value ary = mrb_ary_new_capa(mrb, 2); mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[0])); mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[1])); return ary; -#endif } /* @@ -1357,20 +1266,12 @@ mrb_win32_basicsocket_syswrite(mrb_state *mrb, mrb_value self) void mrb_mruby_socket_gem_init(mrb_state* mrb) { -#ifdef _WIN32 - WSADATA wsaData; - int result; - result = WSAStartup(MAKEWORD(2,2), &wsaData); - if (result != NO_ERROR) - mrb_raise(mrb, E_RUNTIME_ERROR, "WSAStartup failed"); -#endif + mrb_socket_hal_init(mrb); struct RClass *ainfo = mrb_define_class_id(mrb, MRB_SYM(Addrinfo), mrb->object_class); mrb_define_class_method_id(mrb, ainfo, MRB_SYM(getaddrinfo), mrb_addrinfo_getaddrinfo, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(4)); mrb_define_method_id(mrb, ainfo, MRB_SYM(getnameinfo), mrb_addrinfo_getnameinfo, MRB_ARGS_OPT(1)); -#ifndef _WIN32 mrb_define_method_id(mrb, ainfo, MRB_SYM(unix_path), mrb_addrinfo_unix_path, MRB_ARGS_NONE()); -#endif struct RClass *io = mrb_class_get_id(mrb, MRB_SYM(IO)); @@ -1447,7 +1348,5 @@ mrb_mruby_socket_gem_init(mrb_state* mrb) void mrb_mruby_socket_gem_final(mrb_state* mrb) { -#ifdef _WIN32 - WSACleanup(); -#endif + mrb_socket_hal_final(mrb); }