1 /*=========================================================================*\
4 \*=========================================================================*/
16 /*=========================================================================*\
17 * Internal function prototypes
18 \*=========================================================================*/
19 static int global_create(lua_State
*L
);
20 static int meth_connect(lua_State
*L
);
21 static int meth_listen(lua_State
*L
);
22 static int meth_bind(lua_State
*L
);
23 static int meth_send(lua_State
*L
);
24 static int meth_shutdown(lua_State
*L
);
25 static int meth_receive(lua_State
*L
);
26 static int meth_accept(lua_State
*L
);
27 static int meth_close(lua_State
*L
);
28 static int meth_setoption(lua_State
*L
);
29 static int meth_settimeout(lua_State
*L
);
30 static int meth_getfd(lua_State
*L
);
31 static int meth_setfd(lua_State
*L
);
32 static int meth_dirty(lua_State
*L
);
33 static int meth_getstats(lua_State
*L
);
34 static int meth_setstats(lua_State
*L
);
36 static const char *unix_tryconnect(p_unix un
, const char *path
);
37 static const char *unix_trybind(p_unix un
, const char *path
);
39 /* unix object methods */
40 static luaL_Reg unix_methods
[] = {
42 {"__tostring", auxiliar_tostring
},
43 {"accept", meth_accept
},
45 {"close", meth_close
},
46 {"connect", meth_connect
},
47 {"dirty", meth_dirty
},
48 {"getfd", meth_getfd
},
49 {"getstats", meth_getstats
},
50 {"setstats", meth_setstats
},
51 {"listen", meth_listen
},
52 {"receive", meth_receive
},
54 {"setfd", meth_setfd
},
55 {"setoption", meth_setoption
},
56 {"setpeername", meth_connect
},
57 {"setsockname", meth_bind
},
58 {"settimeout", meth_settimeout
},
59 {"shutdown", meth_shutdown
},
63 /* socket option handlers */
64 static t_opt optset
[] = {
65 {"keepalive", opt_set_keepalive
},
66 {"reuseaddr", opt_set_reuseaddr
},
67 {"linger", opt_set_linger
},
71 /* our socket creation function */
72 static luaL_Reg func
[] = {
73 {"unix", global_create
},
78 /*-------------------------------------------------------------------------*\
80 \*-------------------------------------------------------------------------*/
81 int luaopen_socket_unix(lua_State
*L
) {
83 auxiliar_newclass(L
, "unix{master}", unix_methods
);
84 auxiliar_newclass(L
, "unix{client}", unix_methods
);
85 auxiliar_newclass(L
, "unix{server}", unix_methods
);
86 /* create class groups */
87 auxiliar_add2group(L
, "unix{master}", "unix{any}");
88 auxiliar_add2group(L
, "unix{client}", "unix{any}");
89 auxiliar_add2group(L
, "unix{server}", "unix{any}");
90 /* make sure the function ends up in the package table */
91 luaL_openlib(L
, "socket", func
, 0);
92 /* return the function instead of the 'socket' table */
93 lua_pushstring(L
, "unix");
98 /*=========================================================================*\
100 \*=========================================================================*/
101 /*-------------------------------------------------------------------------*\
102 * Just call buffered IO methods
103 \*-------------------------------------------------------------------------*/
104 static int meth_send(lua_State
*L
) {
105 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{client}", 1);
106 return buffer_meth_send(L
, &un
->buf
);
109 static int meth_receive(lua_State
*L
) {
110 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{client}", 1);
111 return buffer_meth_receive(L
, &un
->buf
);
114 static int meth_getstats(lua_State
*L
) {
115 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{client}", 1);
116 return buffer_meth_getstats(L
, &un
->buf
);
119 static int meth_setstats(lua_State
*L
) {
120 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{client}", 1);
121 return buffer_meth_setstats(L
, &un
->buf
);
124 /*-------------------------------------------------------------------------*\
125 * Just call option handler
126 \*-------------------------------------------------------------------------*/
127 static int meth_setoption(lua_State
*L
) {
128 p_unix un
= (p_unix
) auxiliar_checkgroup(L
, "unix{any}", 1);
129 return opt_meth_setoption(L
, optset
, &un
->sock
);
132 /*-------------------------------------------------------------------------*\
133 * Select support methods
134 \*-------------------------------------------------------------------------*/
135 static int meth_getfd(lua_State
*L
) {
136 p_unix un
= (p_unix
) auxiliar_checkgroup(L
, "unix{any}", 1);
137 lua_pushnumber(L
, (int) un
->sock
);
141 /* this is very dangerous, but can be handy for those that are brave enough */
142 static int meth_setfd(lua_State
*L
) {
143 p_unix un
= (p_unix
) auxiliar_checkgroup(L
, "unix{any}", 1);
144 un
->sock
= (t_socket
) luaL_checknumber(L
, 2);
148 static int meth_dirty(lua_State
*L
) {
149 p_unix un
= (p_unix
) auxiliar_checkgroup(L
, "unix{any}", 1);
150 lua_pushboolean(L
, !buffer_isempty(&un
->buf
));
154 /*-------------------------------------------------------------------------*\
155 * Waits for and returns a client object attempting connection to the
157 \*-------------------------------------------------------------------------*/
158 static int meth_accept(lua_State
*L
) {
159 p_unix server
= (p_unix
) auxiliar_checkclass(L
, "unix{server}", 1);
160 p_timeout tm
= timeout_markstart(&server
->tm
);
162 int err
= socket_accept(&server
->sock
, &sock
, NULL
, NULL
, tm
);
163 /* if successful, push client socket */
164 if (err
== IO_DONE
) {
165 p_unix clnt
= (p_unix
) lua_newuserdata(L
, sizeof(t_unix
));
166 auxiliar_setclass(L
, "unix{client}", -1);
167 /* initialize structure fields */
168 socket_setnonblocking(&sock
);
170 io_init(&clnt
->io
, (p_send
)socket_send
, (p_recv
)socket_recv
,
171 (p_error
) socket_ioerror
, &clnt
->sock
);
172 timeout_init(&clnt
->tm
, -1, -1);
173 buffer_init(&clnt
->buf
, &clnt
->io
, &clnt
->tm
);
177 lua_pushstring(L
, socket_strerror(err
));
182 /*-------------------------------------------------------------------------*\
183 * Binds an object to an address
184 \*-------------------------------------------------------------------------*/
185 static const char *unix_trybind(p_unix un
, const char *path
) {
186 struct sockaddr_un local
;
187 size_t len
= strlen(path
);
189 if (len
>= sizeof(local
.sun_path
)) return "path too long";
190 memset(&local
, 0, sizeof(local
));
191 strcpy(local
.sun_path
, path
);
192 local
.sun_family
= AF_UNIX
;
193 #ifdef UNIX_HAS_SUN_LEN
194 local
.sun_len
= sizeof(local
.sun_family
) + sizeof(local
.sun_len
)
196 err
= socket_bind(&un
->sock
, (SA
*) &local
, local
.sun_len
);
199 err
= socket_bind(&un
->sock
, (SA
*) &local
,
200 sizeof(local
.sun_family
) + len
);
202 if (err
!= IO_DONE
) socket_destroy(&un
->sock
);
203 return socket_strerror(err
);
206 static int meth_bind(lua_State
*L
) {
207 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{master}", 1);
208 const char *path
= luaL_checkstring(L
, 2);
209 const char *err
= unix_trybind(un
, path
);
212 lua_pushstring(L
, err
);
215 lua_pushnumber(L
, 1);
219 /*-------------------------------------------------------------------------*\
220 * Turns a master unix object into a client object.
221 \*-------------------------------------------------------------------------*/
222 static const char *unix_tryconnect(p_unix un
, const char *path
)
224 struct sockaddr_un remote
;
226 size_t len
= strlen(path
);
227 if (len
>= sizeof(remote
.sun_path
)) return "path too long";
228 memset(&remote
, 0, sizeof(remote
));
229 strcpy(remote
.sun_path
, path
);
230 remote
.sun_family
= AF_UNIX
;
231 timeout_markstart(&un
->tm
);
232 #ifdef UNIX_HAS_SUN_LEN
233 remote
.sun_len
= sizeof(remote
.sun_family
) + sizeof(remote
.sun_len
)
235 err
= socket_connect(&un
->sock
, (SA
*) &remote
, remote
.sun_len
, &un
->tm
);
237 err
= socket_connect(&un
->sock
, (SA
*) &remote
,
238 sizeof(remote
.sun_family
) + len
, &un
->tm
);
240 if (err
!= IO_DONE
) socket_destroy(&un
->sock
);
241 return socket_strerror(err
);
244 static int meth_connect(lua_State
*L
)
246 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{master}", 1);
247 const char *path
= luaL_checkstring(L
, 2);
248 const char *err
= unix_tryconnect(un
, path
);
251 lua_pushstring(L
, err
);
254 /* turn master object into a client object */
255 auxiliar_setclass(L
, "unix{client}", 1);
256 lua_pushnumber(L
, 1);
260 /*-------------------------------------------------------------------------*\
261 * Closes socket used by object
262 \*-------------------------------------------------------------------------*/
263 static int meth_close(lua_State
*L
)
265 p_unix un
= (p_unix
) auxiliar_checkgroup(L
, "unix{any}", 1);
266 socket_destroy(&un
->sock
);
267 lua_pushnumber(L
, 1);
271 /*-------------------------------------------------------------------------*\
272 * Puts the sockt in listen mode
273 \*-------------------------------------------------------------------------*/
274 static int meth_listen(lua_State
*L
)
276 p_unix un
= (p_unix
) auxiliar_checkclass(L
, "unix{master}", 1);
277 int backlog
= (int) luaL_optnumber(L
, 2, 32);
278 int err
= socket_listen(&un
->sock
, backlog
);
279 if (err
!= IO_DONE
) {
281 lua_pushstring(L
, socket_strerror(err
));
284 /* turn master object into a server object */
285 auxiliar_setclass(L
, "unix{server}", 1);
286 lua_pushnumber(L
, 1);
290 /*-------------------------------------------------------------------------*\
291 * Shuts the connection down partially
292 \*-------------------------------------------------------------------------*/
293 static int meth_shutdown(lua_State
*L
)
295 /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
296 static const char* methods
[] = { "receive", "send", "both", NULL
};
297 p_unix tcp
= (p_unix
) auxiliar_checkclass(L
, "unix{client}", 1);
298 int how
= luaL_checkoption(L
, 2, "both", methods
);
299 socket_shutdown(&tcp
->sock
, how
);
300 lua_pushnumber(L
, 1);
304 /*-------------------------------------------------------------------------*\
305 * Just call tm methods
306 \*-------------------------------------------------------------------------*/
307 static int meth_settimeout(lua_State
*L
) {
308 p_unix un
= (p_unix
) auxiliar_checkgroup(L
, "unix{any}", 1);
309 return timeout_meth_settimeout(L
, &un
->tm
);
312 /*=========================================================================*\
314 \*=========================================================================*/
315 /*-------------------------------------------------------------------------*\
316 * Creates a master unix object
317 \*-------------------------------------------------------------------------*/
318 static int global_create(lua_State
*L
) {
320 int err
= socket_create(&sock
, AF_UNIX
, SOCK_STREAM
, 0);
321 /* try to allocate a system socket */
322 if (err
== IO_DONE
) {
323 /* allocate unix object */
324 p_unix un
= (p_unix
) lua_newuserdata(L
, sizeof(t_unix
));
325 /* set its type as master object */
326 auxiliar_setclass(L
, "unix{master}", -1);
327 /* initialize remaining structure fields */
328 socket_setnonblocking(&sock
);
330 io_init(&un
->io
, (p_send
) socket_send
, (p_recv
) socket_recv
,
331 (p_error
) socket_ioerror
, &un
->sock
);
332 timeout_init(&un
->tm
, -1, -1);
333 buffer_init(&un
->buf
, &un
->io
, &un
->tm
);
337 lua_pushstring(L
, socket_strerror(err
));