mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
@@ -3,6 +3,12 @@ MRuby::Gem::Specification.new('mruby-socket') do |spec|
|
||||
spec.authors = 'Internet Initiative Japan'
|
||||
|
||||
spec.cc.include_paths << "#{build.root}/src"
|
||||
|
||||
# If Windows, use winsock
|
||||
if ( /mswin|mingw|win32/ =~ RUBY_PLATFORM ) then
|
||||
spec.linker.libraries << "wsock32"
|
||||
spec.linker.libraries << "ws2_32"
|
||||
end
|
||||
|
||||
spec.add_dependency('mruby-io')
|
||||
spec.add_dependency('mruby-pack')
|
||||
|
||||
+99
-15
@@ -4,19 +4,28 @@
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
#include "mruby.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mruby.h"
|
||||
#include "mruby/array.h"
|
||||
#include "mruby/class.h"
|
||||
#include "mruby/data.h"
|
||||
@@ -130,6 +139,7 @@ mrb_addrinfo_getnameinfo(mrb_state *mrb, mrb_value self)
|
||||
return ary;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static mrb_value
|
||||
mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -140,6 +150,7 @@ mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
|
||||
mrb_raise(mrb, E_SOCKET_ERROR, "need AF_UNIX address");
|
||||
return mrb_str_new_cstr(mrb, ((struct sockaddr_un *)RSTRING_PTR(sastr))->sun_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_value
|
||||
sa2addrlist(mrb_state *mrb, const struct sockaddr *sa, socklen_t salen)
|
||||
@@ -244,7 +255,8 @@ mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int opt, s;
|
||||
char opt[8];
|
||||
int s;
|
||||
mrb_int family, level, optname;
|
||||
mrb_value c, data;
|
||||
socklen_t optlen;
|
||||
@@ -252,11 +264,11 @@ mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self)
|
||||
mrb_get_args(mrb, "ii", &level, &optname);
|
||||
s = socket_fd(mrb, self);
|
||||
optlen = sizeof(opt);
|
||||
if (getsockopt(s, level, optname, &opt, &optlen) == -1)
|
||||
if (getsockopt(s, level, optname, opt, &optlen) == -1)
|
||||
mrb_sys_fail(mrb, "getsockopt");
|
||||
c = mrb_const_get(mrb, mrb_obj_value(mrb_class_get(mrb, "Socket")), mrb_intern_lit(mrb, "Option"));
|
||||
family = socket_family(s);
|
||||
data = mrb_str_new(mrb, (char *)&opt, sizeof(int));
|
||||
data = mrb_str_new(mrb, opt, optlen);
|
||||
return mrb_funcall(mrb, c, "new", 4, mrb_fixnum_value(family), mrb_fixnum_value(level), mrb_fixnum_value(optname), data);
|
||||
}
|
||||
|
||||
@@ -323,10 +335,17 @@ mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int fd, flags;
|
||||
mrb_value bool;
|
||||
#ifdef _WIN32
|
||||
u_long mode = 1;
|
||||
#endif
|
||||
|
||||
mrb_get_args(mrb, "o", &bool);
|
||||
fd = socket_fd(mrb, self);
|
||||
|
||||
#ifdef _WIN32
|
||||
flags = ioctlsocket(fd, FIONBIO, &mode);
|
||||
if (flags != NO_ERROR)
|
||||
mrb_sys_fail(mrb, "ioctlsocket");
|
||||
#else
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
if (flags == 1)
|
||||
mrb_sys_fail(mrb, "fcntl");
|
||||
@@ -336,6 +355,7 @@ mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self)
|
||||
flags &= ~O_NONBLOCK;
|
||||
if (fcntl(fd, F_SETFL, flags) == -1)
|
||||
mrb_sys_fail(mrb, "fcntl");
|
||||
#endif
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
@@ -561,6 +581,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
|
||||
struct sockaddr_un *sunp;
|
||||
mrb_value path, s;
|
||||
|
||||
@@ -575,11 +599,16 @@ mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass)
|
||||
sunp->sun_path[RSTRING_LEN(path)] = '\0';
|
||||
mrb_str_resize(mrb, s, sizeof(struct sockaddr_un));
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
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_value ary;
|
||||
mrb_int domain, type, protocol;
|
||||
int sv[2];
|
||||
@@ -593,6 +622,7 @@ mrb_socket_socketpair(mrb_state *mrb, mrb_value klass)
|
||||
mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[0]));
|
||||
mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[1]));
|
||||
return ary;
|
||||
#endif
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
@@ -619,17 +649,60 @@ mrb_tcpsocket_allocate(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_obj_value((struct RObject*)mrb_obj_alloc(mrb, ttype, c));
|
||||
}
|
||||
|
||||
/* Windows overrides for IO methods on BasicSocket objects.
|
||||
* This is because sockets on Windows are not the same as file
|
||||
* descriptors, and thus functions which operate on file descriptors
|
||||
* will break on socket descriptors.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
static mrb_value
|
||||
mrb_win32_basicsocket_close(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
if (closesocket(socket_fd(mrb, self)) != NO_ERROR)
|
||||
mrb_raise(mrb, E_SOCKET_ERROR, "closesocket unsuccessful");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_win32_basicsocket_write(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int n;
|
||||
SOCKET sd;
|
||||
mrb_value str;
|
||||
|
||||
sd = socket_fd(mrb, self);
|
||||
mrb_get_args(mrb, "S", &str);
|
||||
n = send(sd, RSTRING_PTR(str), RSTRING_LEN(str), 0);
|
||||
if (n == SOCKET_ERROR)
|
||||
mrb_sys_fail(mrb, "send");
|
||||
return mrb_fixnum_value(n);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
mrb_mruby_socket_gem_init(mrb_state* mrb)
|
||||
{
|
||||
struct RClass *io, *ai, *sock, *bsock, *ipsock, *tcpsock, *udpsock, *usock;
|
||||
struct RClass *io, *ai, *sock, *bsock, *ipsock, *tcpsock, *udpsock;
|
||||
struct RClass *constants;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
int result;
|
||||
result = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||
if (result != NO_ERROR)
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "WSAStartup failed");
|
||||
#else
|
||||
struct RClass *usock;
|
||||
#endif
|
||||
|
||||
ai = mrb_define_class(mrb, "Addrinfo", mrb->object_class);
|
||||
mrb_mod_cv_set(mrb, ai, mrb_intern_lit(mrb, "_lastai"), mrb_nil_value());
|
||||
mrb_define_class_method(mrb, ai, "getaddrinfo", mrb_addrinfo_getaddrinfo, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(4));
|
||||
mrb_define_method(mrb, ai, "getnameinfo", mrb_addrinfo_getnameinfo, MRB_ARGS_OPT(1));
|
||||
#ifndef _WIN32
|
||||
mrb_define_method(mrb, ai, "unix_path", mrb_addrinfo_unix_path, MRB_ARGS_NONE());
|
||||
#endif
|
||||
|
||||
io = mrb_class_get(mrb, "IO");
|
||||
|
||||
@@ -676,7 +749,9 @@ mrb_mruby_socket_gem_init(mrb_state* mrb)
|
||||
mrb_define_class_method(mrb, sock, "socketpair", mrb_socket_socketpair, MRB_ARGS_REQ(3));
|
||||
//mrb_define_method(mrb, sock, "sysaccept", mrb_socket_accept, MRB_ARGS_NONE());
|
||||
|
||||
#ifndef _WIN32
|
||||
usock = mrb_define_class(mrb, "UNIXSocket", bsock);
|
||||
#endif
|
||||
//mrb_define_class_method(mrb, usock, "pair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
|
||||
//mrb_define_class_method(mrb, usock, "socketpair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
|
||||
|
||||
@@ -684,6 +759,12 @@ mrb_mruby_socket_gem_init(mrb_state* mrb)
|
||||
//mrb_define_method(mrb, usock, "recvfrom", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
|
||||
//mrb_define_method(mrb, usock, "send_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
|
||||
|
||||
/* Windows IO Method Overrides on BasicSocket */
|
||||
#ifdef _WIN32
|
||||
mrb_define_method(mrb, bsock, "close", mrb_win32_basicsocket_close, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, bsock, "write", mrb_win32_basicsocket_write, MRB_ARGS_REQ(1));
|
||||
#endif
|
||||
|
||||
constants = mrb_define_module_under(mrb, sock, "Constants");
|
||||
|
||||
#define define_const(SYM) \
|
||||
@@ -702,4 +783,7 @@ mrb_mruby_socket_gem_final(mrb_state* mrb)
|
||||
if (mrb_cptr_p(ai)) {
|
||||
freeaddrinfo(mrb_cptr(ai));
|
||||
}
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user