luat_lib_httpsrv.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. @module httpsrv
  3. @summary http服务端
  4. @version 1.0
  5. @date 2022.010.15
  6. @demo wlan
  7. @tag LUAT_USE_HTTPSRV
  8. */
  9. #include "luat_base.h"
  10. #include "luat_httpsrv.h"
  11. #include "luat_network_adapter.h"
  12. #include "luat_netdrv.h"
  13. #include "lwip/netif.h"
  14. #include "lwip/ip_addr.h"
  15. #define LUAT_LOG_TAG "httpsrv"
  16. #include "luat_log.h"
  17. #define LUAT_HTTPSRV_COUNT 16
  18. typedef struct port_srv
  19. {
  20. uint16_t port;
  21. uint8_t adapter;
  22. uint8_t status;
  23. luat_httpsrv_ctx_t* ctx;
  24. }port_srv_t;
  25. static port_srv_t srvs[LUAT_HTTPSRV_COUNT];
  26. /*
  27. 启动并监听一个http端口
  28. @api httpsrv.start(port, func, adapter)
  29. @int 端口号
  30. @function 回调函数
  31. @int 网络适配器编号, 默认是平台自带的网络协议栈
  32. @return bool 成功返回true, 否则返回false
  33. @usage
  34. -- 监听80端口
  35. httpsrv.start(80, function(client, method, uri, headers, body)
  36. -- method 是字符串, 例如 GET POST PUT DELETE
  37. -- uri 也是字符串 例如 / /api/abc
  38. -- headers table类型
  39. -- body 字符串
  40. log.info("httpsrv", method, uri, json.encode(headers), body)
  41. if uri == "/led/1" then
  42. LEDA(1)
  43. return 200, {}, "ok"
  44. elseif uri == "/led/0" then
  45. LEDA(0)
  46. return 200, {}, "ok"
  47. end
  48. -- 返回值的约定 code, headers, body
  49. -- 若没有返回值, 则默认 404, {} ,""
  50. return 404, {}, "Not Found" .. uri
  51. end)
  52. -- 关于静态文件
  53. -- 情况1: / , 映射为 /index.html
  54. -- 情况2: /abc.html , 先查找 /abc.html, 不存在的话查找 /abc.html.gz
  55. -- 若gz存在, 会自动以压缩文件进行响应, 绝大部分浏览器支持.
  56. -- 当前默认查找 /luadb/xxx 下的文件,暂不可配置
  57. */
  58. static int l_httpsrv_start(lua_State *L) {
  59. luat_ip_addr_t local_ip, net_mask, gate_way, ipv6;
  60. char buff[64] = {0};
  61. int port = luaL_checkinteger(L, 1);
  62. if (!lua_isfunction(L, 2)) {
  63. LLOGW("httpsrv need callback function!!!");
  64. return 0;
  65. }
  66. uint8_t adapter_index = luaL_optinteger(L, 3, network_register_get_default());
  67. luat_netdrv_t* drv = luat_netdrv_get(adapter_index);
  68. if (drv == NULL || drv->netif == NULL) {
  69. LLOGW("该网络还没准备好 %d", adapter_index);
  70. return 0;
  71. }
  72. // 检查一下是否有空位
  73. for (size_t i = 0; i < LUAT_HTTPSRV_COUNT; i++)
  74. {
  75. if (srvs[i].port == port && srvs[i].adapter == adapter_index) {
  76. LLOGW("httpsrv port %d already in use", port);
  77. return 0;
  78. }
  79. }
  80. int index = -1;
  81. for (size_t i = 0; i < LUAT_HTTPSRV_COUNT; i++)
  82. {
  83. if (srvs[i].ctx == NULL) {
  84. index = i;
  85. break;
  86. }
  87. }
  88. if (index < 0) {
  89. LLOGW("httpsrv no free slot, max %d", LUAT_HTTPSRV_COUNT);
  90. return 0;
  91. }
  92. luat_httpsrv_ctx_t* ctx = luat_httpsrv_malloc(port, adapter_index);
  93. if (ctx == NULL) {
  94. return 0;
  95. }
  96. ctx->netif = drv->netif;
  97. lua_pushvalue(L, 2);
  98. ctx->lua_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
  99. int ret = luat_httpsrv_start(ctx);
  100. if (ret == 0) {
  101. ipaddr_ntoa_r(&drv->netif->ip_addr, buff, 32);
  102. LLOGI("http listen at %s:%d", buff, ctx->port);
  103. srvs[index].port = port;
  104. srvs[index].adapter = adapter_index;
  105. srvs[index].ctx = ctx;
  106. srvs[index].status = 1;
  107. }
  108. lua_pushboolean(L, ret == 0 ? 1 : 0);
  109. return 1;
  110. }
  111. /*
  112. 停止http服务
  113. @api httpsrv.stop(port)
  114. @int 端口号
  115. @return nil 当前无返回值
  116. */
  117. static int l_httpsrv_stop(lua_State *L) {
  118. int port = luaL_checkinteger(L, 1);
  119. uint8_t adapter_index = luaL_optinteger(L, 3, network_register_get_default());
  120. for (size_t i = 0; i < LUAT_HTTPSRV_COUNT; i++)
  121. {
  122. if (srvs[i].port == port && srvs[i].adapter == adapter_index) {
  123. if (srvs[i].ctx != NULL) {
  124. srvs[i].port = 0;
  125. srvs[i].adapter = 0;
  126. srvs[i].status = 0;
  127. if (srvs[i].ctx->lua_ref_id != LUA_NOREF) {
  128. luaL_unref(L, LUA_REGISTRYINDEX, srvs[i].ctx->lua_ref_id);
  129. srvs[i].ctx->lua_ref_id = LUA_NOREF;
  130. }
  131. luat_httpsrv_stop(srvs[i].ctx);
  132. srvs[i].ctx = NULL;
  133. lua_pushboolean(L, 1);
  134. return 1;
  135. }
  136. }
  137. }
  138. return 0;
  139. }
  140. #include "rotable2.h"
  141. static const rotable_Reg_t reg_httpsrv[] =
  142. {
  143. {"start", ROREG_FUNC(l_httpsrv_start) },
  144. {"stop", ROREG_FUNC(l_httpsrv_stop) },
  145. { NULL, ROREG_INT(0) }
  146. };
  147. LUAMOD_API int luaopen_httpsrv( lua_State *L ) {
  148. luat_newlib2(L, reg_httpsrv);
  149. return 1;
  150. }