diff options
Diffstat (limited to 'ext/socket/unixserver.c')
-rw-r--r-- | ext/socket/unixserver.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/ext/socket/unixserver.c b/ext/socket/unixserver.c new file mode 100644 index 0000000000..74d91872eb --- /dev/null +++ b/ext/socket/unixserver.c @@ -0,0 +1,148 @@ +/************************************************ + + unixserver.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 +/* + * call-seq: + * UNIXServer.new(path) => unixserver + * + * Creates a new UNIX server socket bound to _path_. + * + * serv = UNIXServer.new("/tmp/sock") + * s = serv.accept + * p s.read + */ +static VALUE +unix_svr_init(VALUE sock, VALUE path) +{ + return init_unixsock(sock, path, 1); +} + +/* + * call-seq: + * unixserver.accept => unixsocket + * + * Accepts a new connection. + * It returns new UNIXSocket object. + * + * UNIXServer.open("/tmp/sock") {|serv| + * UNIXSocket.open("/tmp/sock") {|c| + * s = serv.accept + * s.puts "hi" + * s.close + * p c.read #=> "hi\n" + * } + * } + * + */ +static VALUE +unix_accept(VALUE sock) +{ + rb_io_t *fptr; + struct sockaddr_un from; + socklen_t fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(struct sockaddr_un); + return s_accept(rb_cUNIXSocket, fptr->fd, + (struct sockaddr*)&from, &fromlen); +} + +/* + * call-seq: + * unixserver.accept_nonblock => unixsocket + * + * Accepts an incoming connection using accept(2) after + * O_NONBLOCK is set for the underlying file descriptor. + * It returns an accepted UNIXSocket for the incoming connection. + * + * === Example + * require 'socket' + * serv = UNIXServer.new("/tmp/sock") + * begin # emulate blocking accept + * sock = serv.accept_nonblock + * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR + * IO.select([serv]) + * retry + * end + * # sock is an accepted socket. + * + * Refer to Socket#accept for the exceptions that may be thrown if the call + * to UNIXServer#accept_nonblock fails. + * + * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure, + * including Errno::EWOULDBLOCK. + * + * === See + * * UNIXServer#accept + * * Socket#accept + */ +static VALUE +unix_accept_nonblock(VALUE sock) +{ + rb_io_t *fptr; + struct sockaddr_un from; + socklen_t fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(from); + return s_accept_nonblock(rb_cUNIXSocket, fptr, + (struct sockaddr *)&from, &fromlen); +} + +/* + * call-seq: + * unixserver.sysaccept => file_descriptor + * + * Accepts a new connection. + * It returns the new file descriptor which is an integer. + * + * UNIXServer.open("/tmp/sock") {|serv| + * UNIXSocket.open("/tmp/sock") {|c| + * fd = serv.sysaccept + * s = IO.new(fd) + * s.puts "hi" + * s.close + * p c.read #=> "hi\n" + * } + * } + * + */ +static VALUE +unix_sysaccept(VALUE sock) +{ + rb_io_t *fptr; + struct sockaddr_un from; + socklen_t fromlen; + + GetOpenFile(sock, fptr); + fromlen = sizeof(struct sockaddr_un); + return s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); +} + +#endif + +/* + * UNIXServer class + */ +void +Init_unixserver(void) +{ +#ifdef HAVE_SYS_UN_H + rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket); + rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1); + rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0); + rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0); + rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0); + rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1); +#endif +} |