mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
@@ -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 <mruby.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/error.h>
|
||||
#include <mruby/presym.h>
|
||||
#include <socket_hal.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 <mruby.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/error.h>
|
||||
#include <mruby/presym.h>
|
||||
#include <socket_hal.h>
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
@@ -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 <mruby.h>
|
||||
|
||||
#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 */
|
||||
@@ -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
|
||||
|
||||
@@ -6,12 +6,9 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <winerror.h>
|
||||
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
typedef int fsize_t;
|
||||
#else
|
||||
@@ -42,6 +39,7 @@
|
||||
#include <mruby/presym.h>
|
||||
|
||||
#include <mruby/ext/io.h>
|
||||
#include <socket_hal.h>
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user