luat_lib_netdrv.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. /*
  2. @module netdrv
  3. @summary 网络设备管理
  4. @catalog 外设API
  5. @version 1.0
  6. @date 2025.01.07
  7. @demo netdrv
  8. @tag LUAT_USE_NETDRV
  9. */
  10. #include "luat_base.h"
  11. #include "luat_gpio.h"
  12. #include "luat_mem.h"
  13. #include "luat_mcu.h"
  14. #include "luat_msgbus.h"
  15. #include "luat_timer.h"
  16. #include "luat_rtos.h"
  17. #include "luat_netdrv.h"
  18. #include "luat_netdrv_napt.h"
  19. #include "luat_netdrv_drv.h"
  20. #include "luat_network_adapter.h"
  21. #include "luat_netdrv_event.h"
  22. #include "net_lwip2.h"
  23. #include "lwip/ip.h"
  24. #include "lwip/ip4.h"
  25. #define LUAT_LOG_TAG "netdrv"
  26. #include "luat_log.h"
  27. /*
  28. 初始化指定netdrv设备
  29. @api netdrv.setup(id, tp, opts)
  30. @int 网络适配器编号, 例如 socket.LWIP_ETH, socket.LWIP_USER0
  31. @int 实现方式,如果是设备自带的硬件,那就不需要传, 外挂设备需要传,当前支持CH390H/D/OPENVPN等
  32. @table 外挂方式,需要额外的参数,参考示例
  33. @return boolean 初始化成功与否
  34. @usage
  35. -- Air8101初始化内部以太网控制器
  36. netdrv.setup(socket.LWIP_ETH)
  37. -- Air8000/Air780EPM初始化CH390H/D作为LAN/WAN
  38. -- 支持多个CH390H, 使用不同的CS脚区分不同网口
  39. netdrv.setup(socket.LWIP_ETH, netdrv.CH390, {spi=0,cs=8})
  40. netdrv.dhcp(socket.LWIP_ETH, true)
  41. -- 支持CH390H的中断模式, 能提供响应速度, 但是需要外接中断引脚
  42. -- 实测对总网速没有帮助, 轻负载时能降低功耗, 让模组能进入低功耗模式
  43. netdrv.setup(socket.LWIP_ETH, netdrv.CH390, {spi=0,cs=8,irq=20})
  44. */
  45. static int l_netdrv_setup(lua_State *L) {
  46. luat_netdrv_conf_t conf = {0};
  47. size_t len = 0;
  48. conf.id = luaL_checkinteger(L, 1);
  49. conf.impl = luaL_optinteger(L, 2, 0);
  50. conf.irqpin = 255; // 默认无效
  51. if (lua_istable(L, 3)) {
  52. if (lua_getfield(L, 3, "spi") == LUA_TNUMBER) {
  53. conf.spiid = luaL_checkinteger(L, -1);
  54. };
  55. lua_pop(L, 1);
  56. if (lua_getfield(L, 3, "cs") == LUA_TNUMBER) {
  57. conf.cspin = luaL_checkinteger(L, -1);
  58. };
  59. lua_pop(L, 1);
  60. if (lua_getfield(L, 3, "irq") == LUA_TNUMBER) {
  61. conf.irqpin = luaL_checkinteger(L, -1);
  62. };
  63. lua_pop(L, 1);
  64. if (lua_getfield(L, 3, "mtu") == LUA_TNUMBER) {
  65. conf.mtu = luaL_checkinteger(L, -1);
  66. };
  67. lua_pop(L, 1);
  68. if (lua_getfield(L, 3, "flags") == LUA_TNUMBER) {
  69. conf.flags = luaL_checkinteger(L, -1);
  70. };
  71. lua_pop(L, 1);
  72. #ifdef LUAT_USE_NETDRV_WG
  73. // WG的配置参数比较多, 放在这里面传递
  74. // 需要的参数有, private_key, public_key, endpoint, port, address, dns, mtu
  75. if (lua_getfield(L, 3, "wg_private_key") == LUA_TSTRING) {
  76. conf.wg_private_key = luaL_checklstring(L, -1, &len);
  77. };
  78. lua_pop(L, 1);
  79. // 本地端口
  80. if (lua_getfield(L, 3, "wg_listen_port") == LUA_TNUMBER) {
  81. conf.wg_listen_port = luaL_checkinteger(L, -1);
  82. };
  83. lua_pop(L, 1);
  84. // keepalive时长
  85. if (lua_getfield(L, 3, "wg_keepalive") == LUA_TNUMBER) {
  86. conf.wg_keepalive = luaL_checkinteger(L, -1);
  87. };
  88. lua_pop(L, 1);
  89. // 预分享密钥
  90. if (lua_getfield(L, 3, "wg_preshared_key") == LUA_TSTRING) {
  91. conf.wg_preshared_key = luaL_checklstring(L, -1, &len);
  92. };
  93. lua_pop(L, 1);
  94. // 对端信息, 公钥, IP地址, 端口
  95. if (lua_getfield(L, 3, "wg_endpoint_key") == LUA_TSTRING) {
  96. conf.wg_endpoint_key = luaL_checklstring(L, -1, &len);
  97. };
  98. lua_pop(L, 1);
  99. if (lua_getfield(L, 3, "wg_endpoint_ip") == LUA_TSTRING) {
  100. conf.wg_endpoint_ip = luaL_checklstring(L, -1, &len);
  101. };
  102. lua_pop(L, 1);
  103. if (lua_getfield(L, 3, "wg_endpoint_port") == LUA_TNUMBER) {
  104. conf.wg_endpoint_port = luaL_checkinteger(L, -1);
  105. };
  106. lua_pop(L, 1);
  107. #endif
  108. #ifdef LUAT_USE_NETDRV_OPENVPN
  109. // OpenVPN的配置参数
  110. if (lua_getfield(L, 3, "ovpn_remote_ip") == LUA_TSTRING) {
  111. conf.ovpn_remote_ip = luaL_checklstring(L, -1, &len);
  112. };
  113. lua_pop(L, 1);
  114. if (lua_getfield(L, 3, "ovpn_remote_port") == LUA_TNUMBER) {
  115. conf.ovpn_remote_port = luaL_checkinteger(L, -1);
  116. };
  117. lua_pop(L, 1);
  118. if (lua_getfield(L, 3, "ovpn_ca_cert") == LUA_TSTRING) {
  119. conf.ovpn_ca_cert = luaL_checklstring(L, -1, &conf.ovpn_ca_cert_len);
  120. };
  121. lua_pop(L, 1);
  122. if (lua_getfield(L, 3, "ovpn_client_cert") == LUA_TSTRING) {
  123. conf.ovpn_client_cert = luaL_checklstring(L, -1, &conf.ovpn_client_cert_len);
  124. };
  125. lua_pop(L, 1);
  126. if (lua_getfield(L, 3, "ovpn_client_key") == LUA_TSTRING) {
  127. conf.ovpn_client_key = luaL_checklstring(L, -1, &conf.ovpn_client_key_len);
  128. };
  129. lua_pop(L, 1);
  130. if (lua_getfield(L, 3, "ovpn_static_key") == LUA_TSTRING) {
  131. conf.ovpn_static_key = (const uint8_t *)luaL_checklstring(L, -1, &conf.ovpn_static_key_len);
  132. };
  133. lua_pop(L, 1);
  134. #endif
  135. }
  136. luat_netdrv_t* ret = luat_netdrv_setup(&conf);
  137. lua_pushboolean(L, ret != NULL);
  138. return 1;
  139. }
  140. /*
  141. 开启或关闭DHCP
  142. @api netdrv.dhcp(id, enable, name)
  143. @int 网络适配器编号, 例如 socket.LWIP_ETH
  144. @boolean 开启或者关闭
  145. @string dhcp主机名称, 可选, 最长31字节,填""清除
  146. @return boolean 成功与否
  147. @usgae
  148. -- 注意, 并非所有网络设备都支持关闭DHCP, 例如4G Cat.1自带的netdrv就不支持关闭DHCP
  149. -- name参数于2025.9.23添加
  150. netdrv.dhcp(socket.LWIP_ETH, true)
  151. netdrv.dhcp(socket.LWIP_ETH, true, "LuatOS")
  152. */
  153. static int l_netdrv_dhcp(lua_State *L) {
  154. int id = luaL_checkinteger(L, 1);
  155. int enable = lua_toboolean(L, 2);
  156. if (lua_isstring(L, 3)) {
  157. size_t len = 0;
  158. const char* data = NULL;
  159. luat_netdrv_t *drv = NULL;
  160. data = luaL_checklstring(L, 3, &len);
  161. drv = luat_netdrv_get(id);
  162. if(((len + 1) > 32) || (drv == NULL) || (drv->ulwip == NULL)) {
  163. LLOGD("adapter %d dhcp name set fail", id);
  164. lua_pushboolean(L, 0);
  165. return 1;
  166. }
  167. if(0 == len){
  168. memset(drv->ulwip->dhcp_client.name, 0x00, 32);
  169. } else {
  170. memcpy(drv->ulwip->dhcp_client.name, data, len + 1);
  171. }
  172. }
  173. int ret = luat_netdrv_dhcp(id, enable);
  174. lua_pushboolean(L, ret == 0);
  175. return 1;
  176. }
  177. /*
  178. 设置或获取设备MAC
  179. @api netdrv.mac(id, new_mac, raw_string)
  180. @int 网络适配器编号, 例如 socket.LWIP_ETH
  181. @string 新的MAC地址,可选, 必须是6个字节
  182. @boolean 是否返回6字节原始数据, 默认是否, 返回HEX字符串
  183. @return boolean 成功与否
  184. @usage
  185. -- 获取MAC地址
  186. log.info("netdrv", "mac addr", netdrv.mac(socket.LWIP_ETH))
  187. -- 暂不支持设置
  188. */
  189. static int l_netdrv_mac(lua_State *L) {
  190. int id = luaL_checkinteger(L, 1);
  191. uint8_t buff[6] = {0};
  192. char tmpbuff[13] = {0};
  193. size_t len = 0;
  194. if (lua_type(L, 2) == LUA_TSTRING) {
  195. const char* tmp = luaL_checklstring(L, 2, &len);
  196. if (len != 6) {
  197. return 0;
  198. }
  199. luat_netdrv_mac(id, tmp, (char*)buff);
  200. }
  201. else {
  202. luat_netdrv_mac(id, NULL, (char*)buff);
  203. }
  204. if (lua_isboolean(L, 3) && !lua_toboolean(L, 3)) {
  205. lua_pushlstring(L, (const char*)buff, 6);
  206. }
  207. else {
  208. sprintf_(tmpbuff, "%02X%02X%02X%02X%02X%02X", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
  209. lua_pushstring(L, tmpbuff);
  210. }
  211. return 1;
  212. }
  213. /*
  214. 设置或读取ipv4地址
  215. @api netdrv.ipv4(id, addr, mark, gw)
  216. @int 网络适配器编号, 例如 socket.LWIP_ETH
  217. @string ipv4地址,如果是读取就不需要传
  218. @string 掩码
  219. @string 网关
  220. @return string ipv4地址
  221. @return string 掩码
  222. @return string 网关
  223. @usage
  224. -- 注意, 不是所有netdrv都支持设置的, 尤其4G Cat.1自带的netdrv就不能设置ipv4
  225. -- 注意, 设置ipv4时, DHCP要处于关闭状态!!
  226. -- 当前设置ip但ip值非法, 不返回任何东西
  227. -- 如果设置ip且ip值合法, 会返回ip, mask, gw
  228. */
  229. static int l_netdrv_ipv4(lua_State *L) {
  230. int id = luaL_checkinteger(L, 1);
  231. const char* tmp = NULL;
  232. luat_ip_addr_t ip;
  233. luat_ip_addr_t netmask;
  234. luat_ip_addr_t gw;
  235. int ret = 0;
  236. luat_netdrv_t* netdrv = luat_netdrv_get(id);
  237. if (netdrv == NULL || netdrv->netif == NULL) {
  238. LLOGW("对应的netdrv不存在或未就绪 %d %p", id, netdrv);
  239. return 0;
  240. }
  241. if (lua_isstring(L, 2) && lua_isstring(L, 3) && lua_isstring(L, 4)) {
  242. luat_netdrv_dhcp(id, 0); // 自动关闭DHCP
  243. tmp = luaL_checkstring(L, 2);
  244. ret = ipaddr_aton(tmp, &ip);
  245. if (!ret) {
  246. LLOGW("非法IP[%d] %s %d", id, tmp, ret);
  247. return 0;
  248. }
  249. tmp = luaL_checkstring(L, 3);
  250. ret = ipaddr_aton(tmp, &netmask);
  251. if (!ret) {
  252. LLOGW("非法MARK[%d] %s %d", id, tmp, ret);
  253. return 0;
  254. }
  255. tmp = luaL_checkstring(L, 4);
  256. ret = ipaddr_aton(tmp, &gw);
  257. if (ret == 0) {
  258. LLOGW("非法GW[%d] %s %d", id, tmp, ret);
  259. return 0;
  260. }
  261. ret = network_set_static_ip_info(id, &ip, &netmask, &gw, NULL);
  262. LLOGI("设置IP[%d] %s %s %s ret %d", id,
  263. luaL_checkstring(L, 2),
  264. luaL_checkstring(L, 3),
  265. luaL_checkstring(L, 4),
  266. ret
  267. );
  268. }
  269. char buff[16] = {0};
  270. char buff2[16] = {0};
  271. char buff3[16] = {0};
  272. ipaddr_ntoa_r(&netdrv->netif->ip_addr, buff, 16);
  273. ipaddr_ntoa_r(&netdrv->netif->netmask, buff2, 16);
  274. ipaddr_ntoa_r(&netdrv->netif->gw, buff3, 16);
  275. lua_pushstring(L, buff);
  276. lua_pushstring(L, buff2);
  277. lua_pushstring(L, buff3);
  278. return 3;
  279. }
  280. /*
  281. 开启或关闭NAPT
  282. @api netdrv.napt(id)
  283. @int 网关适配器的id
  284. @return bool 合法值就返回true, 否则返回nil
  285. @usage
  286. -- 使用4G网络作为主网关出口
  287. netdrv.napt(socket.LWIP_GP)
  288. -- 关闭napt功能
  289. netdrv.napt(-1)
  290. */
  291. static int l_netdrv_napt(lua_State *L) {
  292. int id = luaL_checkinteger(L, 1);
  293. if (id < 0) {
  294. LLOGD("NAPT is disabled");
  295. luat_netdrv_napt_enable(id);
  296. lua_pushboolean(L, 1);
  297. return 1;
  298. }
  299. luat_netdrv_t* netdrv = luat_netdrv_get(id);
  300. if (netdrv == NULL || netdrv->netif == NULL) {
  301. LLOGE("对应的网关netdrv不存在或未就绪 %d", id);
  302. return 0;
  303. }
  304. LLOGD("NAPT is enabled gw %d", id);
  305. luat_netdrv_napt_enable(id);
  306. lua_pushboolean(L, 1);
  307. return 1;
  308. }
  309. /*
  310. 获取netdrv的物理连接状态
  311. @api netdrv.link(id)
  312. @int netdrv的id, 例如 socket.LWIP_ETH
  313. @return bool 已连接返回true, 否则返回false. 如果id对应的netdrv不存在,返回nil
  314. @usage
  315. -- 注意, 本函数仅支持读取, 而且不能ip状态, 即是否能联网
  316. */
  317. static int l_netdrv_link(lua_State *L) {
  318. int id = luaL_checkinteger(L, 1);
  319. if (id < 0) {
  320. return 0; // 非法id
  321. }
  322. luat_netdrv_t* netdrv = luat_netdrv_get(id);
  323. if (netdrv == NULL || netdrv->netif == NULL) {
  324. return 0;
  325. }
  326. lua_pushboolean(L, netif_is_link_up(netdrv->netif));
  327. return 1;
  328. }
  329. /*
  330. 获取netdrv的网络状态
  331. @api netdrv.ready(id)
  332. @int netdrv的id, 例如 socket.LWIP_ETH
  333. @return bool 已连接返回true, 否则返回false. 如果id对应的netdrv不存在,返回nil
  334. @usage
  335. -- 注意, 本函数仅支持读取, 即判断是否能通信, 不代表IP状态
  336. */
  337. static int l_netdrv_ready(lua_State *L) {
  338. int id = luaL_checkinteger(L, 1);
  339. if (id < 0) {
  340. return 0; // 非法id
  341. }
  342. luat_netdrv_t* netdrv = luat_netdrv_get(id);
  343. if (netdrv == NULL || netdrv->netif == NULL) {
  344. return 0;
  345. }
  346. lua_pushboolean(L, netif_is_link_up(netdrv->netif) && !ip_addr_isany(&netdrv->netif->ip_addr));
  347. return 1;
  348. }
  349. /*
  350. 给具体的驱动发送控制指令
  351. @api netdrv.ctrl(id, cmd, arg)
  352. @int 网络适配器编号, 例如 socket.LWIP_ETH
  353. @int 指令, 例如 netdrv.CTRL_RESET
  354. @int 参数, 例如 netdrv.RESET_HARD
  355. @return boolean 成功与否
  356. @usage
  357. -- 重启网卡, 仅CH390H支持, 其他网络设备暂不支持
  358. -- 本函数于 2025.4.14 新增
  359. netdrv.ctrl(socket.LWIP_ETH, netdrv.CTRL_RESET, netdrv.RESET_HARD)
  360. -- 关闭CH390H通信并下电PHY,可用于降功耗;第三个参数1=关闭,0=重新启动
  361. netdrv.ctrl(socket.LWIP_ETH, netdrv.CTRL_DOWN, 1)
  362. netdrv.ctrl(socket.LWIP_ETH, netdrv.CTRL_DOWN, 0)
  363. */
  364. static int l_netdrv_ctrl(lua_State *L) {
  365. int id = luaL_checkinteger(L, 1);
  366. int cmd = luaL_checkinteger(L, 2);
  367. int arg = luaL_checkinteger(L, 3);
  368. luat_netdrv_t* drv = luat_netdrv_get(id);
  369. if (drv == NULL) {
  370. LLOGW("not such netdrv %d", id);
  371. return 0;
  372. }
  373. if (drv->ctrl == NULL) {
  374. LLOGW("netdrv %d not support ctrl", id);
  375. return 0;
  376. }
  377. int ret = drv->ctrl(drv, drv->userdata, cmd, arg);
  378. lua_pushboolean(L, ret == 0);
  379. lua_pushinteger(L, ret);
  380. return 2;
  381. }
  382. /*
  383. 设置调试信息输出
  384. @api netdrv.debug(id, enable)
  385. @int 网络适配器编号, 例如 socket.LWIP_ETH, 如果传0就是全局调试开关
  386. @boolean 是否开启调试信息输出
  387. @return boolean 成功与否
  388. @usage
  389. -- 打开netdrv全局调试开关
  390. netdrv.debug(0, true)
  391. */
  392. static int l_netdrv_debug(lua_State *L) {
  393. int id = luaL_checkinteger(L, 1);
  394. int enable = lua_toboolean(L, 2);
  395. luat_netdrv_debug_set(id, enable);
  396. return 0;
  397. }
  398. /*
  399. 设置遥测功能,开启后,会自动上报设备信息,2025/9/25启用
  400. @api netdrv.mreport(config, value)
  401. @string 配置项
  402. @boolean 设置功能开关
  403. @return boolean 成功与否
  404. @usage
  405. -- 设置开启与关闭
  406. netdrv.mreport("enable", true)
  407. netdrv.mreport("enable", false)
  408. -- 设置使用的网络适配器,2025/10/30启用
  409. netdrv.mreport("adapter_id", socket.LWIP_GP)
  410. netdrv.mreport("adapter_id", socket.LWIP_STA)
  411. netdrv.mreport("adapter_id", socket.LWIP_ETH)
  412. -- 立即上报一次, 无参数的方式调用
  413. netdrv.mreport()
  414. */
  415. extern int l_mreport_config(lua_State* L);
  416. /*
  417. 发起ping(异步的)
  418. @api netdrv.ping(id, ip, len)
  419. @int 网络适配器的id
  420. @string 目标ip地址,不支持域名!!
  421. @int ping包大小,默认128字节,可以不传
  422. @return bool 成功与否, 仅代表发送与否,不代表服务器已经响应
  423. @usage
  424. -- 本功能在2025.9.3新增
  425. sys.taskInit(function()
  426. -- 要等联网了才能ping
  427. sys.waitUntil("IP_READY")
  428. sys.wait(1000)
  429. while 1 do
  430. -- 必须指定使用哪个网卡
  431. netdrv.ping(socket.LWIP_GP, "121.14.77.221")
  432. sys.waitUntil("PING_RESULT", 3000)
  433. sys.wait(3000)
  434. end
  435. end)
  436. sys.subscribe("PING_RESULT", function(id, time, dst)
  437. log.info("ping", id, time, dst);
  438. end)
  439. */
  440. extern int l_icmp_ping(lua_State *L);
  441. static int s_socket_evt_ref[NW_ADAPTER_QTY] = {0};
  442. static int l_socket_evt_cb(lua_State *L, void* ptr) {
  443. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  444. netdrv_tcp_evt_t* evt = (netdrv_tcp_evt_t*)ptr;
  445. int ref = s_socket_evt_ref[evt->id];
  446. if (ref == 0) {
  447. LLOGW("socket evt cb no lua ref");
  448. luat_heap_free(ptr);
  449. return 0;
  450. }
  451. // LLOGD("socket evt cb %d %d lua function %d", evt->id, evt->flags, ref);
  452. // 取出函数
  453. lua_geti(L, LUA_REGISTRYINDEX, ref);
  454. if (!lua_isfunction(L, -1)) {
  455. LLOGW("socket evt cb ref not function");
  456. lua_pop(L, 1);
  457. luat_heap_free(ptr);
  458. return 0;
  459. }
  460. lua_pushinteger(L, evt->id);
  461. switch (evt->flags)
  462. {
  463. case 0x81:
  464. lua_pushstring(L, "create");
  465. break;
  466. case 0x82:
  467. lua_pushstring(L, "release");
  468. break;
  469. case 0x83:
  470. lua_pushstring(L, "connecting");
  471. break;
  472. case EV_NW_TIMEOUT - EV_NW_RESET:
  473. lua_pushstring(L, "timeout");
  474. break;
  475. case EV_NW_SOCKET_CLOSE_OK - EV_NW_RESET:
  476. lua_pushstring(L, "closed");
  477. break;
  478. case EV_NW_SOCKET_CONNECT_OK - EV_NW_RESET:
  479. lua_pushstring(L, "connected");
  480. break;
  481. case EV_NW_SOCKET_REMOTE_CLOSE - EV_NW_RESET:
  482. lua_pushstring(L, "remote_close");
  483. break;
  484. case EV_NW_SOCKET_ERROR - EV_NW_RESET:
  485. lua_pushstring(L, "error");
  486. break;
  487. case EV_NW_DNS_RESULT - EV_NW_RESET:
  488. lua_pushstring(L, "dns_result");
  489. break;
  490. default:
  491. lua_pushstring(L, "unknown");
  492. break;
  493. }
  494. lua_newtable(L);
  495. // 填充参数表 远端ip, 远端端口, 本地ip, 本地端口
  496. char buff[32] = {0};
  497. if (!ip_addr_isany(&evt->remote_ip)) {
  498. ipaddr_ntoa_r(&evt->remote_ip, buff, 32);
  499. lua_pushstring(L, buff);
  500. lua_setfield(L, -2, "remote_ip");
  501. }
  502. if (!ip_addr_isany(&evt->online_ip)) {
  503. ipaddr_ntoa_r(&evt->online_ip, buff, 32);
  504. lua_pushstring(L, buff);
  505. lua_setfield(L, -2, "online_ip");
  506. }
  507. lua_pushinteger(L, evt->remote_port);
  508. lua_setfield(L, -2, "remote_port");
  509. switch (evt->proto)
  510. {
  511. case 1:
  512. lua_pushstring(L, "tcp");
  513. break;
  514. case 2:
  515. lua_pushstring(L, "udp");
  516. break;
  517. case 3:
  518. lua_pushstring(L, "http");
  519. break;
  520. case 4:
  521. lua_pushstring(L, "mqtt");
  522. break;
  523. case 5:
  524. lua_pushstring(L, "websocket");
  525. break;
  526. default:
  527. lua_pushstring(L, "unknown");
  528. break;
  529. }
  530. lua_setfield(L, -2, "proto");
  531. // p = ipaddr_ntoa_r(&evt->local_ip, buff, 32);
  532. // lua_pushstring(L, p);
  533. // lua_setfield(L, -2, "local_ip");
  534. // lua_pushinteger(L, evt->local_port);
  535. // lua_setfield(L, -2, "local_port");
  536. if (evt->domain_name[0]) {
  537. lua_pushstring(L, evt->domain_name);
  538. lua_setfield(L, -2, "domain_name");
  539. }
  540. lua_call(L, 3, 0);
  541. // 释放内存
  542. luat_heap_free(ptr);
  543. return 0;
  544. }
  545. static void luat_socket_evt_cb(netdrv_tcp_evt_t* evt, void* userdata) {
  546. rtos_msg_t msg = {0};
  547. msg.handler = l_socket_evt_cb;
  548. msg.ptr = luat_heap_malloc(sizeof(netdrv_tcp_evt_t));
  549. if (msg.ptr == NULL) {
  550. LLOGE("socket evt cb no mem");
  551. return;
  552. }
  553. memcpy(msg.ptr, evt, sizeof(netdrv_tcp_evt_t));
  554. luat_msgbus_put(&msg, 0);
  555. }
  556. // 监听socket事件
  557. /*
  558. 订阅网络事件
  559. @api netdrv.on(adapter_id, event_type, callback)
  560. @int 网络适配器的id
  561. @int 事件总类型, 当前支持 netdrv.EVT_SOCKET
  562. @function 回调函数 function(id, event, params)
  563. @return bool 成功与否,成功返回true,否则返回nil
  564. @usage
  565. -- 订阅socket连接状态变化事件
  566. netdrv.on(socket.LWIP_ETH, netdrv.EVT_SOCKET, function(id, event, params)
  567. -- id 是网络适配器id
  568. -- event是事件id, 字符串类型,
  569. - create 创建socket对象
  570. - release 释放socket对象
  571. - connecting 正在连接, 域名解析成功后出现
  572. - connected 连接成功, TCP三次握手成功后出现
  573. - closed 连接关闭
  574. - remote_close 远程关闭, 网络中断,或者服务器主动断开
  575. - timeout dns解析超时,或者tcp连接超时
  576. - error 错误,包括一切异常错误
  577. -- params是参数表
  578. - remote_ip 远端ip地址,未必存在
  579. - remote_port 远端端口,未必存在
  580. - online_ip 实际连接的ip地址,未必存在
  581. - domain_name 远端域名,如果是通过域名连接的话, release时没有这个值, create时也没有
  582. log.info("netdrv", "socket event", id, event, json.encode(params or {}))
  583. if params then
  584. -- params里会有remote_ip, remote_port等信息, 可按需获取
  585. local remote_ip = params.remote_ip
  586. local remote_port = params.remote_port
  587. local domain_name = params.domain_name
  588. log.info("netdrv", "socket event", "remote_ip", remote_ip, "remote_port", remote_port, "domain_name", domain_name)
  589. end
  590. end)
  591. */
  592. static int l_netdrv_on(lua_State *L) {
  593. int id = luaL_checkinteger(L, 1);
  594. if (id < 0) {
  595. return 0; // 非法id
  596. }
  597. luat_netdrv_t* netdrv = luat_netdrv_get(id);
  598. if (netdrv == NULL || netdrv->netif == NULL) {
  599. return 0;
  600. }
  601. int event_id = luaL_checkinteger(L, 2);
  602. if (event_id == 0) {
  603. if (s_socket_evt_ref[id]) {
  604. luaL_unref(L, LUA_REGISTRYINDEX, s_socket_evt_ref[id]);
  605. s_socket_evt_ref[id] = 0;
  606. }
  607. luat_netdrv_register_socket_event_cb(id, 0, NULL, NULL);
  608. lua_pushboolean(L, 1);
  609. return 1;
  610. }
  611. else if (event_id == 1) {
  612. if (!lua_isfunction(L, 3)) {
  613. return 0;
  614. }
  615. lua_pushvalue(L, 3);
  616. s_socket_evt_ref[id] = luaL_ref(L, LUA_REGISTRYINDEX);
  617. // LLOGD("register socket event cb %d", s_socket_evt_ref[id]);
  618. luat_netdrv_register_socket_event_cb(id, 0xFF, luat_socket_evt_cb, NULL);
  619. lua_pushboolean(L, 1);
  620. return 1;
  621. }
  622. LLOGW("not support event type %d", event_id);
  623. return 0;
  624. }
  625. #include "rotable2.h"
  626. static const rotable_Reg_t reg_netdrv[] =
  627. {
  628. { "setup" , ROREG_FUNC(l_netdrv_setup )},
  629. { "dhcp", ROREG_FUNC(l_netdrv_dhcp)},
  630. { "mac", ROREG_FUNC(l_netdrv_mac)},
  631. { "ipv4", ROREG_FUNC(l_netdrv_ipv4)},
  632. { "napt", ROREG_FUNC(l_netdrv_napt)},
  633. { "link", ROREG_FUNC(l_netdrv_link)},
  634. { "ready", ROREG_FUNC(l_netdrv_ready)},
  635. { "ctrl", ROREG_FUNC(l_netdrv_ctrl)},
  636. { "debug", ROREG_FUNC(l_netdrv_debug)},
  637. { "on",ROREG_FUNC(l_netdrv_on)},
  638. #ifdef LUAT_USE_MREPORT
  639. { "mreport", ROREG_FUNC(l_mreport_config)},
  640. #endif
  641. #ifdef LUAT_USE_ICMP
  642. { "ping", ROREG_FUNC(l_icmp_ping)},
  643. #endif
  644. //@const CH390 number 南京沁恒CH390系列,支持CH390D/CH390H, SPI通信
  645. { "CH390", ROREG_INT(LUAT_NETDRV_IMPL_CH390H)},
  646. { "UART", ROREG_INT(LUAT_NETDRV_IMPL_UART)}, // UART形式的网卡, 不带MAC, 直接IP包
  647. #ifdef LUAT_USE_NETDRV_WG
  648. { "WG", ROREG_INT(LUAT_NETDRV_IMPL_WG)}, // Wireguard VPN网卡
  649. #endif
  650. //@const WHALE number 虚拟网卡
  651. { "WHALE", ROREG_INT(LUAT_NETDRV_IMPL_WHALE)}, // 通用WHALE设备
  652. #ifdef LUAT_USE_NETDRV_OPENVPN
  653. { "OPENVPN", ROREG_INT(LUAT_NETDRV_IMPL_OPENVPN)}, // OpenVPN虚拟网卡
  654. #endif
  655. //@const CTRL_RESET number 控制类型-复位,当前仅支持CH390H
  656. { "CTRL_RESET", ROREG_INT(LUAT_NETDRV_CTRL_RESET)},
  657. //@const CTRL_UPDOWN number 控制类型-1=启动UP,0关闭DOWN
  658. { "CTRL_UPDOWN", ROREG_INT(LUAT_NETDRV_CTRL_UPDOWN)},
  659. //@const RESET_HARD number 请求对网卡硬复位,当前仅支持CH390H
  660. { "RESET_HARD", ROREG_INT(0x101)},
  661. //@const RESET_SOFT number 请求对网卡软复位,当前仅支持CH390H
  662. { "RESET_SOFT", ROREG_INT(0x102)},
  663. //@const EVT_SOCKET number 事件类型-socket事件
  664. { "EVT_SOCKET", ROREG_INT(1)}, // socket事件
  665. { NULL, ROREG_INT(0) }
  666. };
  667. LUAMOD_API int luaopen_netdrv( lua_State *L ) {
  668. luat_newlib2(L, reg_netdrv);
  669. return 1;
  670. }