aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-22 16:12:53 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-22 16:12:53 +0000
commit1ce47ebe3942a8b18b3b709f1ad915ac9ce82782 (patch)
tree7e78b55363929ecd43ac01a64dec6f22b2386215
parent7195ab620bd5029856a5c6c88e54a9a6eceb5e87 (diff)
downloadluasocket-1ce47ebe3942a8b18b3b709f1ad915ac9ce82782.tar.gz
luasocket-1ce47ebe3942a8b18b3b709f1ad915ac9ce82782.tar.bz2
luasocket-1ce47ebe3942a8b18b3b709f1ad915ac9ce82782.zip
Added support for unix stream sockets.
-rw-r--r--FIX6
-rw-r--r--src/ssl.c70
-rw-r--r--src/ssl.h29
-rw-r--r--src/tcp.c3
-rw-r--r--src/unix.c324
-rw-r--r--src/unix.h28
6 files changed, 457 insertions, 3 deletions
diff --git a/FIX b/FIX
new file mode 100644
index 0000000..6a8913e
--- /dev/null
+++ b/FIX
@@ -0,0 +1,6 @@
1accept/connect interrupt safe
2accepted sockets are nonblocking
3new timming functions. better sleep/gettime
4bug fixes in the manual
5getfd missing cast
6added unix domain support example
diff --git a/src/ssl.c b/src/ssl.c
new file mode 100644
index 0000000..8e2ce00
--- /dev/null
+++ b/src/ssl.c
@@ -0,0 +1,70 @@
1/*=========================================================================*\
2* Simple client SSL support
3* LuaSocket toolkit
4*
5* RCS ID: $Id$
6\*=========================================================================*/
7#include <lua.h>
8#include <lauxlib.h>
9
10#include "ssl.h"
11
12/*=========================================================================*\
13* Internal function prototypes
14\*=========================================================================*/
15static int global_wrap(lua_State *L);
16
17/* functions in library namespace */
18static luaL_reg func[] = {
19 {"wrap", global_create},
20 {NULL, NULL}
21};
22
23static luaL_reg wrap[] = {
24 {"__tostring", aux_tostring},
25 {"__gc", meth_close},
26 {"close", meth_close},
27 {"receive", meth_receive},
28 {"send", meth_send},
29 {NULL, NULL}
30};
31
32static luaL_reg owned[] = {
33 {"__tostring", aux_tostring},
34 {NULL, NULL}
35};
36
37/*-------------------------------------------------------------------------*\
38* Initializes module
39\*-------------------------------------------------------------------------*/
40int ssl_open(lua_State *L)
41{
42 aux_newclass(L, "ssl{wraper}", wrap);
43 aux_newclass(L, "ssl{owned}", owned);
44 lua_pushstring(L, "ssl")
45 lua_newtable(L);
46 luaL_openlib(L, NULL, func, 0);
47 lua_settable(L, -3);
48 return 0;
49}
50
51/*=========================================================================*\
52* Library functions
53\*=========================================================================*/
54/*-------------------------------------------------------------------------*\
55* Wraps a tcp object into an SSL object
56\*-------------------------------------------------------------------------*/
57static int global_wrap(lua_State *L) {
58 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
59 /* change class of tcp object */
60 aux_setclass(L, "ssl{owned}", 1);
61 /* create wrapper */
62 p_wrap wrap = (p_wrap) lua_newuserdata(L, sizeof(t_wrap));
63 /* lock reference */
64 lua_pushvalue(L, 1);
65 wrap->ref = lua_ref(L, 1);
66 /* initialize wrapper */
67 wrap->tcp = tcp;
68 io_init(&tcp->io, wrap_send, wrap_recv, wrap);
69 return 1;
70}
diff --git a/src/ssl.h b/src/ssl.h
new file mode 100644
index 0000000..13ce97b
--- /dev/null
+++ b/src/ssl.h
@@ -0,0 +1,29 @@
1#ifndef SSL_H
2#define SSL_H
3/*=========================================================================*\
4* Simple client SSL support
5* LuaSocket toolkit
6*
7* This is just a simple example to show how to extend LuaSocket
8*
9* RCS ID: $Id$
10\*=========================================================================*/
11#include <lua.h>
12#include <openssl/ssl.h>
13
14#include "buffer.h"
15#include "timeout.h"
16#include "socket.h"
17#include "tcp.h"
18
19typedef struct t_wrap_ {
20 p_tcp tcp;
21 SSL* ssl;
22 int ref;
23} t_wrap;
24
25typedef t_wrap *p_wrap;
26
27int ssl_open(lua_State *L);
28
29#endif /* SSL_H */
diff --git a/src/tcp.c b/src/tcp.c
index 1f51b22..6c58494 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -89,9 +89,6 @@ int tcp_open(lua_State *L)
89 aux_add2group(L, "tcp{server}", "tcp{any}"); 89 aux_add2group(L, "tcp{server}", "tcp{any}");
90 aux_add2group(L, "tcp{client}", "tcp{client,server}"); 90 aux_add2group(L, "tcp{client}", "tcp{client,server}");
91 aux_add2group(L, "tcp{server}", "tcp{client,server}"); 91 aux_add2group(L, "tcp{server}", "tcp{client,server}");
92 /* both server and client objects are selectable */
93 aux_add2group(L, "tcp{client}", "select{able}");
94 aux_add2group(L, "tcp{server}", "select{able}");
95 /* define library functions */ 92 /* define library functions */
96 luaL_openlib(L, NULL, func, 0); 93 luaL_openlib(L, NULL, func, 0);
97 return 0; 94 return 0;
diff --git a/src/unix.c b/src/unix.c
new file mode 100644
index 0000000..b2c4659
--- /dev/null
+++ b/src/unix.c
@@ -0,0 +1,324 @@
1/*=========================================================================*\
2* Unix domain socket
3* LuaSocket toolkit
4*
5* RCS ID: $Id$
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\*=========================================================================*/
21static int global_create(lua_State *L);
22static int meth_connect(lua_State *L);
23static int meth_listen(lua_State *L);
24static int meth_bind(lua_State *L);
25static int meth_send(lua_State *L);
26static int meth_shutdown(lua_State *L);
27static int meth_receive(lua_State *L);
28static int meth_accept(lua_State *L);
29static int meth_close(lua_State *L);
30static int meth_setoption(lua_State *L);
31static int meth_settimeout(lua_State *L);
32static int meth_getfd(lua_State *L);
33static int meth_setfd(lua_State *L);
34static int meth_dirty(lua_State *L);
35
36static const char *unix_tryconnect(p_unix unix, const char *path);
37static const char *unix_trybind(p_unix unix, const char *path);
38
39/* unix object methods */
40static luaL_reg unix[] = {
41 {"__gc", meth_close},
42 {"__tostring", aux_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 {"listen", meth_listen},
50 {"receive", meth_receive},
51 {"send", meth_send},
52 {"setfd", meth_setfd},
53 {"setoption", meth_setoption},
54 {"setpeername", meth_connect},
55 {"setsockname", meth_bind},
56 {"settimeout", meth_settimeout},
57 {"shutdown", meth_shutdown},
58 {NULL, NULL}
59};
60
61/* socket option handlers */
62static t_opt opt[] = {
63 {"keepalive", opt_keepalive},
64 {"reuseaddr", opt_reuseaddr},
65 {"linger", opt_linger},
66 {NULL, NULL}
67};
68
69/* functions in library namespace */
70static luaL_reg func[] = {
71 {"unix", global_create},
72 {NULL, NULL}
73};
74
75/*-------------------------------------------------------------------------*\
76* Initializes module
77\*-------------------------------------------------------------------------*/
78int unix_open(lua_State *L) {
79 /* create classes */
80 aux_newclass(L, "unix{master}", unix);
81 aux_newclass(L, "unix{client}", unix);
82 aux_newclass(L, "unix{server}", unix);
83 /* create class groups */
84 aux_add2group(L, "unix{master}", "unix{any}");
85 aux_add2group(L, "unix{client}", "unix{any}");
86 aux_add2group(L, "unix{server}", "unix{any}");
87 aux_add2group(L, "unix{client}", "unix{client,server}");
88 aux_add2group(L, "unix{server}", "unix{client,server}");
89 /* define library functions */
90 luaL_openlib(L, NULL, func, 0);
91 return 0;
92}
93
94/*=========================================================================*\
95* Lua methods
96\*=========================================================================*/
97/*-------------------------------------------------------------------------*\
98* Just call buffered IO methods
99\*-------------------------------------------------------------------------*/
100static int meth_send(lua_State *L) {
101 p_unix unix = (p_unix) aux_checkclass(L, "unix{client}", 1);
102 return buf_meth_send(L, &unix->buf);
103}
104
105static int meth_receive(lua_State *L) {
106 p_unix unix = (p_unix) aux_checkclass(L, "unix{client}", 1);
107 return buf_meth_receive(L, &unix->buf);
108}
109
110/*-------------------------------------------------------------------------*\
111* Just call option handler
112\*-------------------------------------------------------------------------*/
113static int meth_setoption(lua_State *L) {
114 p_unix unix = aux_checkgroup(L, "unix{any}", 1);
115 return opt_meth_setoption(L, opt, &unix->sock);
116}
117
118/*-------------------------------------------------------------------------*\
119* Select support methods
120\*-------------------------------------------------------------------------*/
121static int meth_getfd(lua_State *L) {
122 p_unix unix = (p_unix) aux_checkgroup(L, "unix{any}", 1);
123 lua_pushnumber(L, (int) unix->sock);
124 return 1;
125}
126
127/* this is very dangerous, but can be handy for those that are brave enough */
128static int meth_setfd(lua_State *L) {
129 p_unix unix = (p_unix) aux_checkgroup(L, "unix{any}", 1);
130 unix->sock = (t_sock) luaL_checknumber(L, 2);
131 return 0;
132}
133
134static int meth_dirty(lua_State *L) {
135 p_unix unix = (p_unix) aux_checkgroup(L, "unix{any}", 1);
136 lua_pushboolean(L, !buf_isempty(&unix->buf));
137 return 1;
138}
139
140/*-------------------------------------------------------------------------*\
141* Waits for and returns a client object attempting connection to the
142* server object
143\*-------------------------------------------------------------------------*/
144static int meth_accept(lua_State *L) {
145 p_unix server = (p_unix) aux_checkclass(L, "unix{server}", 1);
146 p_tm tm = tm_markstart(&server->tm);
147 t_sock sock;
148 const char *err = sock_accept(&server->sock, &sock, NULL, NULL, tm);
149 /* if successful, push client socket */
150 if (!err) {
151 p_unix clnt = lua_newuserdata(L, sizeof(t_unix));
152 aux_setclass(L, "unix{client}", -1);
153 /* initialize structure fields */
154 sock_setnonblocking(&sock);
155 clnt->sock = sock;
156 io_init(&clnt->io, (p_send)sock_send, (p_recv)sock_recv, &clnt->sock);
157 tm_init(&clnt->tm, -1, -1);
158 buf_init(&clnt->buf, &clnt->io, &clnt->tm);
159 return 1;
160 } else {
161 lua_pushnil(L);
162 lua_pushstring(L, err);
163 return 2;
164 }
165}
166
167/*-------------------------------------------------------------------------*\
168* Binds an object to an address
169\*-------------------------------------------------------------------------*/
170static const char *unix_trybind(p_unix unix, const char *path) {
171 struct sockaddr_un local;
172 int len = strlen(path);
173 const char *err;
174 if (len >= 92) return "path too long";
175 memset(&local, 0, sizeof(local));
176 strcpy(local.sun_path, path);
177 local.sun_family = AF_UNIX;
178 err = sock_bind(&unix->sock, (SA *) &local,
179 sizeof(local.sun_family) + len);
180 if (err) sock_destroy(&unix->sock);
181 return err;
182}
183
184static int meth_bind(lua_State *L) {
185 p_unix unix = (p_unix) aux_checkclass(L, "unix{master}", 1);
186 const char *path = luaL_checkstring(L, 2);
187 const char *err = unix_trybind(unix, path);
188 if (err) {
189 lua_pushnil(L);
190 lua_pushstring(L, err);
191 return 2;
192 }
193 lua_pushnumber(L, 1);
194 return 1;
195}
196
197/*-------------------------------------------------------------------------*\
198* Turns a master unix object into a client object.
199\*-------------------------------------------------------------------------*/
200static const char *unix_tryconnect(p_unix unix, const char *path)
201{
202 struct sockaddr_un remote;
203 const char *err;
204 int len = strlen(path);
205 if (len >= 92) return "path too long";
206 memset(&remote, 0, sizeof(remote));
207 strcpy(remote.sun_path, path);
208 remote.sun_family = AF_UNIX;
209 tm_markstart(&unix->tm);
210 err = sock_connect(&unix->sock, (SA *) &remote,
211 sizeof(remote.sun_family) + len, &unix->tm);
212 if (err) sock_destroy(&unix->sock);
213 return err;
214}
215
216static int meth_connect(lua_State *L)
217{
218 p_unix unix = (p_unix) aux_checkclass(L, "unix{master}", 1);
219 const char *path = luaL_checkstring(L, 2);
220 const char *err = unix_tryconnect(unix, path);
221 if (err) {
222 lua_pushnil(L);
223 lua_pushstring(L, err);
224 return 2;
225 }
226 /* turn master object into a client object */
227 aux_setclass(L, "unix{client}", 1);
228 lua_pushnumber(L, 1);
229 return 1;
230}
231
232/*-------------------------------------------------------------------------*\
233* Closes socket used by object
234\*-------------------------------------------------------------------------*/
235static int meth_close(lua_State *L)
236{
237 p_unix unix = (p_unix) aux_checkgroup(L, "unix{any}", 1);
238 sock_destroy(&unix->sock);
239 return 0;
240}
241
242/*-------------------------------------------------------------------------*\
243* Puts the sockt in listen mode
244\*-------------------------------------------------------------------------*/
245static int meth_listen(lua_State *L)
246{
247 p_unix unix = (p_unix) aux_checkclass(L, "unix{master}", 1);
248 int backlog = (int) luaL_optnumber(L, 2, 32);
249 const char *err = sock_listen(&unix->sock, backlog);
250 if (err) {
251 lua_pushnil(L);
252 lua_pushstring(L, err);
253 return 2;
254 }
255 /* turn master object into a server object */
256 aux_setclass(L, "unix{server}", 1);
257 lua_pushnumber(L, 1);
258 return 1;
259}
260
261/*-------------------------------------------------------------------------*\
262* Shuts the connection down partially
263\*-------------------------------------------------------------------------*/
264static int meth_shutdown(lua_State *L)
265{
266 p_unix unix = (p_unix) aux_checkgroup(L, "unix{client}", 1);
267 const char *how = luaL_optstring(L, 2, "both");
268 switch (how[0]) {
269 case 'b':
270 if (strcmp(how, "both")) goto error;
271 sock_shutdown(&unix->sock, 2);
272 break;
273 case 's':
274 if (strcmp(how, "send")) goto error;
275 sock_shutdown(&unix->sock, 1);
276 break;
277 case 'r':
278 if (strcmp(how, "receive")) goto error;
279 sock_shutdown(&unix->sock, 0);
280 break;
281 }
282 lua_pushnumber(L, 1);
283 return 1;
284error:
285 luaL_argerror(L, 2, "invalid shutdown method");
286 return 0;
287}
288
289/*-------------------------------------------------------------------------*\
290* Just call tm methods
291\*-------------------------------------------------------------------------*/
292static int meth_settimeout(lua_State *L) {
293 p_unix unix = (p_unix) aux_checkgroup(L, "unix{any}", 1);
294 return tm_meth_settimeout(L, &unix->tm);
295}
296
297/*=========================================================================*\
298* Library functions
299\*=========================================================================*/
300/*-------------------------------------------------------------------------*\
301* Creates a master unix object
302\*-------------------------------------------------------------------------*/
303static int global_create(lua_State *L) {
304 t_sock sock;
305 const char *err = sock_create(&sock, AF_UNIX, SOCK_STREAM, 0);
306 /* try to allocate a system socket */
307 if (!err) {
308 /* allocate unix object */
309 p_unix unix = (p_unix) lua_newuserdata(L, sizeof(t_unix));
310 /* set its type as master object */
311 aux_setclass(L, "unix{master}", -1);
312 /* initialize remaining structure fields */
313 sock_setnonblocking(&sock);
314 unix->sock = sock;
315 io_init(&unix->io, (p_send) sock_send, (p_recv) sock_recv, &unix->sock);
316 tm_init(&unix->tm, -1, -1);
317 buf_init(&unix->buf, &unix->io, &unix->tm);
318 return 1;
319 } else {
320 lua_pushnil(L);
321 lua_pushstring(L, err);
322 return 2;
323 }
324}
diff --git a/src/unix.h b/src/unix.h
new file mode 100644
index 0000000..7b2a5c5
--- /dev/null
+++ b/src/unix.h
@@ -0,0 +1,28 @@
1#ifndef UNIX_H
2#define UNIX_H
3/*=========================================================================*\
4* Unix domain object
5* LuaSocket toolkit
6*
7* This module is just an example of how to extend LuaSocket with a new
8* domain.
9*
10* RCS ID: $Id$
11\*=========================================================================*/
12#include <lua.h>
13
14#include "buffer.h"
15#include "timeout.h"
16#include "socket.h"
17
18typedef struct t_unix_ {
19 t_sock sock;
20 t_io io;
21 t_buf buf;
22 t_tm tm;
23} t_unix;
24typedef t_unix *p_unix;
25
26int unix_open(lua_State *L);
27
28#endif /* UNIX_H */