lua-multicast.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #define LUA_LIB
  2. #include "skynet.h"
  3. #include <lua.h>
  4. #include <lauxlib.h>
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include "atomic.h"
  8. struct mc_package {
  9. ATOM_INT reference;
  10. uint32_t size;
  11. void *data;
  12. };
  13. static int
  14. pack(lua_State *L, void *data, size_t size) {
  15. struct mc_package * pack = skynet_malloc(sizeof(struct mc_package));
  16. ATOM_INIT(&pack->reference, 0);
  17. pack->size = (uint32_t)size;
  18. pack->data = data;
  19. struct mc_package ** ret = skynet_malloc(sizeof(*ret));
  20. *ret = pack;
  21. lua_pushlightuserdata(L, ret);
  22. lua_pushinteger(L, sizeof(ret));
  23. return 2;
  24. }
  25. /*
  26. lightuserdata
  27. integer size
  28. return lightuserdata, sizeof(struct mc_package *)
  29. */
  30. static int
  31. mc_packlocal(lua_State *L) {
  32. void * data = lua_touserdata(L, 1);
  33. size_t size = (size_t)luaL_checkinteger(L, 2);
  34. if (size != (uint32_t)size) {
  35. return luaL_error(L, "Size should be 32bit integer");
  36. }
  37. return pack(L, data, size);
  38. }
  39. /*
  40. lightuserdata
  41. integer size
  42. return lightuserdata, sizeof(struct mc_package *)
  43. */
  44. static int
  45. mc_packremote(lua_State *L) {
  46. void * data = lua_touserdata(L, 1);
  47. size_t size = (size_t)luaL_checkinteger(L, 2);
  48. if (size != (uint32_t)size) {
  49. return luaL_error(L, "Size should be 32bit integer");
  50. }
  51. void * msg = skynet_malloc(size);
  52. memcpy(msg, data, size);
  53. return pack(L, msg, size);
  54. }
  55. /*
  56. lightuserdata struct mc_package **
  57. integer size (must be sizeof(struct mc_package *)
  58. return package, lightuserdata, size
  59. */
  60. static int
  61. mc_unpacklocal(lua_State *L) {
  62. struct mc_package ** pack = lua_touserdata(L,1);
  63. int sz = luaL_checkinteger(L,2);
  64. if (sz != sizeof(pack)) {
  65. return luaL_error(L, "Invalid multicast package size %d", sz);
  66. }
  67. lua_pushlightuserdata(L, *pack);
  68. lua_pushlightuserdata(L, (*pack)->data);
  69. lua_pushinteger(L, (lua_Integer)((*pack)->size));
  70. return 3;
  71. }
  72. /*
  73. lightuserdata struct mc_package **
  74. integer reference
  75. return mc_package *
  76. */
  77. static int
  78. mc_bindrefer(lua_State *L) {
  79. struct mc_package ** pack = lua_touserdata(L,1);
  80. int ref = luaL_checkinteger(L,2);
  81. if (ATOM_LOAD(&(*pack)->reference) != 0) {
  82. return luaL_error(L, "Can't bind a multicast package more than once");
  83. }
  84. ATOM_STORE(&(*pack)->reference , ref);
  85. lua_pushlightuserdata(L, *pack);
  86. skynet_free(pack);
  87. return 1;
  88. }
  89. /*
  90. lightuserdata struct mc_package *
  91. */
  92. static int
  93. mc_closelocal(lua_State *L) {
  94. struct mc_package *pack = lua_touserdata(L,1);
  95. int ref = ATOM_FDEC(&pack->reference)-1;
  96. if (ref <= 0) {
  97. skynet_free(pack->data);
  98. skynet_free(pack);
  99. if (ref < 0) {
  100. return luaL_error(L, "Invalid multicast package reference %d", ref);
  101. }
  102. }
  103. return 0;
  104. }
  105. /*
  106. lightuserdata struct mc_package **
  107. return lightuserdata/size
  108. */
  109. static int
  110. mc_remote(lua_State *L) {
  111. struct mc_package **ptr = lua_touserdata(L,1);
  112. struct mc_package *pack = *ptr;
  113. lua_pushlightuserdata(L, pack->data);
  114. lua_pushinteger(L, (lua_Integer)(pack->size));
  115. skynet_free(pack);
  116. skynet_free(ptr);
  117. return 2;
  118. }
  119. static int
  120. mc_nextid(lua_State *L) {
  121. uint32_t id = (uint32_t)luaL_checkinteger(L, 1);
  122. id += 256;
  123. // remove the highest bit, see #1139
  124. lua_pushinteger(L, id & 0x7fffffffu);
  125. return 1;
  126. }
  127. LUAMOD_API int
  128. luaopen_skynet_multicast_core(lua_State *L) {
  129. luaL_Reg l[] = {
  130. { "pack", mc_packlocal },
  131. { "unpack", mc_unpacklocal },
  132. { "bind", mc_bindrefer },
  133. { "close", mc_closelocal },
  134. { "remote", mc_remote },
  135. { "packremote", mc_packremote },
  136. { "nextid", mc_nextid },
  137. { NULL, NULL },
  138. };
  139. luaL_checkversion(L);
  140. luaL_newlib(L,l);
  141. return 1;
  142. }