Commit bfb9cf79 authored by Tomoyuki Sahara's avatar Tomoyuki Sahara

Merge pull request #20 from expeditiousRubyist/master

Win32 Port
parents dacb8b62 4ab92204
......@@ -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')
......
......@@ -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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment