aura  0.1
 All Data Structures Functions Variables Modules Pages
bindings-lua.c
1 #define LUA_LIB
2 
3 #include <aura/aura.h>
4 #include <aura/private.h>
5 #include <search.h>
6 #include <lua.h>
7 #include <lauxlib.h>
8 
9 #define REF_NODE_CONTAINER (1<<0)
10 #define REF_STATUS_CB (1<<1)
11 #define REF_ETABLE_CB (1<<2)
12 #define REF_EVENT_CB (1<<3)
13 
14 //#define TRACE_BCALLS
15 
16 #ifdef TRACE_BCALLS
17 #define TRACE() slog(4, SLOG_DEBUG, "Bindings call: %s", __func__)
18 #else
19 #define TRACE()
20 #endif
21 
22 #define aura_check_args(L, need) aura_do_check_args(L, __FUNCTION__, need)
23 
24 #define laura_eventloop_type "laura_eventloop"
25 #define laura_node_type "laura_node"
26 
27 extern int lua_stackdump(lua_State *L);
28 
29 
30 #if LUA_VERSION_NUM < 502
31 #warning Building with lua-5.1-compat hacks
32 
33 
34 #define luaL_setmetatable(L, name) \
35  luaL_getmetatable(L, name); \
36  lua_setmetatable(L, -2)
37 
38 #define setfuncs(L, l) luaL_setfuncs(L, l, 0)
39 
40 static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
41  luaL_checkstack(L, nup+1, "too many upvalues");
42  for (; l->name != NULL; l++) { /* fill the table with given functions */
43  int i;
44  lua_pushstring(L, l->name);
45  for (i = 0; i < nup; i++) /* copy upvalues to the top */
46  lua_pushvalue(L, -(nup+1));
47  lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
48  lua_settable(L, -(nup + 3));
49  }
50  lua_pop(L, nup); /* remove upvalues */
51 }
52 
53 #define luaL_newlib(L, l) \
54  (lua_newtable((L)),luaL_setfuncs((L), (l), 0))
55 
56 #endif
57 
58 
59 /* Lightuserdata can't have an attached metatable so we have to resort to
60  using full userdata here.
61  Bindings take care to close nodes and destroy eventloops when
62  garbage-collecting
63 */
64 struct laura_node {
65  lua_State *L;
66  struct aura_node *node;
67  const char *current_call;
68  uint32_t refs;
69  int node_container; /* lua table representing this node */
70  int status_changed_ref;
71  int status_changed_arg_ref;
72  int inbound_event_ref;
73  int inbound_event_arg_ref;
74 };
75 
76 struct laura_eventloop
77 {
78  struct aura_eventloop *loop;
79 };
80 
81 static inline int check_node_and_push(lua_State *L, struct aura_node *node)
82 {
83  if (node) {
84  struct laura_node *bdata = lua_newuserdata(L, sizeof(*bdata));
85  if (!bdata)
86  return luaL_error(L, "Memory allocation error");
87  bzero(bdata, sizeof(*bdata));
88  bdata->L = L;
89  bdata->node = node;
90  aura_set_userdata(node, bdata);
91  luaL_setmetatable(L, laura_node_type);
92  } else {
93  lua_pushnil(L);
94  }
95  return 1;
96 }
97 
98 
99 #define PREPARE_ARG(n) \
100  const void *arg ## n ##_ptr; \
101  const int arg ## n ##_int; \
102  if (lua_gettop(L) > (1 + n)) { \
103  if (lua_isstring(L, (1 + n))) \
104  arg ## n ## _ptr = lua_tostring(L, (1 + n)); \
105  else if (lua_isnumber(L, (1 + n))) \
106  arg ## n ## _int = lua_tonumber(L, (1 + n)); \
107  } \
108  \
109 
110 #define ARG(n) (lua_isstring(L, 1 + n) ? arg ## n ## _ptr : arg ## n ## _int)
111 
112 
113 static int aura_typeerror (lua_State *L, int narg, const char *tname)
114 {
115  const char *msg = lua_pushfstring(L, "%s expected, got %s",
116  tname, luaL_typename(L, narg));
117  return luaL_argerror(L, narg, msg);
118 }
119 
120 static struct laura_node *lua_fetch_node(lua_State *L, int idx) {
121 
122  struct laura_node *lnode = NULL;
123 
124  if (lua_isuserdata(L, idx))
125  lnode = lua_touserdata(L, idx);
126  else if (lua_istable(L, idx)) {
127  lua_pushstring(L, "__node");
128  lua_gettable(L, idx);
129  lnode = lua_touserdata(L, -1);
130  }
131  lua_pop(L, 1);
132  return lnode;
133 }
134 
135 static void aura_do_check_args (lua_State *L, const char *func, int need)
136 {
137  int got = lua_gettop(L);
138  if (got < need) {
139  luaL_error(L, "%s expects %d args, %d given",
140  func, need, got);
141  }
142 }
143 
144 
145 static void lua_setfield_string(lua_State *L, const char *key, const char *value)
146 {
147  lua_pushstring(L, key);
148  lua_pushstring(L, value);
149  lua_settable(L, -3);
150 }
151 
152 static void lua_setfield_int(lua_State *L, const char *key, long value)
153 {
154  lua_pushstring(L, key);
155  lua_pushnumber(L, value);
156  lua_settable(L, -3);
157 }
158 
159 static void lua_setfield_bool(lua_State *L, const char *key, bool value)
160 {
161  lua_pushstring(L, key);
162  lua_pushboolean(L, value);
163  lua_settable(L, -3);
164 }
165 
166 static int lua_push_etable(lua_State *L, struct aura_export_table *tbl)
167 {
168  int i;
169  if (!tbl) {
170  lua_pushnil(L);
171  return 1;
172  }
173 
174  lua_newtable(L);
175  for (i=0; i<tbl->next; i++) {
176  struct aura_object *o = &tbl->objects[i];
177  lua_pushinteger(L, i);
178  lua_newtable(L);
179 
180  lua_setfield_string(L, "name", o->name);
181  lua_setfield_bool(L, "valid", o->valid);
182  lua_setfield_int(L, "id", o->id);
183  if (o->arg_fmt)
184  lua_setfield_string(L, "arg", o->arg_fmt);
185  if (o->ret_fmt)
186  lua_setfield_string(L, "ret", o->ret_fmt);
187  if (o->arg_pprinted)
188  lua_setfield_string(L, "arg_pprint", o->arg_pprinted);
189  if (o->arg_pprinted)
190  lua_setfield_string(L, "ret_pprint", o->arg_pprinted);
191 
192  lua_settable(L, -3);
193  }
194  return 1;
195 }
196 
197 static int buffer_to_lua(lua_State *L, struct aura_node *node, const struct aura_object *o, struct aura_buffer *buf)
198 {
199  const char *fmt = o->ret_fmt;
200  int nargs = 0;
201 
202  while (*fmt) {
203  double tmp;
204  switch (*fmt++) {
205  case URPC_U8:
206  tmp = aura_buffer_get_u8(buf);
207  lua_pushnumber(L, tmp);
208  break;
209  case URPC_S8:
210  tmp = aura_buffer_get_s8(buf);
211  lua_pushnumber(L, tmp);
212  break;
213  case URPC_U16:
214  tmp = aura_buffer_get_u16(buf);
215  lua_pushnumber(L, tmp);
216  break;
217  case URPC_S16:
218  tmp = aura_buffer_get_s16(buf);
219  lua_pushnumber(L, tmp);
220  break;
221  case URPC_U32:
222  tmp = aura_buffer_get_u32(buf);
223  lua_pushnumber(L, tmp);
224  break;
225  case URPC_S32:
226  tmp = aura_buffer_get_s32(buf);
227  lua_pushnumber(L, tmp);
228  break;
229  case URPC_U64:
230  tmp = aura_buffer_get_u64(buf);
231  lua_pushnumber(L, tmp);
232  break;
233  case URPC_S64:
234  tmp = aura_buffer_get_s64(buf);
235  lua_pushnumber(L, tmp);
236  break;
237  case URPC_BIN:
238  {
239  void *udata;
240  const void *srcdata;
241  int len = atoi(fmt);
242 
243  if (len == 0)
244  BUG(node, "Internal deserilizer bug processing: %s", fmt);
245  udata = lua_newuserdata(L, len);
246  if (!udata)
247  BUG(node, "Failed to allocate userdata");
248  srcdata = aura_buffer_get_bin(buf, len);
249  memcpy(udata, srcdata, len);
250  while (*fmt && (*fmt++ != '.'));
251  break;
252  }
253  default:
254  BUG(node, "Unexpected format token: %s", --fmt);
255  }
256  nargs++;
257  };
258 
259  return nargs;
260 }
261 
262 static struct aura_buffer *lua_to_buffer(lua_State *L, struct aura_node *node, int stackpos, struct aura_object *o)
263 {
264  int i;
265  struct aura_buffer *buf;
266  const char *fmt;
267 
268  fmt = o->arg_fmt;
269  if (lua_gettop(L) - stackpos + 1 != o->num_args) {
270  slog(0, SLOG_ERROR, "Invalid argument count for %s: %d / %d",
271  o->name, lua_gettop(L) - stackpos, o->num_args);
272  return NULL;
273  }
274 
275  buf = aura_buffer_request(node, o->arglen);
276  if (!buf) {
277  slog(0, SLOG_ERROR, "Epic fail during buffer allocation");
278  return NULL;
279  }
280 
281  /* Let's serialize the data, arguments are on the stack,
282  * Starting from #3.
283  */
284 
285  for (i=stackpos; i<=lua_gettop(L); i++) {
286  double tmp;
287 
288  switch (*fmt++) {
289  case URPC_U8:
290  tmp = lua_tonumber(L, i);
291  aura_buffer_put_u8(buf, tmp);
292  break;
293  case URPC_S8:
294  tmp = lua_tonumber(L, i);
295  aura_buffer_put_s8(buf, tmp);
296  break;
297  case URPC_U16:
298  tmp = lua_tonumber(L, i);
299  aura_buffer_put_u16(buf, (uint16_t) tmp);
300  break;
301  case URPC_S16:
302  tmp = lua_tonumber(L, i);
303  aura_buffer_put_s16(buf, tmp);
304  break;
305  case URPC_U32:
306  tmp = lua_tonumber(L, i);
307  aura_buffer_put_u32(buf, tmp);
308  break;
309  case URPC_S32:
310  tmp = lua_tonumber(L, i);
311  aura_buffer_put_s32(buf, tmp);
312  break;
313  case URPC_S64:
314  tmp = lua_tonumber(L, i);
315  aura_buffer_put_s64(buf, tmp);
316  break;
317  case URPC_U64:
318  tmp = lua_tonumber(L, i);
319  aura_buffer_put_u64(buf, tmp);
320  break;
321 
322  /* Binary is the tricky part. String or usata? */
323  case URPC_BIN:
324  {
325  const char *srcbuf = NULL;
326  int len = 0;
327  int blen;
328  if (lua_isstring(L, i)) {
329  srcbuf = lua_tostring(L, i);
330  len = strlen(srcbuf);
331  } else if (lua_isuserdata(L, i)) {
332  srcbuf = lua_touserdata(L, i);
333  }
334 
335  blen = atoi(fmt);
336 
337  if (blen == 0) {
338  slog(0, SLOG_ERROR, "Internal serilizer bug processing: %s", fmt);
339  goto err;
340  }
341 
342  if (!srcbuf) {
343  slog(0, SLOG_ERROR, "Internal bug fetching src pointer");
344  goto err;
345  }
346 
347  if (blen < len)
348  len = blen;
349 
350  aura_buffer_put_bin(buf, srcbuf, len);
351 
352  while (*fmt && (*fmt++ != '.'));
353 
354  break;
355  }
356  default:
357  BUG(node, "Unknown token: %c\n", *(--fmt));
358  break;
359  }
360  }
361 
362  return buf;
363 err:
364  aura_buffer_release(buf);
365  return NULL;
366 }
367 
368 static int l_open_node(lua_State *L)
369 {
370  struct aura_node *node;
371 
372  TRACE();
373  aura_check_args(L, 2);
374  node = aura_open(lua_tostring(L, 1), lua_tostring(L, 2));
375  if (!node)
376  return luaL_error(L, "Failed to open node");
377 
378  return check_node_and_push(L, node);
379 
380 }
381 
382 static int l_close_node(lua_State *L)
383 {
384  struct laura_node *lnode = lua_fetch_node(L, -1);
385  struct aura_node *node = lnode->node;
386 
387  TRACE();
388 
389  /* Handle weird cases when we've already cleaned up */
390  if (!node)
391  return 0;
392 
393  /* Clear up references we've set up so far*/
394  if (lnode->refs & REF_NODE_CONTAINER)
395  luaL_unref(L, LUA_REGISTRYINDEX, lnode->node_container);
396 
397  if (lnode->refs & REF_STATUS_CB) {
398  luaL_unref(L, LUA_REGISTRYINDEX, lnode->status_changed_ref);
399  luaL_unref(L, LUA_REGISTRYINDEX, lnode->status_changed_arg_ref);
400  }
401 
402 /*
403  if (lnode->refs & REF_ETABLE_CB) {
404  luaL_unref(L, LUA_REGISTRYINDEX, lnode->etable_changed_ref);
405  luaL_unref(L, LUA_REGISTRYINDEX, lnode->etable_changed_arg_ref);
406  }
407 */
408 
409  aura_close(node);
410  lnode->node = NULL;
411  return 0;
412 }
413 
414 static int l_node_gc(lua_State *L)
415 {
416  return l_close_node(L);
417 }
418 
419 static int laura_do_sync_call(lua_State *L){
420 
421  struct laura_node *lnode = lua_fetch_node(L, 1);
422  struct aura_buffer *buf, *retbuf;
423  struct aura_object *o;
424  int ret;
425  TRACE();
426 
427  o = aura_etable_find(lnode->node->tbl, lnode->current_call);
428  if (!o)
429  return luaL_error(L, "Attempt to call non-existend method");
430 
431  buf = lua_to_buffer(L, lnode->node, 2, o);
432  if (!buf)
433  return luaL_error(L, "Serializer failed!");
434 
435  ret = aura_core_call(lnode->node, o, &retbuf, buf);
436  if (ret != 0)
437  return luaL_error(L, "Call for %s failed", o->name);
438 
439  ret = buffer_to_lua(L, lnode->node, o, retbuf);
440  aura_buffer_release(retbuf);
441  return ret;
442 }
443 
444 
445 static void calldone_cb(struct aura_node *node, int status, struct aura_buffer *retbuf, void *arg)
446 {
447  struct laura_node *lnode;
448  lua_State *L;
449  const struct aura_object *o;
450 
451  lnode = aura_get_userdata(node);
452  L = lnode->L;
453  o = aura_get_current_object(lnode->node);
454  TRACE();
455 
456 
457  lua_rawgeti(L, LUA_REGISTRYINDEX, (long) arg); /* Fetch our callback params */
458  lua_pushnumber(L, 1);
459  lua_gettable(L, -2);
460 
461  lua_rawgeti(L, LUA_REGISTRYINDEX, lnode->node_container);
462 
463  lua_pushnumber(L, status);
464 
465  lua_pushnumber(L, 2);
466  lua_gettable(L, -5);
467 
468  buffer_to_lua(L, lnode->node, o, retbuf);
469 
470  lua_stackdump(L);
471 
472  lua_call(L, 3 + o->num_rets, 0); /* Fire the callback! */
473 
474  luaL_unref(L, LUA_REGISTRYINDEX, (long) arg); /* Remove the reference */
475 }
476 
477 static int laura_do_async_call(lua_State *L){
478  struct laura_node *lnode = NULL;
479  const char *name;
480  struct aura_buffer *buf;
481  struct aura_object *o;
482  int ret;
483  int callback_ref;
484 
485  TRACE();
486 
487  /* Sanity */
488  lnode=lua_fetch_node(L, 1);
489  if (!lnode) {
490  lua_stackdump(L);
491  return aura_typeerror(L, 1, "userdata (node)");
492  }
493 
494  if (!lua_isstring(L, 2)) {
495  lua_stackdump(L);
496  return aura_typeerror(L, 2, "string (object name)");
497  }
498 
499  if (!lua_isfunction(L, 3)) {
500  lua_stackdump(L);
501  return aura_typeerror(L, 3, "function (callback)");
502  }
503 
504  name = lua_tostring(L, 2);
505 
506  o = aura_etable_find(lnode->node->tbl, name);
507  if (!o)
508  return luaL_error(L, "Attempt to call non-existend method");
509 
510  if (!object_is_method(o)) {
511  lua_stackdump(L);
512  return luaL_error(L, "Attempt to call an event");
513  }
514 
515 
516  /* Now we're sane! */
517 
518  buf = lua_to_buffer(L, lnode->node, 5, o);
519  if (!buf)
520  luaL_error(L, "Serializer failed!");
521 
522  /* Let's create a table to store our callback and arg */
523  lua_newtable(L);
524 
525  /* Push the callback function there */
526  lua_pushnumber(L, 1);
527  lua_pushvalue(L, 3);
528  lua_settable(L, -3);
529 
530  /* And the user argument */
531  lua_pushnumber(L, 2);
532  lua_pushvalue(L, 4);
533  lua_settable(L, -3);
534 
535  /* And fetch the reference to out table that we'll use in callback */
536  callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
537  slog(4, SLOG_DEBUG, "Callback tbl reference: %d", callback_ref);
538 
539  ret = aura_core_start_call(lnode->node, o, calldone_cb, (void *) (long) callback_ref, buf);
540  if (ret != 0) {
541  aura_buffer_release(buf);
542  return luaL_error(L, "Async call for %s failed: %d:%s", o->name, ret, strerror(ret));
543  }
544 
545  return 0;
546 }
547 
548 static int l_node_index(lua_State *L)
549 {
550  struct laura_node *lnode = lua_touserdata(L, 1);
551  const char *name = lua_tostring(L, -1);
552  struct aura_object *o;
553 
554  TRACE();
555  /* FixMe: Can this get gc-d by the time we actually use it? */
556  lnode->current_call = name;
557 
558  o = aura_etable_find(lnode->node->tbl, lnode->current_call);
559 
560  if (strcmp("__", name)==0)
561  lua_pushcfunction(L, laura_do_async_call);
562  else if (object_is_method(o))
563  lua_pushcfunction(L, laura_do_sync_call);
564  else
565  lua_pushnil(L);
566  return 1;
567 }
568 
569 
570 
571 static int l_etable_get(lua_State *L)
572 {
573  struct laura_node *lnode = NULL;
574  struct aura_node *node = NULL;
575 
576  TRACE();
577  aura_check_args(L, 1);
578 
579  if (lua_islightuserdata(L, 1)) {
580  node = lua_touserdata(L, 1);
581  } else {
582  lnode = lua_fetch_node(L, 1);
583  }
584  if (lnode)
585  node = lnode->node;
586 
587  if (!node)
588  return luaL_error(L, "Failed to fetch node");
589 
590  return lua_push_etable(L, node->tbl);
591 }
592 
593 
594 static int l_etable_create (lua_State *L)
595 {
596  struct aura_node *node;
597  int count = 0;
598  struct aura_export_table *tbl;
599 
600  TRACE();
601  aura_check_args(L, 2);
602  if (!lua_islightuserdata(L, 1)) {
603  aura_typeerror(L, 1, "ludata");
604  }
605  if (!lua_isnumber(L, 2)) {
606  aura_typeerror(L, 1, "number");
607  }
608 
609  node = lua_touserdata(L, 1);
610  count = lua_tonumber(L, 2);
611  tbl = aura_etable_create(node, count);
612  if (!tbl)
613  return luaL_error(L, "error creating etable for %d elements", count);
614 
615  lua_pushlightuserdata(L, tbl);
616  return 1;
617 }
618 
619 static int l_etable_add (lua_State *L)
620 {
621  struct aura_export_table *tbl;
622  const char *name, *arg, *ret;
623 
624  TRACE();
625  aura_check_args(L, 4);
626 
627  if (!lua_islightuserdata(L, 1)) {
628  aura_typeerror(L, 1, "ludata");
629  }
630  if (!lua_isstring(L, 2)) {
631  aura_typeerror(L, 1, "string");
632  }
633  if (!lua_isstring(L, 3)) {
634  aura_typeerror(L, 1, "string");
635  }
636  if (!lua_isstring(L, 4)) {
637  aura_typeerror(L, 1, "string");
638  }
639 
640  tbl = lua_touserdata(L, 1);
641  name = lua_tostring(L, 2);
642  arg = lua_tostring(L, 3);
643  ret = lua_tostring(L, 4);
644 
645  aura_etable_add(tbl, name, arg, ret);
646  return 0;
647 }
648 
649 static int l_etable_activate(lua_State *L)
650 {
651  struct aura_export_table *tbl;
652 
653  TRACE();
654  aura_check_args(L, 1);
655 
656  if (!lua_islightuserdata(L, 1)) {
657  aura_typeerror(L, 1, "ludata");
658  }
659 
660  tbl = lua_touserdata(L, 1);
661  aura_etable_activate(tbl);
662  return 0;
663 }
664 
665 
666 static int l_eventloop_create(lua_State *L)
667 {
668  struct laura_node *lnode;
669  struct laura_eventloop *lloop;
670 
671  TRACE();
672 
673  lnode = lua_fetch_node(L, 1);
674  if (!lnode)
675  return luaL_error(L, "Failed to fetch node");
676 
677  lloop = lua_newuserdata(L, sizeof(*lloop));
678  if (!lloop)
679  return luaL_error(L, "Userdata allocation failed");
680  luaL_setmetatable(L, laura_eventloop_type);
681 
682  lloop->loop = aura_eventloop_create(lnode->node);
683  if (!lloop->loop)
684  lua_pushnil(L);
685 
686  return 1;
687 }
688 
689 static int l_eventloop_add(lua_State *L)
690 {
691  struct laura_node *lnode;
692  struct laura_eventloop *lloop;
693 
694  TRACE();
695  aura_check_args(L, 2);
696 
697  if (!lua_isuserdata(L, 1)) {
698  aura_typeerror(L, 1, "ludata (eventloop)");
699  }
700  lnode = lua_fetch_node(L, 2);
701 
702  lloop = lua_touserdata(L, 1);
703  if (!lloop || !lnode)
704  return luaL_error(L, "Failed to retrive arguments");
705 
706  aura_eventloop_add(lloop->loop, lnode->node);
707 
708  return 0;
709 }
710 
711 static int l_eventloop_del(lua_State *L)
712 {
713  struct laura_node *lnode;
714 
715  TRACE();
716  aura_check_args(L, 1);
717 
718  lnode = lua_fetch_node(L, 1);
719 
720  if (!lnode)
721  return luaL_error(L, "Failed to retrive arguments");
722 
723  aura_eventloop_del(lnode->node);
724  return 0;
725 }
726 
727 static int l_eventloop_destroy(lua_State *L)
728 {
729  struct laura_eventloop *lloop;
730 
731  TRACE();
732  aura_check_args(L, 1);
733 
734  if (!lua_isuserdata(L, 1)) {
735  aura_typeerror(L, 2, "ludata (eventloop)");
736  }
737 
738  lloop = lua_touserdata(L, 1);
739  if (!lloop)
740  return luaL_error(L, "Failed to retrive arguments");
741 
742  if (!lloop->loop)
743  return 0;
744 
745  aura_eventloop_destroy(lloop->loop);
746  lloop->loop = NULL;
747 
748  return 0;
749 }
750 
751 static int l_slog_init(lua_State *L)
752 {
753  const char *fname;
754  int level;
755 
756  TRACE();
757  aura_check_args(L, 2);
758  fname = lua_tostring(L, 1);
759  level = lua_tonumber(L, 2);
760  slog_init(fname, level);
761  return 0;
762 }
763 
764 static int l_wait_status(lua_State *L)
765 {
766  struct laura_node *lnode;
767  TRACE();
768  aura_check_args(L, 2);
769  lnode = lua_fetch_node(L, 1);
770  aura_wait_status(lnode->node, lua_tonumber(L,2));
771  return 0;
772 }
773 
774 static void event_cb(struct aura_node *node, struct aura_buffer *buf, void *arg)
775 {
776  struct laura_node *lnode = arg;
777  lua_State *L = lnode->L;
778  const struct aura_object *o = aura_get_current_object(node);
779  int nargs;
780 
781  TRACE();
782 
783  lua_rawgeti(L, LUA_REGISTRYINDEX, lnode->node_container);
784  lua_pushstring(L, o->name);
785  lua_gettable(L, -2);
786 
787  if (!lua_isfunction(L, -1)) {
788  slog(0, SLOG_WARN, "Dropping unhandled event: %s", o->name);
789  return;
790  }
791 
792  lua_rawgeti(L, LUA_REGISTRYINDEX, lnode->node_container);
793 
794  nargs = buffer_to_lua(L, lnode->node, o, buf);
795  lua_call(L, nargs + 1, 0);
796 }
797 
798 static int l_set_node_container(lua_State *L)
799 {
800  struct laura_node *lnode;
801 
802  TRACE();
803  aura_check_args(L, 2);
804  if (!lua_isuserdata(L, 1)) {
805  aura_typeerror(L, 1, "udata");
806  }
807 
808  if (!lua_istable(L, 2)) {
809  aura_typeerror(L, 2, "table");
810  }
811 
812  lnode = lua_touserdata(L, 1);
813  lnode->node_container = luaL_ref(L, LUA_REGISTRYINDEX);
814  lnode->refs |= REF_NODE_CONTAINER;
815 
816  aura_unhandled_evt_cb(lnode->node, event_cb, lnode);
817 
818  return 0;
819 }
820 
821 static int l_status(lua_State *L)
822 {
823  struct laura_node *lnode;
824 
825  TRACE();
826  aura_check_args(L, 1);
827  lnode = lua_fetch_node(L, 1);
828  if (!lnode)
829  return luaL_error(L, "Failed to retrieve lnode");
830  lua_pushnumber(L, aura_get_status(lnode->node));
831  return 1;
832 }
833 
834 
835 static void status_cb(struct aura_node *node, int newstatus, void *arg)
836 {
837  struct laura_node *lnode = arg;
838  lua_State *L = lnode->L;
839  lua_rawgeti(L, LUA_REGISTRYINDEX, lnode->status_changed_ref);
840  lua_rawgeti(L, LUA_REGISTRYINDEX, lnode->node_container);
841  lua_pushnumber(L, newstatus);
842  lua_rawgeti(L, LUA_REGISTRYINDEX, lnode->status_changed_arg_ref);
843  lua_call(L, 3, 0);
844 }
845 
846 static int l_set_status_change_cb(lua_State *L)
847 {
848  struct laura_node *lnode;
849  struct aura_node *node;
850 
851  TRACE();
852  aura_check_args(L, 3);
853 
854  lnode = lua_fetch_node(L, 1);
855  if (!lnode)
856  return luaL_error(L, "Failed to retrieve node");
857 
858  node = lnode->node;
859 
860  if (!lua_isfunction(L, 2)) {
861  aura_typeerror(L, 2, "function");
862  }
863 
864  if (lnode->refs & REF_STATUS_CB)
865  {
866  luaL_unref(L, LUA_REGISTRYINDEX, lnode->status_changed_arg_ref);
867  luaL_unref(L, LUA_REGISTRYINDEX, lnode->status_changed_ref);
868  }
869 
870  lnode->refs |= REF_STATUS_CB;
871  lnode->status_changed_arg_ref = luaL_ref(L, LUA_REGISTRYINDEX);
872  lnode->status_changed_ref = luaL_ref(L, LUA_REGISTRYINDEX);
873  aura_status_changed_cb(node, status_cb, lnode);
874 
875  return 0;
876 }
877 
878 static int l_handle_events(lua_State *L)
879 {
880  struct laura_eventloop *lloop;
881  int timeout = -1;
882 
883  TRACE();
884  aura_check_args(L, 1);
885 
886  if (!lua_isuserdata(L, 1)) {
887  aura_typeerror(L, 1, "ludata");
888  }
889 
890  lloop = lua_touserdata(L, 1);
891 
892  if (lua_gettop(L) == 2) {
893  timeout = lua_tonumber(L, 2);
894  aura_handle_events_timeout(lloop->loop, timeout);
895  } else {
896  aura_handle_events_forever(lloop->loop);
897  }
898 
899  return 0;
900 }
901 
902 static const luaL_Reg libfuncs[] = {
903  { "slog_init", l_slog_init },
904  { "etable_create", l_etable_create },
905  { "etable_get", l_etable_get },
906  { "etable_add", l_etable_add },
907  { "etable_activate", l_etable_activate },
908  { "core_open", l_open_node },
909  { "core_close", l_close_node },
910  { "wait_status", l_wait_status },
911 
912  { "status", l_status },
913  { "status_cb", l_set_status_change_cb },
914 
915  { "set_node_containing_table", l_set_node_container },
916  { "eventloop_create", l_eventloop_create },
917  { "eventloop_add", l_eventloop_add },
918  { "eventloop_del", l_eventloop_del },
919  { "eventloop_destroy", l_eventloop_destroy },
920 
921  { "handle_events", l_handle_events },
922 
923 /*
924  { "status_cb", l_set_status_change_cb },
925  { "event_cb", l_set_event_cb },
926 
927 */
928  {NULL, NULL}
929 };
930 
931 
932 static const struct luaL_Reg node_meta[] = {
933  {"__gc", l_node_gc },
934  {"__index", l_node_index },
935  {NULL, NULL }
936 };
937 
938 
939 static int l_loop_gc(lua_State *L)
940 {
941  slog(0, SLOG_WARN, "GC on a evtloop: This shouldn't normally happen, but we'll close the node anyway");
942  return l_eventloop_destroy(L);
943 }
944 
945 
946 static const struct luaL_Reg loop_meta[] = {
947  {"__gc", l_loop_gc },
948  {NULL, NULL }
949 };
950 
951 
952 LUALIB_API int luaopen_auracore (lua_State *L)
953 {
954  luaL_newmetatable(L, laura_node_type);
955  luaL_setfuncs(L, node_meta, 0);
956 
957  luaL_newmetatable(L, laura_eventloop_type);
958  luaL_setfuncs(L, loop_meta, 0);
959 
960  luaL_newlib(L, libfuncs);
961  lua_setfield_int(L, "STATUS_OFFLINE", AURA_STATUS_OFFLINE);
962  lua_setfield_int(L, "STATUS_ONLINE", AURA_STATUS_ONLINE);
963 
964  lua_setfield_int(L, "CALL_COMPLETED", AURA_CALL_COMPLETED);
965  lua_setfield_int(L, "CALL_TIMEOUT", AURA_CALL_TIMEOUT);
966  lua_setfield_int(L, "CALL_TRANSPORT_FAIL", AURA_CALL_TRANSPORT_FAIL);
967 
968  /* Return One result */
969  return 1;
970 }
void aura_buffer_put_s16(struct aura_buffer *buf, int16_t value)
Put a signed 16 bit integer to aura buffer.
struct aura_buffer * aura_buffer_request(struct aura_node *nd, int size)
Definition: buffer.c:40
void aura_buffer_put_s32(struct aura_buffer *buf, int32_t value)
Put a signed 32 bit integer to aura buffer.
int aura_core_call(struct aura_node *node, struct aura_object *o, struct aura_buffer **retbuf, struct aura_buffer *argbuf)
Definition: aura.c:412
#define aura_eventloop_create(...)
Definition: aura.h:759
void aura_handle_events_forever(struct aura_eventloop *loop)
Definition: eventloop.c:187
int64_t aura_buffer_get_s64(struct aura_buffer *buf)
Get a signed 64 bit integer from aura buffer.
void aura_buffer_put_u16(struct aura_buffer *buf, uint16_t value)
Put an unsigned 16 bit integer to aura buffer.
void aura_buffer_put_bin(struct aura_buffer *buf, const void *data, int len)
Copy data of len bytes to aura buffer from a buffer pointed by data.
Definition: retparse.c:71
void aura_eventloop_add(struct aura_eventloop *loop, struct aura_node *node)
Definition: eventloop.c:38
void aura_wait_status(struct aura_node *node, int status)
Definition: aura.c:607
int32_t aura_buffer_get_s32(struct aura_buffer *buf)
Get a signed 32 bit integer from aura buffer.
void aura_handle_events_timeout(struct aura_eventloop *loop, int timeout_ms)
Definition: eventloop.c:217
int8_t aura_buffer_get_s8(struct aura_buffer *buf)
Get a signed 8 bit integer from aura buffer.
void aura_buffer_put_s8(struct aura_buffer *buf, int8_t value)
Put a signed 8 bit integer to aura buffer.
void aura_buffer_put_u32(struct aura_buffer *buf, uint32_t value)
Put an unsigned 32 bit integer to aura buffer.
void aura_buffer_put_u8(struct aura_buffer *buf, uint8_t value)
Put an unsigned 8 bit integer to aura buffer.
static int aura_get_status(struct aura_node *node)
Definition: inlines.h:41
static void aura_set_userdata(struct aura_node *node, void *udata)
Definition: inlines.h:17
uint32_t aura_buffer_get_u32(struct aura_buffer *buf)
Get an unsigned 32 bit integer from aura buffer.
uint16_t aura_buffer_get_u16(struct aura_buffer *buf)
Get an unsigned 16 bit integer from aura buffer.
void aura_buffer_put_u64(struct aura_buffer *buf, uint64_t value)
Put an unsigned 64 bit integer to aura buffer.
void aura_eventloop_destroy(struct aura_eventloop *loop)
Definition: eventloop.c:166
uint8_t aura_buffer_get_u8(struct aura_buffer *buf)
Get an unsigned 8 bit integer from aura buffer.
struct aura_node * aura_open(const char *name, const char *opts)
Definition: aura.c:34
const void * aura_buffer_get_bin(struct aura_buffer *buf, int len)
Get a pointer to the binary data block within buffer and advance internal pointer by len bytes...
Definition: retparse.c:60
void aura_buffer_put_s64(struct aura_buffer *buf, int64_t value)
Put a signed 64 bit integer to aura buffer.
void aura_eventloop_del(struct aura_node *node)
Definition: eventloop.c:69
uint64_t aura_buffer_get_u64(struct aura_buffer *buf)
Get an unsigned 64 bit integer from aura buffer.
int aura_core_start_call(struct aura_node *node, struct aura_object *o, void(*calldonecb)(struct aura_node *dev, int status, struct aura_buffer *ret, void *arg), void *arg, struct aura_buffer *buf)
Definition: aura.c:361
const struct aura_object * aura_get_current_object(struct aura_node *node)
Obtain the pointer to the current aura_object.
Definition: aura.c:226
void aura_status_changed_cb(struct aura_node *node, void(*cb)(struct aura_node *node, int newstatus, void *arg), void *arg)
Definition: aura.c:258
static void * aura_get_userdata(struct aura_node *node)
Definition: inlines.h:28
void aura_unhandled_evt_cb(struct aura_node *node, void(*cb)(struct aura_node *node, struct aura_buffer *buf, void *arg), void *arg)
Definition: aura.c:314
int16_t aura_buffer_get_s16(struct aura_buffer *buf)
Get a signed 16 bit integer from aura buffer.
void aura_buffer_release(struct aura_buffer *buf)
Definition: buffer.c:80
void aura_close(struct aura_node *node)
Definition: aura.c:102