Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more

UNIXSocket

UNIXSocket represents a UNIX domain stream client socket.

Public Class Methods

new(path) => unixsocket click to toggle source

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);
}
 
pair([type [, protocol]]) => [unixsocket1, unixsocket2] click to toggle source

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);
}
 
socketpair([type [, protocol]]) => [unixsocket1, unixsocket2] click to toggle source

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);
}
 

Public Instance Methods

addr => [address_family, unix_path] click to toggle source

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);
}
 
path => path click to toggle source

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);
}
 
peeraddr => [address_family, unix_path] click to toggle source

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);
}
 
recv_io([klass [, mode]]) => io click to toggle source

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);
 }
}
 
recvfrom(maxlen [, flags]) => [mesg, unixaddress] click to toggle source

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);
}
 
send_io(io) => nil click to toggle source

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;
}
 

AltStyle によって変換されたページ (->オリジナル) /