summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrblib/socket.rb18
-rw-r--r--src/socket.c14
2 files changed, 28 insertions, 4 deletions
diff --git a/mrblib/socket.rb b/mrblib/socket.rb
index b8c8b4c18..732a6db8e 100644
--- a/mrblib/socket.rb
+++ b/mrblib/socket.rb
@@ -224,7 +224,7 @@ end
class TCPSocket
def initialize(host, service, local_host=nil, local_service=nil)
- if self.is_a? TCPServer
+ if @init_with_fd
super(host, service)
else
s = nil
@@ -243,12 +243,20 @@ class TCPSocket
end
end
+ def self.new_with_prelude pre, *args
+ o = self._allocate
+ o.instance_eval(&pre)
+ o.initialize(*args)
+ o
+ end
+
#def self.gethostbyname(host)
end
class TCPServer
def initialize(host=nil, service)
ai = Addrinfo.getaddrinfo(host, service, nil, nil, nil, Socket::AI_PASSIVE)[0]
+ @init_with_fd = true
super(Socket._socket(ai.afamily, Socket::SOCK_STREAM, 0), "r+")
Socket._bind(self.fileno, ai.to_sockaddr)
listen(5)
@@ -256,7 +264,13 @@ class TCPServer
end
def accept
- TCPSocket.for_fd(self.sysaccept)
+ fd = self.sysaccept
+ begin
+ TCPSocket.new_with_prelude(proc { @init_with_fd = true }, fd, "r+")
+ rescue
+ IO._sysclose(fd) rescue nil
+ raise
+ end
end
def accept_nonblock
diff --git a/src/socket.c b/src/socket.c
index 2cf7ac385..ded5dfa25 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -599,6 +599,17 @@ mrb_socket_socket(mrb_state *mrb, mrb_value klass)
return mrb_fixnum_value(s);
}
+static mrb_value
+mrb_tcpsocket_allocate(mrb_state *mrb, mrb_value klass)
+{
+ struct RClass *c = mrb_class_ptr(klass);
+ enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
+
+ /* copied from mrb_instance_alloc() */
+ if (ttype == 0) ttype = MRB_TT_OBJECT;
+ return mrb_obj_value((struct RObject*)mrb_obj_alloc(mrb, ttype, c));
+}
+
void
mrb_mruby_socket_gem_init(mrb_state* mrb)
{
@@ -634,8 +645,7 @@ mrb_mruby_socket_gem_init(mrb_state* mrb)
mrb_define_method(mrb, ipsock, "recvfrom", mrb_ipsocket_recvfrom, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
tcpsock = mrb_define_class(mrb, "TCPSocket", ipsock);
- //mrb_define_class_method(mrb, tcpsock, "open", mrb_tcpsocket_open, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(2));
- //mrb_define_class_method(mrb, tcpsock, "new", mrb_tcpsocket_open, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(2));
+ mrb_define_class_method(mrb, tcpsock, "_allocate", mrb_tcpsocket_allocate, MRB_ARGS_NONE());
mrb_define_class(mrb, "TCPServer", tcpsock);
udpsock = mrb_define_class(mrb, "UDPSocket", ipsock);