Index: EcnlProtoTool/trunk/mrbgems/mruby-socket/src/socket.c
===================================================================
--- EcnlProtoTool/trunk/mrbgems/mruby-socket/src/socket.c	(revision 321)
+++ EcnlProtoTool/trunk/mrbgems/mruby-socket/src/socket.c	(revision 331)
@@ -4,18 +4,27 @@
 ** See Copyright Notice in 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>
-#include <unistd.h>
+
+#ifdef _WIN32
+  #define _WIN32_WINNT 0x0501
+
+  #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>*/
-extern int gethostname(char *name, size_t len);
 
 #include "mruby.h"
@@ -27,10 +36,4 @@
 #include "error.h"
 
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 255
-#endif
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
 #define E_SOCKET_ERROR             (mrb_class_get(mrb, "SocketError"))
 
@@ -41,5 +44,5 @@
 #endif
 
-//#ifdef _WIN32
+#ifdef _WIN32
 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
 {
@@ -59,5 +62,5 @@
 	memset(&in, 0, sizeof(in));
 	in.sin6_family = AF_INET6;
-	memcpy(&in.sin6_addr, src, sizeof(struct in6_addr));
+	memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
 	getnameinfo((struct sockaddr *)&in, sizeof(struct
 		    sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
@@ -92,5 +95,5 @@
 }
 
-//#endif
+#endif
 
 static mrb_value
@@ -192,4 +195,5 @@
 }
 
+#ifndef _WIN32
 static mrb_value
 mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
@@ -202,4 +206,5 @@
   return mrb_str_new_cstr(mrb, ((struct sockaddr_un *)RSTRING_PTR(sastr))->sun_path);
 }
+#endif
 
 static mrb_value
@@ -256,5 +261,5 @@
 static mrb_value
 mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self)
-{ 
+{
 #ifdef HAVE_GETPEEREID
   mrb_value ary;
@@ -262,5 +267,5 @@
   uid_t euid;
   int s;
-  
+
   s = socket_fd(mrb, self);
   if (getpeereid(s, &euid, &egid) != 0)
@@ -279,8 +284,8 @@
 static mrb_value
 mrb_basicsocket_getpeername(mrb_state *mrb, mrb_value self)
-{ 
+{
   struct sockaddr_storage ss;
   socklen_t salen;
-  
+
   salen = sizeof(ss);
   if (getpeername(socket_fd(mrb, self), (struct sockaddr *)&ss, &salen) != 0)
@@ -292,8 +297,8 @@
 static mrb_value
 mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self)
-{ 
+{
   struct sockaddr_storage ss;
   socklen_t salen;
-  
+
   salen = sizeof(ss);
   if (getsockname(socket_fd(mrb, self), (struct sockaddr *)&ss, &salen) != 0)
@@ -305,5 +310,5 @@
 static mrb_value
 mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self)
-{ 
+{
   char opt[8];
   int s;
@@ -325,5 +330,5 @@
 static mrb_value
 mrb_basicsocket_recv(mrb_state *mrb, mrb_value self)
-{ 
+{
   int n;
   mrb_int maxlen, flags = 0;
@@ -341,5 +346,5 @@
 static mrb_value
 mrb_basicsocket_recvfrom(mrb_state *mrb, mrb_value self)
-{ 
+{
   int n;
   mrb_int maxlen, flags = 0;
@@ -364,5 +369,5 @@
 static mrb_value
 mrb_basicsocket_send(mrb_state *mrb, mrb_value self)
-{ 
+{
   int n;
   mrb_int flags;
@@ -383,10 +388,18 @@
 static mrb_value
 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)
@@ -398,4 +411,5 @@
   if (fcntl(fd, F_SETFL, flags) == -1)
     mrb_sys_fail(mrb, "fcntl");
+#endif
   return mrb_nil_value();
 }
@@ -403,5 +417,5 @@
 static mrb_value
 mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
-{ 
+{
   int argc, s;
   mrb_int level = 0, optname;
@@ -420,6 +434,11 @@
       optval = mrb_str_new(mrb, (char *)&i, sizeof(i));
     } else if (mrb_fixnum_p(optval)) {
-      mrb_int i = mrb_fixnum(optval);
-      optval = mrb_str_new(mrb, (char *)&i, sizeof(i));
+      if (optname == IP_MULTICAST_TTL || optname == IP_MULTICAST_LOOP) {
+        char uc = mrb_fixnum(optval);
+        optval = mrb_str_new(mrb, &uc, sizeof(uc));
+      } else {
+        mrb_int i = mrb_fixnum(optval);
+        optval = mrb_str_new(mrb, (char *)&i, sizeof(i));
+      }
     } else {
       mrb_raise(mrb, E_ARGUMENT_ERROR, "optval should be true, false, an integer, or a string");
@@ -443,5 +462,5 @@
 static mrb_value
 mrb_basicsocket_shutdown(mrb_state *mrb, mrb_value self)
-{ 
+{
   mrb_int how = SHUT_RDWR;
 
@@ -454,5 +473,5 @@
 static mrb_value
 mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
-{ 
+{
   mrb_int af, n;
   char *addr, buf[50];
@@ -468,5 +487,5 @@
 static mrb_value
 mrb_ipsocket_pton(mrb_state *mrb, mrb_value klass)
-{ 
+{
   mrb_int af, n;
   char *bp, buf[50];
@@ -498,5 +517,5 @@
 static mrb_value
 mrb_ipsocket_recvfrom(mrb_state *mrb, mrb_value self)
-{ 
+{
   struct sockaddr_storage ss;
   socklen_t socklen;
@@ -528,5 +547,5 @@
   mrb_value buf;
   size_t bufsize;
-  
+
 #ifdef HOST_NAME_MAX
   bufsize = HOST_NAME_MAX + 1;
@@ -568,8 +587,8 @@
 {
   mrb_value sastr;
-  int s;
+  mrb_int s;
 
   mrb_get_args(mrb, "iS", &s, &sastr);
-  if (bind(s, (struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr)) == -1) {
+  if (bind((int)s, (struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr)) == -1) {
     mrb_sys_fail(mrb, "bind");
   }
@@ -581,8 +600,8 @@
 {
   mrb_value sastr;
-  int s;
+  mrb_int s;
 
   mrb_get_args(mrb, "iS", &s, &sastr);
-  if (connect(s, (struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr)) == -1) {
+  if (connect((int)s, (struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr)) == -1) {
     mrb_sys_fail(mrb, "connect");
   }
@@ -593,8 +612,8 @@
 mrb_socket_listen(mrb_state *mrb, mrb_value klass)
 {
-  int backlog, s;
+  mrb_int backlog, s;
 
   mrb_get_args(mrb, "ii", &s, &backlog);
-  if (listen(s, backlog) == -1) {
+  if (listen((int)s, (int)backlog) == -1) {
     mrb_sys_fail(mrb, "listen");
   }
@@ -623,7 +642,11 @@
 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;
-  
+
   mrb_get_args(mrb, "S", &path);
   if (RSTRING_LEN(path) > sizeof(sunp->sun_path) - 1) {
@@ -637,4 +660,5 @@
   mrb_str_resize(mrb, s, sizeof(struct sockaddr_un));
   return s;
+#endif
 }
 
@@ -642,4 +666,8 @@
 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;
@@ -655,4 +683,5 @@
   mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[1]));
   return ary;
+#endif
 }
 
@@ -686,4 +715,80 @@
  * 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();
+}
+
+#define E_EOF_ERROR                (mrb_class_get(mrb, "EOFError"))
+static mrb_value
+mrb_win32_basicsocket_sysread(mrb_state *mrb, mrb_value self)
+{
+  int sd, ret;
+  mrb_value buf = mrb_nil_value();
+  mrb_int maxlen;
+
+  mrb_get_args(mrb, "i|S", &maxlen, &buf);
+  if (maxlen < 0) {
+    return mrb_nil_value();
+  }
+
+  if (mrb_nil_p(buf)) {
+    buf = mrb_str_new(mrb, NULL, maxlen);
+  }
+  if (RSTRING_LEN(buf) != maxlen) {
+    buf = mrb_str_resize(mrb, buf, maxlen);
+  }
+
+  sd = socket_fd(mrb, self);
+  ret = recv(sd, RSTRING_PTR(buf), maxlen, 0);
+
+  switch (ret) {
+    case 0: /* EOF */
+      if (maxlen == 0) {
+        buf = mrb_str_new_cstr(mrb, "");
+      } else {
+        mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
+      }
+      break;
+    case SOCKET_ERROR: /* Error */
+      mrb_sys_fail(mrb, "recv");
+      break;
+    default:
+      if (RSTRING_LEN(buf) != ret) {
+        buf = mrb_str_resize(mrb, buf, ret);
+      }
+      break;
+  }
+
+  return buf;
+}
+
+static mrb_value
+mrb_win32_basicsocket_sysseek(mrb_state *mrb, mrb_value self)
+{
+  mrb_raise(mrb, E_NOTIMP_ERROR, "sysseek not implemented for windows sockets");
+  return mrb_nil_value();
+}
+
+static mrb_value
+mrb_win32_basicsocket_syswrite(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
@@ -693,5 +798,13 @@
   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);
@@ -699,5 +812,7 @@
   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");
@@ -746,5 +861,7 @@
   //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));
@@ -755,4 +872,10 @@
 
   /* 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, "sysread", mrb_win32_basicsocket_sysread, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
+  mrb_define_method(mrb, bsock, "sysseek", mrb_win32_basicsocket_sysseek, MRB_ARGS_REQ(1));
+  mrb_define_method(mrb, bsock, "syswrite", mrb_win32_basicsocket_syswrite, MRB_ARGS_REQ(1));
+#endif
 
   constants = mrb_define_module_under(mrb, sock, "Constants");
@@ -774,3 +897,6 @@
     freeaddrinfo(mrb_cptr(ai));
   }
-}
+#ifdef _WIN32
+  WSACleanup();
+#endif
+}
