2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Volker Lendecke 2006
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "utils/net.h"
24 #include "lua-5.1.4/src/lualib.h"
25 #include "lua-5.1.4/src/lauxlib.h"
27 #define SOCK_METATABLE "cade1208-9029-4d76-8748-426dfc1436f7"
29 struct sock_userdata
{
33 static int sock_userdata_gc(lua_State
*L
)
35 struct sock_userdata
*p
= (struct sock_userdata
*)
36 luaL_checkudata(L
, 1, SOCK_METATABLE
);
41 static int sock_userdata_tostring(lua_State
*L
)
43 struct sock_userdata
*p
= (struct sock_userdata
*)
44 luaL_checkudata(L
, 1, SOCK_METATABLE
);
46 lua_pushfstring(L
, "socket: %d", p
->fd
);
50 static int sock_userdata_connect(lua_State
*L
)
52 struct sock_userdata
*p
= (struct sock_userdata
*)
53 luaL_checkudata(L
, 1, SOCK_METATABLE
);
56 struct sockaddr_in addr
;
59 if (!lua_isstring(L
, 2)) {
60 luaL_error(L
, "connect: Expected IP-Address");
62 hostname
= lua_tostring(L
, 2);
64 if (!lua_isnumber(L
, 3)) {
65 luaL_error(L
, "connect: Expected port");
67 port
= lua_tointeger(L
, 3);
69 if (lua_gettop(L
) == 4) {
71 * Here we expect an event context in the last argument to
72 * make connect() asynchronous.
76 addr
.sin_family
= AF_INET
;
77 inet_aton(hostname
, &addr
.sin_addr
);
78 addr
.sin_port
= htons(port
);
80 res
= connect(p
->fd
, (struct sockaddr
*)&addr
, sizeof(addr
));
84 lua_pushfstring(L
, "connect failed: %s", strerror(err
));
88 lua_pushboolean(L
, 1);
92 static const struct luaL_Reg sock_methods
[] = {
93 {"__gc", sock_userdata_gc
},
94 {"__tostring", sock_userdata_tostring
},
95 {"connect", sock_userdata_connect
},
102 } socket_domains
[] = {
103 {"PF_UNIX", PF_UNIX
},
104 {"PF_INET", PF_INET
},
108 static const struct {
112 {"SOCK_STREAM", SOCK_STREAM
},
113 {"SOCK_DGRAM", SOCK_DGRAM
},
117 static int sock_userdata_new(lua_State
*L
)
119 struct sock_userdata
*result
;
120 const char *domain_str
= luaL_checkstring(L
, 1);
121 const char *type_str
= luaL_checkstring(L
, 2);
125 while (socket_domains
[i
].name
!= NULL
) {
126 if (strcmp(domain_str
, socket_domains
[i
].name
) == 0) {
131 if (socket_domains
[i
].name
== NULL
) {
132 return luaL_error(L
, "socket domain %s unknown", domain_str
);
134 domain
= socket_domains
[i
].domain
;
137 while (socket_types
[i
].name
!= NULL
) {
138 if (strcmp(type_str
, socket_types
[i
].name
) == 0) {
143 if (socket_types
[i
].name
== NULL
) {
144 return luaL_error(L
, "socket type %s unknown", type_str
);
146 type
= socket_types
[i
].type
;
148 result
= (struct sock_userdata
*)lua_newuserdata(L
, sizeof(*result
));
149 ZERO_STRUCTP(result
);
151 result
->fd
= socket(domain
, type
, 0);
152 if (result
->fd
== -1) {
155 lua_pushfstring(L
, "socket() failed: %s", strerror(errno
));
156 lua_pushinteger(L
, err
);
160 luaL_getmetatable(L
, SOCK_METATABLE
);
161 lua_setmetatable(L
, -2);
165 static const struct luaL_Reg sock_funcs
[] = {
166 {"new", sock_userdata_new
},
170 static int sock_lua_init(lua_State
*L
, const char *libname
) {
171 luaL_newmetatable(L
, SOCK_METATABLE
);
173 lua_pushvalue(L
, -1);
174 lua_setfield(L
, -2, "__index");
176 luaL_register(L
, NULL
, sock_methods
);
177 luaL_register(L
, libname
, sock_funcs
);
181 #define EVT_METATABLE "c42e0642-b24a-40f0-8483-d8eb4aee9ea3"
184 * The userdata we allocate from lua when a new event context is created
186 struct evt_userdata
{
187 struct event_context
*ev
;
190 static bool evt_is_main_thread(lua_State
*L
) {
193 ret
= lua_pushthread(L
);
199 * Per event we allocate a struct thread_reference to keep the coroutine from
200 * being garbage-collected. This is also the hook to find the right thread to
204 struct thread_reference
{
207 * Reference to the Thread (i.e. lua_State) this event is hanging on
212 static int thread_reference_destructor(struct thread_reference
*ref
)
214 luaL_unref(ref
->L
, LUA_REGISTRYINDEX
, ref
->thread_ref
);
218 static struct thread_reference
*evt_reference_thread(TALLOC_CTX
*mem_ctx
,
221 struct thread_reference
*result
;
223 result
= talloc(mem_ctx
, struct thread_reference
);
224 if (result
== NULL
) {
229 result
->thread_ref
= luaL_ref(L
, LUA_REGISTRYINDEX
);
231 talloc_set_destructor(result
, thread_reference_destructor
);
236 static int evt_userdata_gc(lua_State
*L
)
238 struct evt_userdata
*p
= (struct evt_userdata
*)
239 luaL_checkudata(L
, 1, EVT_METATABLE
);
244 static int evt_userdata_tostring(lua_State
*L
) {
245 lua_pushstring(L
, "event context");
249 static void evt_userdata_sleep_done(struct event_context
*event_ctx
,
250 struct timed_event
*te
,
254 struct thread_reference
*ref
= talloc_get_type_abort(
255 priv
, struct thread_reference
);
256 lua_resume(ref
->L
, 0);
260 static int evt_userdata_sleep(lua_State
*L
)
262 struct evt_userdata
*p
= (struct evt_userdata
*)
263 luaL_checkudata(L
, 1, EVT_METATABLE
);
264 lua_Integer usecs
= luaL_checkint(L
, 2);
265 struct thread_reference
*ref
;
266 struct timed_event
*te
;
268 if (evt_is_main_thread(L
)) {
270 * Block in the main thread
272 smb_msleep(usecs
/1000);
276 ref
= evt_reference_thread(p
->ev
, L
);
278 return luaL_error(L
, "evt_reference_thread failed\n");
281 te
= event_add_timed(p
->ev
, ref
, timeval_current_ofs(0, usecs
),
282 evt_userdata_sleep_done
,
287 return luaL_error(L
, "event_add_timed failed");
290 return lua_yield(L
, 0);
293 static int evt_userdata_once(lua_State
*L
)
295 struct evt_userdata
*p
= (struct evt_userdata
*)
296 luaL_checkudata(L
, 1, EVT_METATABLE
);
298 if (!evt_is_main_thread(L
)) {
299 return luaL_error(L
, "event_once called from non-base thread");
302 lua_pushinteger(L
, event_loop_once(p
->ev
));
306 static const struct luaL_Reg evt_methods
[] = {
307 {"__gc", evt_userdata_gc
},
308 {"__tostring", evt_userdata_tostring
},
309 {"sleep", evt_userdata_sleep
},
310 {"once", evt_userdata_once
},
314 static int evt_userdata_new(lua_State
*L
) {
315 struct evt_userdata
*result
;
317 result
= (struct evt_userdata
*)lua_newuserdata(L
, sizeof(*result
));
318 ZERO_STRUCTP(result
);
320 result
->ev
= event_context_init(NULL
);
321 if (result
->ev
== NULL
) {
322 return luaL_error(L
, "event_context_init failed");
325 luaL_getmetatable(L
, EVT_METATABLE
);
326 lua_setmetatable(L
, -2);
330 static const struct luaL_Reg evt_funcs
[] = {
331 {"new", evt_userdata_new
},
335 static int evt_lua_init(lua_State
*L
, const char *libname
) {
336 luaL_newmetatable(L
, EVT_METATABLE
);
338 lua_pushvalue(L
, -1);
339 lua_setfield(L
, -2, "__index");
341 luaL_register(L
, NULL
, evt_methods
);
342 luaL_register(L
, libname
, evt_funcs
);
346 int net_lua(struct net_context
*c
, int argc
, const char **argv
)
352 d_fprintf(stderr
, "lua_newstate failed\n");
356 luaL_openlibs(state
);
357 evt_lua_init(state
, "event");
358 sock_lua_init(state
, "socket");
363 line
= smb_readline("lua> ", NULL
, NULL
);
368 if (line
[0] == ':') {
369 if (luaL_dofile(state
, &line
[1])) {
370 d_printf("luaL_dofile returned an error\n");
373 } else if (line
[0] != '\n') {
374 if (luaL_dostring(state
, line
) != 0) {
375 d_printf("luaL_dostring returned an error\n");