beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luasocket / src / unix.c
blob73e7b69544cbc38afe049e36f64f5f2ee41f2ec6
1 /*=========================================================================*\
2 * Unix domain socket
3 * LuaSocket toolkit
4 \*=========================================================================*/
5 #include <string.h>
7 #include "lua.h"
8 #include "lauxlib.h"
10 #include "auxiliar.h"
11 #include "socket.h"
12 #include "options.h"
13 #include "unix.h"
14 #include <sys/un.h>
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[] = {
41 {"__gc", meth_close},
42 {"__tostring", auxiliar_tostring},
43 {"accept", meth_accept},
44 {"bind", meth_bind},
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},
53 {"send", meth_send},
54 {"setfd", meth_setfd},
55 {"setoption", meth_setoption},
56 {"setpeername", meth_connect},
57 {"setsockname", meth_bind},
58 {"settimeout", meth_settimeout},
59 {"shutdown", meth_shutdown},
60 {NULL, NULL}
63 /* socket option handlers */
64 static t_opt optset[] = {
65 {"keepalive", opt_set_keepalive},
66 {"reuseaddr", opt_set_reuseaddr},
67 {"linger", opt_set_linger},
68 {NULL, NULL}
71 /* our socket creation function */
72 static luaL_Reg func[] = {
73 {"unix", global_create},
74 {NULL, NULL}
78 /*-------------------------------------------------------------------------*\
79 * Initializes module
80 \*-------------------------------------------------------------------------*/
81 int luaopen_socket_unix(lua_State *L) {
82 /* create classes */
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");
94 lua_gettable(L, -2);
95 return 1;
98 /*=========================================================================*\
99 * Lua methods
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);
138 return 1;
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);
145 return 0;
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));
151 return 1;
154 /*-------------------------------------------------------------------------*\
155 * Waits for and returns a client object attempting connection to the
156 * server object
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);
161 t_socket sock;
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);
169 clnt->sock = 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);
174 return 1;
175 } else {
176 lua_pushnil(L);
177 lua_pushstring(L, socket_strerror(err));
178 return 2;
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);
188 int err;
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)
195 + len + 1;
196 err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
198 #else
199 err = socket_bind(&un->sock, (SA *) &local,
200 sizeof(local.sun_family) + len);
201 #endif
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);
210 if (err) {
211 lua_pushnil(L);
212 lua_pushstring(L, err);
213 return 2;
215 lua_pushnumber(L, 1);
216 return 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;
225 int err;
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)
234 + len + 1;
235 err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
236 #else
237 err = socket_connect(&un->sock, (SA *) &remote,
238 sizeof(remote.sun_family) + len, &un->tm);
239 #endif
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);
249 if (err) {
250 lua_pushnil(L);
251 lua_pushstring(L, err);
252 return 2;
254 /* turn master object into a client object */
255 auxiliar_setclass(L, "unix{client}", 1);
256 lua_pushnumber(L, 1);
257 return 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);
268 return 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) {
280 lua_pushnil(L);
281 lua_pushstring(L, socket_strerror(err));
282 return 2;
284 /* turn master object into a server object */
285 auxiliar_setclass(L, "unix{server}", 1);
286 lua_pushnumber(L, 1);
287 return 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);
301 return 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 /*=========================================================================*\
313 * Library functions
314 \*=========================================================================*/
315 /*-------------------------------------------------------------------------*\
316 * Creates a master unix object
317 \*-------------------------------------------------------------------------*/
318 static int global_create(lua_State *L) {
319 t_socket sock;
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);
329 un->sock = 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);
334 return 1;
335 } else {
336 lua_pushnil(L);
337 lua_pushstring(L, socket_strerror(err));
338 return 2;