Mercurial > luasocket
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 } |