comparison src/unix.c @ 0:4b915342e2a8

LuaSocket 2.0.2 + CMake build description.
author Eric Wing <ewing . public |-at-| gmail . com>
date Tue, 26 Aug 2008 18:40:01 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4b915342e2a8
1 /*=========================================================================*\
2 * Unix domain socket
3 * LuaSocket toolkit
4 *
5 * RCS ID: $Id: unix.c,v 1.13 2006/03/13 07:16:39 diego Exp $
6 \*=========================================================================*/
7 #include <string.h>
8
9 #include "lua.h"
10 #include "lauxlib.h"
11
12 #include "auxiliar.h"
13 #include "socket.h"
14 #include "options.h"
15 #include "unix.h"
16 #include <sys/un.h>
17
18 /*=========================================================================*\
19 * Internal function prototypes
20 \*=========================================================================*/
21 static int global_create(lua_State *L);
22 static int meth_connect(lua_State *L);
23 static int meth_listen(lua_State *L);
24 static int meth_bind(lua_State *L);
25 static int meth_send(lua_State *L);
26 static int meth_shutdown(lua_State *L);
27 static int meth_receive(lua_State *L);
28 static int meth_accept(lua_State *L);
29 static int meth_close(lua_State *L);
30 static int meth_setoption(lua_State *L);
31 static int meth_settimeout(lua_State *L);
32 static int meth_getfd(lua_State *L);
33 static int meth_setfd(lua_State *L);
34 static int meth_dirty(lua_State *L);
35 static int meth_getstats(lua_State *L);
36 static int meth_setstats(lua_State *L);
37
38 static const char *unix_tryconnect(p_unix un, const char *path);
39 static const char *unix_trybind(p_unix un, const char *path);
40
41 /* unix object methods */
42 static luaL_reg un[] = {
43 {"__gc", meth_close},
44 {"__tostring", auxiliar_tostring},
45 {"accept", meth_accept},
46 {"bind", meth_bind},
47 {"close", meth_close},
48 {"connect", meth_connect},
49 {"dirty", meth_dirty},
50 {"getfd", meth_getfd},
51 {"getstats", meth_getstats},
52 {"setstats", meth_setstats},
53 {"listen", meth_listen},
54 {"receive", meth_receive},
55 {"send", meth_send},
56 {"setfd", meth_setfd},
57 {"setoption", meth_setoption},
58 {"setpeername", meth_connect},
59 {"setsockname", meth_bind},
60 {"settimeout", meth_settimeout},
61 {"shutdown", meth_shutdown},
62 {NULL, NULL}
63 };
64
65 /* socket option handlers */
66 static t_opt opt[] = {
67 {"keepalive", opt_keepalive},
68 {"reuseaddr", opt_reuseaddr},
69 {"linger", opt_linger},
70 {NULL, NULL}
71 };
72
73 /* our socket creation function */
74 static luaL_reg func[] = {
75 {"unix", global_create},
76 {NULL, NULL}
77 };
78
79
80 /*-------------------------------------------------------------------------*\
81 * Initializes module
82 \*-------------------------------------------------------------------------*/
83 int luaopen_socket_unix(lua_State *L) {
84 /* create classes */
85 auxiliar_newclass(L, "unix{master}", un);
86 auxiliar_newclass(L, "unix{client}", un);
87 auxiliar_newclass(L, "unix{server}", un);
88 /* create class groups */
89 auxiliar_add2group(L, "unix{master}", "unix{any}");
90 auxiliar_add2group(L, "unix{client}", "unix{any}");
91 auxiliar_add2group(L, "unix{server}", "unix{any}");
92 /* make sure the function ends up in the package table */
93 luaL_openlib(L, "socket", func, 0);
94 /* return the function instead of the 'socket' table */
95 lua_pushstring(L, "unix");
96 lua_gettable(L, -2);
97 return 1;
98 }
99
100 /*=========================================================================*\
101 * Lua methods
102 \*=========================================================================*/
103 /*-------------------------------------------------------------------------*\
104 * Just call buffered IO methods
105 \*-------------------------------------------------------------------------*/
106 static int meth_send(lua_State *L) {
107 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
108 return buffer_meth_send(L, &un->buf);
109 }
110
111 static int meth_receive(lua_State *L) {
112 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
113 return buffer_meth_receive(L, &un->buf);
114 }
115
116 static int meth_getstats(lua_State *L) {
117 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
118 return buffer_meth_getstats(L, &un->buf);
119 }
120
121 static int meth_setstats(lua_State *L) {
122 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
123 return buffer_meth_setstats(L, &un->buf);
124 }
125
126 /*-------------------------------------------------------------------------*\
127 * Just call option handler
128 \*-------------------------------------------------------------------------*/
129 static int meth_setoption(lua_State *L) {
130 p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
131 return opt_meth_setoption(L, opt, &un->sock);
132 }
133
134 /*-------------------------------------------------------------------------*\
135 * Select support methods
136 \*-------------------------------------------------------------------------*/
137 static int meth_getfd(lua_State *L) {
138 p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
139 lua_pushnumber(L, (int) un->sock);
140 return 1;
141 }
142
143 /* this is very dangerous, but can be handy for those that are brave enough */
144 static int meth_setfd(lua_State *L) {
145 p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
146 un->sock = (t_socket) luaL_checknumber(L, 2);
147 return 0;
148 }
149
150 static int meth_dirty(lua_State *L) {
151 p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
152 lua_pushboolean(L, !buffer_isempty(&un->buf));
153 return 1;
154 }
155
156 /*-------------------------------------------------------------------------*\
157 * Waits for and returns a client object attempting connection to the
158 * server object
159 \*-------------------------------------------------------------------------*/
160 static int meth_accept(lua_State *L) {
161 p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1);
162 p_timeout tm = timeout_markstart(&server->tm);
163 t_socket sock;
164 int err = socket_accept(&server->sock, &sock, NULL, NULL, tm);
165 /* if successful, push client socket */
166 if (err == IO_DONE) {
167 p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix));
168 auxiliar_setclass(L, "unix{client}", -1);
169 /* initialize structure fields */
170 socket_setnonblocking(&sock);
171 clnt->sock = sock;
172 io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
173 (p_error) socket_ioerror, &clnt->sock);
174 timeout_init(&clnt->tm, -1, -1);
175 buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
176 return 1;
177 } else {
178 lua_pushnil(L);
179 lua_pushstring(L, socket_strerror(err));
180 return 2;
181 }
182 }
183
184 /*-------------------------------------------------------------------------*\
185 * Binds an object to an address
186 \*-------------------------------------------------------------------------*/
187 static const char *unix_trybind(p_unix un, const char *path) {
188 struct sockaddr_un local;
189 size_t len = strlen(path);
190 int err;
191 if (len >= sizeof(local.sun_path)) return "path too long";
192 memset(&local, 0, sizeof(local));
193 strcpy(local.sun_path, path);
194 local.sun_family = AF_UNIX;
195 #ifdef UNIX_HAS_SUN_LEN
196 local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
197 + len + 1;
198 err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
199
200 #else
201 err = socket_bind(&un->sock, (SA *) &local,
202 sizeof(local.sun_family) + len);
203 #endif
204 if (err != IO_DONE) socket_destroy(&un->sock);
205 return socket_strerror(err);
206 }
207
208 static int meth_bind(lua_State *L) {
209 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1);
210 const char *path = luaL_checkstring(L, 2);
211 const char *err = unix_trybind(un, path);
212 if (err) {
213 lua_pushnil(L);
214 lua_pushstring(L, err);
215 return 2;
216 }
217 lua_pushnumber(L, 1);
218 return 1;
219 }
220
221 /*-------------------------------------------------------------------------*\
222 * Turns a master unix object into a client object.
223 \*-------------------------------------------------------------------------*/
224 static const char *unix_tryconnect(p_unix un, const char *path)
225 {
226 struct sockaddr_un remote;
227 int err;
228 size_t len = strlen(path);
229 if (len >= sizeof(remote.sun_path)) return "path too long";
230 memset(&remote, 0, sizeof(remote));
231 strcpy(remote.sun_path, path);
232 remote.sun_family = AF_UNIX;
233 timeout_markstart(&un->tm);
234 #ifdef UNIX_HAS_SUN_LEN
235 remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
236 + len + 1;
237 err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
238 #else
239 err = socket_connect(&un->sock, (SA *) &remote,
240 sizeof(remote.sun_family) + len, &un->tm);
241 #endif
242 if (err != IO_DONE) socket_destroy(&un->sock);
243 return socket_strerror(err);
244 }
245
246 static int meth_connect(lua_State *L)
247 {
248 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1);
249 const char *path = luaL_checkstring(L, 2);
250 const char *err = unix_tryconnect(un, path);
251 if (err) {
252 lua_pushnil(L);
253 lua_pushstring(L, err);
254 return 2;
255 }
256 /* turn master object into a client object */
257 auxiliar_setclass(L, "unix{client}", 1);
258 lua_pushnumber(L, 1);
259 return 1;
260 }
261
262 /*-------------------------------------------------------------------------*\
263 * Closes socket used by object
264 \*-------------------------------------------------------------------------*/
265 static int meth_close(lua_State *L)
266 {
267 p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
268 socket_destroy(&un->sock);
269 lua_pushnumber(L, 1);
270 return 1;
271 }
272
273 /*-------------------------------------------------------------------------*\
274 * Puts the sockt in listen mode
275 \*-------------------------------------------------------------------------*/
276 static int meth_listen(lua_State *L)
277 {
278 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{master}", 1);
279 int backlog = (int) luaL_optnumber(L, 2, 32);
280 int err = socket_listen(&un->sock, backlog);
281 if (err != IO_DONE) {
282 lua_pushnil(L);
283 lua_pushstring(L, socket_strerror(err));
284 return 2;
285 }
286 /* turn master object into a server object */
287 auxiliar_setclass(L, "unix{server}", 1);
288 lua_pushnumber(L, 1);
289 return 1;
290 }
291
292 /*-------------------------------------------------------------------------*\
293 * Shuts the connection down partially
294 \*-------------------------------------------------------------------------*/
295 static int meth_shutdown(lua_State *L)
296 {
297 p_unix un = (p_unix) auxiliar_checkclass(L, "unix{client}", 1);
298 const char *how = luaL_optstring(L, 2, "both");
299 switch (how[0]) {
300 case 'b':
301 if (strcmp(how, "both")) goto error;
302 socket_shutdown(&un->sock, 2);
303 break;
304 case 's':
305 if (strcmp(how, "send")) goto error;
306 socket_shutdown(&un->sock, 1);
307 break;
308 case 'r':
309 if (strcmp(how, "receive")) goto error;
310 socket_shutdown(&un->sock, 0);
311 break;
312 }
313 lua_pushnumber(L, 1);
314 return 1;
315 error:
316 luaL_argerror(L, 2, "invalid shutdown method");
317 return 0;
318 }
319
320 /*-------------------------------------------------------------------------*\
321 * Just call tm methods
322 \*-------------------------------------------------------------------------*/
323 static int meth_settimeout(lua_State *L) {
324 p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
325 return timeout_meth_settimeout(L, &un->tm);
326 }
327
328 /*=========================================================================*\
329 * Library functions
330 \*=========================================================================*/
331 /*-------------------------------------------------------------------------*\
332 * Creates a master unix object
333 \*-------------------------------------------------------------------------*/
334 static int global_create(lua_State *L) {
335 t_socket sock;
336 int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
337 /* try to allocate a system socket */
338 if (err == IO_DONE) {
339 /* allocate unix object */
340 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
341 /* set its type as master object */
342 auxiliar_setclass(L, "unix{master}", -1);
343 /* initialize remaining structure fields */
344 socket_setnonblocking(&sock);
345 un->sock = sock;
346 io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
347 (p_error) socket_ioerror, &un->sock);
348 timeout_init(&un->tm, -1, -1);
349 buffer_init(&un->buf, &un->io, &un->tm);
350 return 1;
351 } else {
352 lua_pushnil(L);
353 lua_pushstring(L, socket_strerror(err));
354 return 2;
355 }
356 }