diff options
Diffstat (limited to 'ruby_1_9_3/ext/socket/unixsocket.c')
-rw-r--r-- | ruby_1_9_3/ext/socket/unixsocket.c | 523 |
1 files changed, 0 insertions, 523 deletions
diff --git a/ruby_1_9_3/ext/socket/unixsocket.c b/ruby_1_9_3/ext/socket/unixsocket.c deleted file mode 100644 index 3c30e92c6e..0000000000 --- a/ruby_1_9_3/ext/socket/unixsocket.c +++ /dev/null @@ -1,523 +0,0 @@ -/************************************************ - - unixsocket.c - - - created at: Thu Mar 31 12:21:29 JST 1994 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - -************************************************/ - -#include "rubysocket.h" - -#ifdef HAVE_SYS_UN_H -struct unixsock_arg { - struct sockaddr_un *sockaddr; - socklen_t sockaddrlen; - int fd; -}; - -static VALUE -unixsock_connect_internal(VALUE a) -{ - struct unixsock_arg *arg = (struct unixsock_arg *)a; - return (VALUE)rsock_connect(arg->fd, (struct sockaddr*)arg->sockaddr, - arg->sockaddrlen, 0); -} - -VALUE -rsock_init_unixsock(VALUE sock, VALUE path, int server) -{ - struct sockaddr_un sockaddr; - socklen_t sockaddrlen; - int fd, status; - rb_io_t *fptr; - - SafeStringValue(path); - fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - rb_sys_fail("socket(2)"); - } - - MEMZERO(&sockaddr, struct sockaddr_un, 1); - sockaddr.sun_family = AF_UNIX; - if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) { - rb_raise(rb_eArgError, "too long unix socket path (%ldbytes given but %dbytes max)", - RSTRING_LEN(path), (int)sizeof(sockaddr.sun_path)); - } - memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); - sockaddrlen = rsock_unix_sockaddr_len(path); - - if (server) { - status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen); - } - else { - int prot; - struct unixsock_arg arg; - arg.sockaddr = &sockaddr; - arg.sockaddrlen = sockaddrlen; - arg.fd = fd; - status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot); - if (prot) { - close(fd); - rb_jump_tag(prot); - } - } - - if (status < 0) { - close(fd); - rb_sys_fail_str(rb_inspect(path)); - } - - if (server) { - if (listen(fd, 5) < 0) { - close(fd); - rb_sys_fail("listen(2)"); - } - } - - rsock_init_sock(sock, fd); - if (server) { - GetOpenFile(sock, fptr); - fptr->pathv = rb_str_new_frozen(path); - } - - return sock; -} - -/* - * call-seq: - * UNIXSocket.new(path) => unixsocket - * - * Creates a new UNIX client socket connected to _path_. - * - * s = UNIXSocket.new("/tmp/sock") - * s.send "hello", 0 - * - */ -static VALUE -unix_init(VALUE sock, VALUE path) -{ - return rsock_init_unixsock(sock, path, 0); -} - -/* - * call-seq: - * unixsocket.path => path - * - * Returns the path of the local address of unixsocket. - * - * s = UNIXServer.new("/tmp/sock") - * p s.path #=> "/tmp/sock" - * - */ -static VALUE -unix_path(VALUE sock) -{ - rb_io_t *fptr; - - GetOpenFile(sock, fptr); - if (NIL_P(fptr->pathv)) { - struct sockaddr_un addr; - socklen_t len = (socklen_t)sizeof(addr); - socklen_t len0 = len; - if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail(0); - if (len0 < len) len = len0; - fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len)); - } - return rb_str_dup(fptr->pathv); -} - -/* - * call-seq: - * unixsocket.recvfrom(maxlen [, flags]) => [mesg, unixaddress] - * - * Receives a message via _unixsocket_. - * - * _maxlen_ is the maximum number of bytes to receive. - * - * _flags_ should be a bitwise OR of Socket::MSG_* constants. - * - * s1 = Socket.new(:UNIX, :DGRAM, 0) - * s1_ai = Addrinfo.unix("/tmp/sock1") - * s1.bind(s1_ai) - * - * s2 = Socket.new(:UNIX, :DGRAM, 0) - * s2_ai = Addrinfo.unix("/tmp/sock2") - * s2.bind(s2_ai) - * s3 = UNIXSocket.for_fd(s2.fileno) - * - * s1.send "a", 0, s2_ai - * p s3.recvfrom(10) #=> ["a", ["AF_UNIX", "/tmp/sock1"]] - * - */ -static VALUE -unix_recvfrom(int argc, VALUE *argv, VALUE sock) -{ - return rsock_s_recvfrom(sock, argc, argv, RECV_UNIX); -} - -#if defined(HAVE_ST_MSG_CONTROL) && defined(SCM_RIGHTS) -#define FD_PASSING_BY_MSG_CONTROL 1 -#else -#define FD_PASSING_BY_MSG_CONTROL 0 -#endif - -#if defined(HAVE_ST_MSG_ACCRIGHTS) -#define FD_PASSING_BY_MSG_ACCRIGHTS 1 -#else -#define FD_PASSING_BY_MSG_ACCRIGHTS 0 -#endif - -struct iomsg_arg { - int fd; - struct msghdr msg; -}; - -#if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS) -static VALUE -sendmsg_blocking(void *data) -{ - struct iomsg_arg *arg = data; - return sendmsg(arg->fd, &arg->msg, 0); -} - -/* - * call-seq: - * unixsocket.send_io(io) => nil - * - * Sends _io_ as file descriptor passing. - * - * s1, s2 = UNIXSocket.pair - * - * s1.send_io STDOUT - * stdout = s2.recv_io - * - * p STDOUT.fileno #=> 1 - * p stdout.fileno #=> 6 - * - * stdout.puts "hello" # outputs "hello\n" to standard output. - */ -static VALUE -unix_send_io(VALUE sock, VALUE val) -{ - int fd; - rb_io_t *fptr; - struct iomsg_arg arg; - struct iovec vec[1]; - char buf[1]; - -#if FD_PASSING_BY_MSG_CONTROL - struct { - struct cmsghdr hdr; - char pad[8+sizeof(int)+8]; - } cmsg; -#endif - - if (rb_obj_is_kind_of(val, rb_cIO)) { - rb_io_t *valfptr; - GetOpenFile(val, valfptr); - fd = valfptr->fd; - } - else if (FIXNUM_P(val)) { - fd = FIX2INT(val); - } - else { - rb_raise(rb_eTypeError, "neither IO nor file descriptor"); - } - - GetOpenFile(sock, fptr); - - arg.msg.msg_name = NULL; - arg.msg.msg_namelen = 0; - - /* Linux and Solaris doesn't work if msg_iov is NULL. */ - buf[0] = '\0'; - vec[0].iov_base = buf; - vec[0].iov_len = 1; - arg.msg.msg_iov = vec; - arg.msg.msg_iovlen = 1; - -#if FD_PASSING_BY_MSG_CONTROL - arg.msg.msg_control = (caddr_t)&cmsg; - arg.msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof(int)); - arg.msg.msg_flags = 0; - MEMZERO((char*)&cmsg, char, sizeof(cmsg)); - cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int)); - cmsg.hdr.cmsg_level = SOL_SOCKET; - cmsg.hdr.cmsg_type = SCM_RIGHTS; - memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int)); -#else - arg.msg.msg_accrights = (caddr_t)&fd; - arg.msg.msg_accrightslen = sizeof(fd); -#endif - - arg.fd = fptr->fd; - while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) { - if (!rb_io_wait_writable(arg.fd)) - rb_sys_fail("sendmsg(2)"); - } - - return Qnil; -} -#else -#define unix_send_io rb_f_notimplement -#endif - -#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS) -static VALUE -recvmsg_blocking(void *data) -{ - struct iomsg_arg *arg = data; - return recvmsg(arg->fd, &arg->msg, 0); -} - -/* - * call-seq: - * unixsocket.recv_io([klass [, mode]]) => io - * - * UNIXServer.open("/tmp/sock") {|serv| - * UNIXSocket.open("/tmp/sock") {|c| - * s = serv.accept - * - * c.send_io STDOUT - * stdout = s.recv_io - * - * p STDOUT.fileno #=> 1 - * p stdout.fileno #=> 7 - * - * stdout.puts "hello" # outputs "hello\n" to standard output. - * } - * } - * - */ -static VALUE -unix_recv_io(int argc, VALUE *argv, VALUE sock) -{ - VALUE klass, mode; - rb_io_t *fptr; - struct iomsg_arg arg; - struct iovec vec[2]; - char buf[1]; - - int fd; -#if FD_PASSING_BY_MSG_CONTROL - struct { - struct cmsghdr hdr; - char pad[8+sizeof(int)+8]; - } cmsg; -#endif - - rb_scan_args(argc, argv, "02", &klass, &mode); - if (argc == 0) - klass = rb_cIO; - if (argc <= 1) - mode = Qnil; - - GetOpenFile(sock, fptr); - - arg.msg.msg_name = NULL; - arg.msg.msg_namelen = 0; - - vec[0].iov_base = buf; - vec[0].iov_len = sizeof(buf); - arg.msg.msg_iov = vec; - arg.msg.msg_iovlen = 1; - -#if FD_PASSING_BY_MSG_CONTROL - arg.msg.msg_control = (caddr_t)&cmsg; - arg.msg.msg_controllen = (socklen_t)CMSG_SPACE(sizeof(int)); - arg.msg.msg_flags = 0; - cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int)); - cmsg.hdr.cmsg_level = SOL_SOCKET; - cmsg.hdr.cmsg_type = SCM_RIGHTS; - fd = -1; - memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int)); -#else - arg.msg.msg_accrights = (caddr_t)&fd; - arg.msg.msg_accrightslen = sizeof(fd); - fd = -1; -#endif - - arg.fd = fptr->fd; - while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) { - if (!rb_io_wait_readable(arg.fd)) - rb_sys_fail("recvmsg(2)"); - } - -#if FD_PASSING_BY_MSG_CONTROL - if (arg.msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr)) { - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)", - (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr)); - } - if (cmsg.hdr.cmsg_level != SOL_SOCKET) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_level=%d, %d expected)", - cmsg.hdr.cmsg_level, SOL_SOCKET); - } - if (cmsg.hdr.cmsg_type != SCM_RIGHTS) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_type=%d, %d expected)", - cmsg.hdr.cmsg_type, SCM_RIGHTS); - } - if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) { - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)", - (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int))); - } - if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) { - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)", - (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int))); - } - if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) { - rsock_discard_cmsg_resource(&arg.msg, 0); - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_len=%d, %d expected)", - (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int))); - } -#else - if (arg.msg.msg_accrightslen != sizeof(fd)) { - rb_raise(rb_eSocket, - "file descriptor was not passed (accrightslen) : %d != %d", - arg.msg.msg_accrightslen, (int)sizeof(fd)); - } -#endif - -#if FD_PASSING_BY_MSG_CONTROL - memcpy(&fd, CMSG_DATA(&cmsg.hdr), sizeof(int)); -#endif - rb_update_max_fd(fd); - - if (klass == Qnil) - return INT2FIX(fd); - else { - ID for_fd; - int ff_argc; - VALUE ff_argv[2]; - CONST_ID(for_fd, "for_fd"); - ff_argc = mode == Qnil ? 1 : 2; - ff_argv[0] = INT2FIX(fd); - ff_argv[1] = mode; - return rb_funcall2(klass, for_fd, ff_argc, ff_argv); - } -} -#else -#define unix_recv_io rb_f_notimplement -#endif - -/* - * call-seq: - * unixsocket.addr => [address_family, unix_path] - * - * Returns the local address as an array which contains - * address_family and unix_path. - * - * Example - * serv = UNIXServer.new("/tmp/sock") - * p serv.addr #=> ["AF_UNIX", "/tmp/sock"] - */ -static VALUE -unix_addr(VALUE sock) -{ - rb_io_t *fptr; - struct sockaddr_un addr; - socklen_t len = (socklen_t)sizeof addr; - - GetOpenFile(sock, fptr); - - if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail("getsockname(2)"); - return rsock_unixaddr(&addr, len); -} - -/* - * call-seq: - * unixsocket.peeraddr => [address_family, unix_path] - * - * Returns the remote address as an array which contains - * address_family and unix_path. - * - * Example - * serv = UNIXServer.new("/tmp/sock") - * c = UNIXSocket.new("/tmp/sock") - * p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"] - */ -static VALUE -unix_peeraddr(VALUE sock) -{ - rb_io_t *fptr; - struct sockaddr_un addr; - socklen_t len = (socklen_t)sizeof addr; - socklen_t len0 = len; - - GetOpenFile(sock, fptr); - - if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail("getpeername(2)"); - if (len0 < len) len = len0; - return rsock_unixaddr(&addr, len); -} - -/* - * call-seq: - * UNIXSocket.pair([type [, protocol]]) => [unixsocket1, unixsocket2] - * UNIXSocket.socketpair([type [, protocol]]) => [unixsocket1, unixsocket2] - * - * Creates a pair of sockets connected each other. - * - * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. - * - * _protocol_ should be a protocol defined in the domain. - * 0 is default protocol for the domain. - * - * s1, s2 = UNIXSocket.pair - * s1.send "a", 0 - * s1.send "b", 0 - * p s2.recv(10) #=> "ab" - * - */ -static VALUE -unix_s_socketpair(int argc, VALUE *argv, VALUE klass) -{ - VALUE domain, type, protocol; - VALUE args[3]; - - domain = INT2FIX(PF_UNIX); - rb_scan_args(argc, argv, "02", &type, &protocol); - if (argc == 0) - type = INT2FIX(SOCK_STREAM); - if (argc <= 1) - protocol = INT2FIX(0); - - args[0] = domain; - args[1] = type; - args[2] = protocol; - - return rsock_sock_s_socketpair(3, args, klass); -} -#endif - -void -rsock_init_unixsocket(void) -{ -#ifdef HAVE_SYS_UN_H - /* - * Document-class: UNIXSocket < BasicSocket - * - * UNIXSocket represents a UNIX domain stream client socket. - */ - rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket); - rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1); - rb_define_method(rb_cUNIXSocket, "path", unix_path, 0); - rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0); - rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0); - rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1); - rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1); - rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1); - rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1); - rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1); -#endif -} |