summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTomoyuki Sahara <[email protected]>2014-12-26 11:16:03 +0900
committerTomoyuki Sahara <[email protected]>2014-12-26 11:16:03 +0900
commit3a22166c67f1d495f617f3ece5524dcdc9d2872c (patch)
tree22a803d7b49c2336d69f832e5173b56ae55068dd
parent723db886e158acf85e5f1f9c56ee40607727eeff (diff)
downloadmruby-3a22166c67f1d495f617f3ece5524dcdc9d2872c.tar.gz
mruby-3a22166c67f1d495f617f3ece5524dcdc9d2872c.zip
debug UNIXSocket and UNIXServer.
-rw-r--r--README.md1
-rw-r--r--mrblib/socket.rb63
-rw-r--r--src/socket.c2
-rw-r--r--test/unix.rb125
4 files changed, 175 insertions, 16 deletions
diff --git a/README.md b/README.md
index 2dac85aa6..5f2227e85 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ Date: Tue, 21 May 2013 04:31:30 GMT
- add missing methods
- write more tests
- fix possible descriptor leakage (see XXX comments)
+- `UNIXSocket#recv_io` `UNIXSocket#send_io`
## License
diff --git a/mrblib/socket.rb b/mrblib/socket.rb
index b8f10befd..e3a1487d4 100644
--- a/mrblib/socket.rb
+++ b/mrblib/socket.rb
@@ -181,6 +181,10 @@ class BasicSocket
@do_not_reverse_lookup = @@do_not_reverse_lookup
end
+ def self.for_fd(fd)
+ super(fd, "r+")
+ end
+
#def connect_address
def local_address
@@ -452,14 +456,24 @@ class Socket
end
end
-class UNIXSocket
+class UNIXSocket < BasicSocket
def initialize(path, &block)
- super(Socket._socket(AF_UNIX, SOCK_STREAM, 0), "r+")
- Socket._connect(self.fileno, Socket.sockaddr_un(path))
- if block
- block.call(self)
+ if self.is_a? UNIXServer
+ super(path, "r")
else
- self
+ super(Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0), "r+")
+ Socket._connect(self.fileno, Socket.sockaddr_un(path))
+
+ if block_given?
+ begin
+ yield self
+ ensure
+ begin
+ self.close unless self.closed?
+ rescue StandardError
+ end
+ end
+ end
end
end
@@ -488,23 +502,42 @@ class UNIXSocket
def recvfrom(maxlen, flags=0)
msg, sa = _recvfrom(maxlen, flags)
- [ msg, [ "AF_UNIX", Addrinfo.new(sa).unix_path ] ]
+ path = (sa.size > 0) ? Addrinfo.new(sa).unix_path : ""
+ [ msg, [ "AF_UNIX", path ] ]
end
#def send_io
end
-class UNIXServer
- def initialize(path, &block)
- super(Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0), "r")
- Socket._bind(self.fileno, Socket.pack_sockaddr_un(path))
- listen(5)
- self
+class UNIXServer < UNIXSocket
+ def initialize(path)
+ fd = Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
+ begin
+ super(fd)
+ Socket._bind(fd, Socket.pack_sockaddr_un(path))
+ self.listen(5)
+ rescue => e
+ IO._sysclose(fd) rescue nil
+ raise e
+ end
+
+ if block_given?
+ begin
+ yield self
+ ensure
+ self.close rescue nil unless self.closed?
+ end
+ end
end
def accept
- fd, addr = self.sysaccept
- [ UNIXSocket.for_fd(fd), addr ]
+ fd = self.sysaccept
+ begin
+ sock = UNIXSocket.for_fd(fd)
+ rescue
+ IO._sysclose(fd) rescue nil
+ end
+ sock
end
def accept_nonblock
diff --git a/src/socket.c b/src/socket.c
index b8d9b7613..ea958f953 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -673,7 +673,7 @@ 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());
- usock = mrb_define_class(mrb, "UNIXSocket", io);
+ usock = mrb_define_class(mrb, "UNIXSocket", bsock);
//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));
diff --git a/test/unix.rb b/test/unix.rb
new file mode 100644
index 000000000..379eb1ec4
--- /dev/null
+++ b/test/unix.rb
@@ -0,0 +1,125 @@
+def unixserver_test_block
+ File.unlink SocketTest.tmppath rescue nil
+ begin
+ result = yield SocketTest.tmppath
+ ensure
+ File.unlink SocketTest.tmppath rescue nil
+ end
+ result
+end
+
+def with_unix_server
+ unixserver_test_block do |path|
+ UNIXServer.open(path) { |server|
+ yield path, server
+ }
+ end
+end
+
+def with_unix_client
+ with_unix_server do |path, server|
+ UNIXSocket.open(path) do |csock|
+ ssock = server.accept
+ begin
+ yield path, server, ssock, csock
+ ensure
+ ssock.close unless ssock.closed? rescue nil
+ end
+ end
+ end
+end
+
+assert('UNIXServer.new') do
+ unixserver_test_block do |path|
+ server = UNIXServer.new(path)
+ assert_true server.is_a? UNIXServer
+ server.close
+ File.unlink path
+
+ s2 = nil
+ result = UNIXServer.open(path) { |s1|
+ assert_true s1.is_a? UNIXServer
+ s2 = s1
+ 1234
+ }
+ assert_equal 1234, result
+ assert_true s2.is_a? UNIXServer
+ assert_true s2.closed?
+ end
+end
+
+# assert('UNIXServer#accept_nonblock') - would block if fails
+
+assert('UNIXServer#addr') do
+ with_unix_server do |path, server|
+ assert_equal [ "AF_UNIX", path], server.addr
+ end
+end
+
+assert('UNIXServer#path') do
+ with_unix_server do |path, server|
+ assert_equal path, server.path
+ end
+end
+
+# assert('UNIXServer#peeraddr') - will raise a runtime exception
+
+assert('UNIXServer#listen') do
+ with_unix_server do |path, server|
+ assert_equal 0, server.listen(1)
+ end
+end
+
+assert('UNIXServer#sysaccept') do
+ with_unix_server do |path, server|
+ UNIXSocket.open(path) do |csock|
+ begin
+ fd = server.sysaccept
+ assert_true fd.kind_of? Integer
+ ensure
+ IO._sysclose(fd) rescue nil
+ end
+ end
+ end
+end
+
+assert('UNIXSocket.new') do
+ with_unix_server do |path, server|
+ c = UNIXSocket.new(path)
+ assert_true c.is_a? UNIXSocket
+ c.close
+ true
+ end
+end
+
+assert('UNIXSocket#addr') do
+ with_unix_client do |path, server, ssock, csock|
+ assert_equal [ "AF_UNIX", path ], ssock.addr
+ assert_equal [ "AF_UNIX", "" ], csock.addr
+ end
+end
+
+assert('UNIXSocket#path') do
+ with_unix_client do |path, server, ssock, csock|
+ assert_equal path, ssock.path
+ assert_equal "", csock.path
+ end
+end
+
+assert('UNIXSocket#peeraddr') do
+ with_unix_client do |path, server, ssock, csock|
+ assert_equal [ "AF_UNIX", "" ], ssock.peeraddr
+ assert_equal [ "AF_UNIX", path ], csock.peeraddr
+ end
+end
+
+assert('UNIXSocket#recvfrom') do
+ with_unix_client do |path, server, ssock, csock|
+ str = "0123456789"
+ ssock.send str, 0
+ a = csock.recvfrom(8)
+ assert_equal str[0, 8], a[0]
+ assert_equal "AF_UNIX", a[1][0]
+ # a[1][1] would be "" or something
+ end
+end