1/************************************************ 2 3 unixserver.c - 4 5 created at: Thu Mar 31 12:21:29 JST 1994 6 7 Copyright (C) 1993-2007 Yukihiro Matsumoto 8 9************************************************/ 10 11#include "rubysocket.h" 12 13#ifdef HAVE_SYS_UN_H 14/* 15 * call-seq: 16 * UNIXServer.new(path) => unixserver 17 * 18 * Creates a new UNIX server socket bound to _path_. 19 * 20 * serv = UNIXServer.new("/tmp/sock") 21 * s = serv.accept 22 * p s.read 23 */ 24static VALUE 25unix_svr_init(VALUE sock, VALUE path) 26{ 27 return rsock_init_unixsock(sock, path, 1); 28} 29 30/* 31 * call-seq: 32 * unixserver.accept => unixsocket 33 * 34 * Accepts a new connection. 35 * It returns new UNIXSocket object. 36 * 37 * UNIXServer.open("/tmp/sock") {|serv| 38 * UNIXSocket.open("/tmp/sock") {|c| 39 * s = serv.accept 40 * s.puts "hi" 41 * s.close 42 * p c.read #=> "hi\n" 43 * } 44 * } 45 * 46 */ 47static VALUE 48unix_accept(VALUE sock) 49{ 50 rb_io_t *fptr; 51 struct sockaddr_un from; 52 socklen_t fromlen; 53 54 GetOpenFile(sock, fptr); 55 fromlen = (socklen_t)sizeof(struct sockaddr_un); 56 return rsock_s_accept(rb_cUNIXSocket, fptr->fd, 57 (struct sockaddr*)&from, &fromlen); 58} 59 60/* 61 * call-seq: 62 * unixserver.accept_nonblock => unixsocket 63 * 64 * Accepts an incoming connection using accept(2) after 65 * O_NONBLOCK is set for the underlying file descriptor. 66 * It returns an accepted UNIXSocket for the incoming connection. 67 * 68 * === Example 69 * require 'socket' 70 * serv = UNIXServer.new("/tmp/sock") 71 * begin # emulate blocking accept 72 * sock = serv.accept_nonblock 73 * rescue IO::WaitReadable, Errno::EINTR 74 * IO.select([serv]) 75 * retry 76 * end 77 * # sock is an accepted socket. 78 * 79 * Refer to Socket#accept for the exceptions that may be thrown if the call 80 * to UNIXServer#accept_nonblock fails. 81 * 82 * UNIXServer#accept_nonblock may raise any error corresponding to accept(2) failure, 83 * including Errno::EWOULDBLOCK. 84 * 85 * If the exception is Errno::EWOULDBLOCK, Errno::AGAIN, Errno::ECONNABORTED or Errno::EPROTO, 86 * it is extended by IO::WaitReadable. 87 * So IO::WaitReadable can be used to rescue the exceptions for retrying accept_nonblock. 88 * 89 * === See 90 * * UNIXServer#accept 91 * * Socket#accept 92 */ 93static VALUE 94unix_accept_nonblock(VALUE sock) 95{ 96 rb_io_t *fptr; 97 struct sockaddr_un from; 98 socklen_t fromlen; 99 100 GetOpenFile(sock, fptr); 101 fromlen = (socklen_t)sizeof(from); 102 return rsock_s_accept_nonblock(rb_cUNIXSocket, fptr, 103 (struct sockaddr *)&from, &fromlen); 104} 105 106/* 107 * call-seq: 108 * unixserver.sysaccept => file_descriptor 109 * 110 * Accepts a new connection. 111 * It returns the new file descriptor which is an integer. 112 * 113 * UNIXServer.open("/tmp/sock") {|serv| 114 * UNIXSocket.open("/tmp/sock") {|c| 115 * fd = serv.sysaccept 116 * s = IO.new(fd) 117 * s.puts "hi" 118 * s.close 119 * p c.read #=> "hi\n" 120 * } 121 * } 122 * 123 */ 124static VALUE 125unix_sysaccept(VALUE sock) 126{ 127 rb_io_t *fptr; 128 struct sockaddr_un from; 129 socklen_t fromlen; 130 131 GetOpenFile(sock, fptr); 132 fromlen = (socklen_t)sizeof(struct sockaddr_un); 133 return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); 134} 135 136#endif 137 138void 139rsock_init_unixserver(void) 140{ 141#ifdef HAVE_SYS_UN_H 142 /* 143 * Document-class: UNIXServer < UNIXSocket 144 * 145 * UNIXServer represents a UNIX domain stream server socket. 146 * 147 */ 148 rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket); 149 rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1); 150 rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0); 151 rb_define_method(rb_cUNIXServer, "accept_nonblock", unix_accept_nonblock, 0); 152 rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0); 153 rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */ 154#endif 155} 156