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  *   require 'socket'
21  *
22  *   serv = UNIXServer.new("/tmp/sock")
23  *   s = serv.accept
24  *   p s.read
25  */
26 static VALUE
unix_svr_init(VALUE sock,VALUE path)27 unix_svr_init(VALUE sock, VALUE path)
28 {
29     return rsock_init_unixsock(sock, path, 1);
30 }
31 
32 /*
33  * call-seq:
34  *   unixserver.accept => unixsocket
35  *
36  * Accepts an incoming connection.
37  * It returns a new UNIXSocket object.
38  *
39  *   UNIXServer.open("/tmp/sock") {|serv|
40  *     UNIXSocket.open("/tmp/sock") {|c|
41  *       s = serv.accept
42  *       s.puts "hi"
43  *       s.close
44  *       p c.read #=> "hi\n"
45  *     }
46  *   }
47  *
48  */
49 static VALUE
unix_accept(VALUE sock)50 unix_accept(VALUE sock)
51 {
52     rb_io_t *fptr;
53     struct sockaddr_un from;
54     socklen_t fromlen;
55 
56     GetOpenFile(sock, fptr);
57     fromlen = (socklen_t)sizeof(struct sockaddr_un);
58     return rsock_s_accept(rb_cUNIXSocket, fptr->fd,
59 		          (struct sockaddr*)&from, &fromlen);
60 }
61 
62 /* :nodoc: */
63 static VALUE
unix_accept_nonblock(VALUE sock,VALUE ex)64 unix_accept_nonblock(VALUE sock, VALUE ex)
65 {
66     rb_io_t *fptr;
67     struct sockaddr_un from;
68     socklen_t fromlen;
69 
70     GetOpenFile(sock, fptr);
71     fromlen = (socklen_t)sizeof(from);
72     return rsock_s_accept_nonblock(rb_cUNIXSocket, ex, fptr,
73 			           (struct sockaddr *)&from, &fromlen);
74 }
75 
76 /*
77  * call-seq:
78  *   unixserver.sysaccept => file_descriptor
79  *
80  * Accepts a new connection.
81  * It returns the new file descriptor which is an integer.
82  *
83  *   UNIXServer.open("/tmp/sock") {|serv|
84  *     UNIXSocket.open("/tmp/sock") {|c|
85  *       fd = serv.sysaccept
86  *       s = IO.new(fd)
87  *       s.puts "hi"
88  *       s.close
89  *       p c.read #=> "hi\n"
90  *     }
91  *   }
92  *
93  */
94 static VALUE
unix_sysaccept(VALUE sock)95 unix_sysaccept(VALUE sock)
96 {
97     rb_io_t *fptr;
98     struct sockaddr_un from;
99     socklen_t fromlen;
100 
101     GetOpenFile(sock, fptr);
102     fromlen = (socklen_t)sizeof(struct sockaddr_un);
103     return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen);
104 }
105 
106 #endif
107 
108 void
rsock_init_unixserver(void)109 rsock_init_unixserver(void)
110 {
111 #ifdef HAVE_SYS_UN_H
112     /*
113      * Document-class: UNIXServer < UNIXSocket
114      *
115      * UNIXServer represents a UNIX domain stream server socket.
116      *
117      */
118     rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
119     rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
120     rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
121 
122     rb_define_private_method(rb_cUNIXServer,
123 			     "__accept_nonblock", unix_accept_nonblock, 1);
124 
125     rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
126     rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */
127 #endif
128 }
129