rough framework
[lemu] / lua_interface.c
1 #include <stdlib.h>
2
3 #include <lua.h>
4 #include <lualib.h>
5 #include <lauxlib.h>
6
7 #include "connections.h"
8 #include "lua_interface.h"
9 #include "notify.h"
10
11 #define CONNECTION_META_TABLE "MetaConnection"
12 #define CONNECTION_TABLE "Connection"
13 #define CONNECTION_TABLE_UD_FIELD "core_"
14
15 /**
16 * HARD: shared common server state, updatable commands table
17 * Interim: independent states, any global changes queued to all workers
18 * Idea: can a proxy table be crafted to access a shared table-like c entity
19 * Idea: eventual-consistency between lua states (somehow)
20 *
21 */
22
23
24 /**
25 * Create a new referenced coroutine on lua state.
26 * release with:
27 * luaL_unref(L, LUA_REGISTRYINDEX, refkey);
28 */
29 int
30 lua_new_coroutine_ref(lua_State *L, lua_State **coL, int *refkey)
31 {
32 *refkey = LUA_NOREF;
33
34 /* Create new coroutine on top of stack. */
35 *coL = lua_newthread(L);
36 if (!*coL) {
37 NOTIFY_ERROR("%s:%s", "lua_newthread", "failed");
38 return -1;
39 }
40
41 /* Store coroutine reference in state registry. */
42 *refkey = luaL_ref(L, LUA_REGISTRYINDEX);
43
44 return 0;
45 }
46
47
48 /**
49 * Connection Object
50 * is a table with metatable for methods and userdata field
51 *
52 */
53
54
55 /**
56 * Add a connection reference to lua stack
57 *
58 */
59 int
60 lemu_connection_push(lua_State *L, struct connection *c)
61 {
62 connection_inc_ref(c);
63
64 lua_newtable(L); // new connection table
65 luaL_getmetatable(L, CONNECTION_META_TABLE); // locate meta
66 lua_setmetatable(L, -2); // assign meta to connection table
67
68 /* keeping a pointer in userdata, rather than light userdata, to get metatable support */
69 struct connection **cud = lua_newuserdatauv(L, sizeof c, 0);
70 *cud = c;
71 luaL_getmetatable(L, CONNECTION_META_TABLE);
72 lua_setmetatable(L, -2);
73
74 lua_setfield(L, -2, CONNECTION_TABLE_UD_FIELD);
75 return 1;
76 }
77
78
79 /**
80 * I guess this one would take a stack value to find a connection
81 */
82 static int
83 lemu_connection_create_(lua_State *L)
84 {
85 struct connection *c;
86
87 luaL_checktype(L, 1, LUA_TSTRING);
88 // c = connection_lookup(lua_tostring(L, 1));
89 c = NULL;
90
91 return lemu_connection_push(L, c);
92 }
93
94
95 /**
96 * this will only get called on userdata (how does that happen??)
97 */
98 static int
99 lemu_connection_destroy_(lua_State *L)
100 {
101 struct connection **cud = luaL_checkudata(L, 1, CONNECTION_META_TABLE);
102 struct connection *c = *cud;
103
104 connection_free(c);
105
106 return 0;
107 }
108
109
110 /**
111 * Send a fixed string to a connection.
112 */
113 static int
114 lemu_connection_send_(lua_State *L)
115 {
116 if (lua_gettop(L) < 2) {
117 lua_pushliteral(L, "too few arguments");
118 lua_error(L);
119 }
120 luaL_checktype(L, 1, LUA_TTABLE);
121 lua_getfield(L, 1, CONNECTION_TABLE_UD_FIELD);
122 luaL_checktype(L, -1, LUA_TUSERDATA);
123 struct connection **cud = lua_touserdata(L, -1);
124 struct connection *c = *cud;
125
126 luaL_checktype(L, 2, LUA_TSTRING);
127 const char *message = lua_tostring(L, 2);
128
129 connection_printf(c, "%s\n", message);
130
131 return 0;
132 }
133
134
135 static const luaL_Reg Connection_funcs[] = {
136 { "create", lemu_connection_create_ },
137 { NULL, NULL }
138 };
139
140
141 static const luaL_Reg Connection_methods[] = {
142 { "__gc", lemu_connection_destroy_ },
143 { "send", lemu_connection_send_ },
144 { NULL, NULL }
145 };
146
147
148 /**
149 * Initialize the Connection object prototypes
150 */
151 int
152 lemu_connection_luainit(lua_State *L)
153 {
154 luaL_newmetatable(L, CONNECTION_META_TABLE); // new userdata metatable, __name = CONNECTION_META_TABLE
155 lua_pushstring(L, "__index");
156 lua_pushvalue(L, -2); // meta table
157 lua_settable(L, -3); // becomes its own index table
158 luaL_setfuncs(L, Connection_methods, 0); // add methods to metatable
159 lua_pop(L, 1);
160
161 luaL_newlibtable(L, Connection_funcs); // new table with functions
162 luaL_setfuncs(L, Connection_funcs, 0);
163 lua_setglobal(L, CONNECTION_TABLE); // make it available
164
165 return 0;
166 }
167
168 // int luaopen_lemu(lua_State *L);