diff options
| author | Tomoyuki Sahara <[email protected]> | 2015-07-22 09:35:39 +0900 |
|---|---|---|
| committer | Tomoyuki Sahara <[email protected]> | 2015-07-22 09:35:39 +0900 |
| commit | bfb9cf7922b9fc9b77d8f170aced944291aa0347 (patch) | |
| tree | 842f3919222d49f7afa0a378376ab55cb0e09bba /src | |
| parent | dacb8b626b293670567bd3cf7870c3e3c4147a08 (diff) | |
| parent | 4ab922044de80da5e6167799d070cec2e73b4204 (diff) | |
| download | mruby-bfb9cf7922b9fc9b77d8f170aced944291aa0347.tar.gz mruby-bfb9cf7922b9fc9b77d8f170aced944291aa0347.zip | |
Merge pull request #20 from expeditiousRubyist/master
Win32 Port
Diffstat (limited to 'src')
| -rw-r--r-- | src/socket.c | 114 |
1 files changed, 99 insertions, 15 deletions
diff --git a/src/socket.c b/src/socket.c index bdfada7b5..fc2abed5b 100644 --- a/src/socket.c +++ b/src/socket.c @@ -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 } |
