luat_lib_libcoap.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. @module socket
  3. @summary socket操作库
  4. @version 1.0
  5. @data 2020.03.30
  6. */
  7. #include "luat_base.h"
  8. #include "luat_timer.h"
  9. #include "luat_malloc.h"
  10. #include "luat_msgbus.h"
  11. #define LUAT_LOG_TAG "luat.libcoap"
  12. #include "luat_log.h"
  13. //---------------------------
  14. #ifndef COAP_OPTION_IF_MATCH
  15. #define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */
  16. #define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */
  17. #define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */
  18. #define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */
  19. #define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */
  20. #define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */
  21. #define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */
  22. #define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */
  23. #define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT
  24. #define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */
  25. #define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */
  26. #define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */
  27. #define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */
  28. #define COAP_OPTION_SIZE2 28 /* E, uint, 0-4 B, (none) */
  29. #define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */
  30. #define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
  31. #define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */
  32. #define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */
  33. #define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */
  34. #define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */
  35. #define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */
  36. #define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */
  37. #define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */
  38. #define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */
  39. #define COAP_MEDIATYPE_APPLICATION_CBOR 60 /* application/cbor */
  40. #endif
  41. //---------------------------
  42. typedef struct libcoap_header
  43. {
  44. unsigned int tokenLen: 4 ;
  45. unsigned int type : 2 ; // 0 - CON, 1 - NON, 2 - ACK, 3 - RST
  46. unsigned int version : 2 ;
  47. uint8_t code;
  48. uint16_t msgid;
  49. }libcoap_header_t;
  50. typedef struct libcoap_opt_header
  51. {
  52. unsigned int opt_len : 4 ;
  53. unsigned int opt_delta : 4 ;
  54. }libcoap_opt_header_t;
  55. typedef struct luat_lib_libcoap
  56. {
  57. libcoap_header_t header;
  58. char token[9];
  59. size_t optSize;
  60. size_t dataSize;
  61. char opt[256];
  62. char data[512 - 128];
  63. }luat_lib_libcoap_t;
  64. static uint16_t c_msgid = 1;
  65. #define LUAT_COAP_HANDLE "COAP*"
  66. //-----------------------------------------------------------------
  67. static void addopt(luat_lib_libcoap_t* _coap, uint8_t opt_type, const char* value, size_t len) {
  68. if (_coap->optSize > 0) { // 检查需要之前的opt
  69. }
  70. int cur_opt = opt_type;
  71. // LLOGD("opt type=%d value len=%d", opt_type, len);
  72. // LLOGD("opt optSize cur=%d", _coap->optSize);
  73. size_t idx = _coap->optSize;
  74. if (len <= 12) {
  75. _coap->opt[idx++] = (cur_opt << 4) + (len & 0xF);
  76. }
  77. else if (len <= 268) {
  78. _coap->opt[idx++] = (cur_opt << 4) + (0x0D);
  79. _coap->opt[idx++] = len - 0x0D;
  80. } else {
  81. LLOGW("coap opt is too large!!! ignore!!!");
  82. return;
  83. }
  84. for (size_t i = 0; i < len; i++)
  85. {
  86. _coap->opt[idx++] = *(value + i);
  87. }
  88. _coap->optSize += idx;
  89. }
  90. // libcoap.new(libcoap.GET, "time", {}, nil)
  91. static int l_libcoap_new(lua_State* L) {
  92. luat_lib_libcoap_t* _coap;
  93. // 生成coap结构体
  94. _coap = (luat_lib_libcoap_t*)lua_newuserdata(L, sizeof(luat_lib_libcoap_t));
  95. if (_coap == NULL)
  96. {
  97. return 0;
  98. }
  99. memset(_coap, 0, sizeof(luat_lib_libcoap_t));
  100. _coap->header.version = 0x01;
  101. _coap->header.tokenLen = 0;
  102. _coap->header.msgid = c_msgid ++; // 设置msgid
  103. luaL_setmetatable(L, LUAT_COAP_HANDLE);
  104. // 然后根据用户参数设置
  105. // 首先,是code, 第1参数
  106. _coap->header.code = luaL_checkinteger(L, 1);
  107. // 肯定要设置URI的吧, 第2参数
  108. size_t len = 0;
  109. const char* uri = luaL_checklstring(L, 2, &len);
  110. addopt(_coap, 11, uri, len); // Uri-Path = 11
  111. // 设置其他OPT, 第3参数
  112. // TODO 是个table吧
  113. // 最后是data, 第4参数
  114. if (lua_isstring(L, 4)) {
  115. const char* payload = luaL_checklstring(L, 4, &len);
  116. if (len > 512) {
  117. LLOGE("data limit to 512 bytes");
  118. lua_pushstring(L, "data limit to 512 bytes");
  119. lua_error(L);
  120. }
  121. _coap->dataSize = len;
  122. memcpy(_coap->data, payload, len);
  123. }
  124. return 1;
  125. }
  126. static int l_libcoap_parse(lua_State* L) {
  127. size_t len;
  128. const char* buff = luaL_checklstring(L, 1, &len);
  129. if (len < 4) {
  130. return 0; // 最起码得有4个字节呀
  131. }
  132. libcoap_header_t *header = (libcoap_header_t *)buff; // 把头部搞一下
  133. if (header->version != 0x01) {
  134. LLOGW("bad coap version");
  135. return 0;
  136. }
  137. luat_lib_libcoap_t* _coap;
  138. // 生成coap结构体
  139. _coap = (luat_lib_libcoap_t*)lua_newuserdata(L, sizeof(luat_lib_libcoap_t));
  140. if (_coap == NULL)
  141. {
  142. LLOGE("out of memory at libcoap.parse");
  143. return 0;
  144. }
  145. memset(_coap, 0, sizeof(luat_lib_libcoap_t));
  146. memcpy(_coap, buff, 4);
  147. luaL_setmetatable(L, LUAT_COAP_HANDLE);
  148. int idx = 4;
  149. // 分析一下token
  150. if (_coap->header.tokenLen > 0) {
  151. memcpy(_coap->token, buff+len, _coap->header.tokenLen);
  152. idx += _coap->header.tokenLen;
  153. }
  154. // 准备一下指针
  155. char* ptr = (char*)buff;
  156. ptr += 4; // 跳过头部
  157. ptr += _coap->header.tokenLen;
  158. // 分析opt
  159. if (idx < len) {
  160. while (idx < len && *ptr != 0xFF) {
  161. libcoap_opt_header_t *opt_header = (libcoap_opt_header_t *)ptr;
  162. if (opt_header->opt_delta == 0xF)
  163. break;
  164. LLOGD("found opt %d %d", opt_header->opt_delta, opt_header->opt_len);
  165. if (opt_header->opt_len <= 12) {
  166. // nop
  167. }
  168. else if (opt_header->opt_len == 13) {
  169. opt_header->opt_len += (unsigned int)(*(ptr+1));
  170. }
  171. ptr += opt_header->opt_len + 1;
  172. idx += opt_header->opt_len + 1;
  173. _coap->optSize += opt_header->opt_len + 1;
  174. }
  175. LLOGD("opt size=%d", _coap->optSize);
  176. memcpy(_coap->opt, ptr - _coap->optSize, _coap->optSize);
  177. }
  178. // 分析一下data
  179. if (idx < len) {
  180. _coap->dataSize = len - idx - 1;
  181. LLOGD("data size=%d", _coap->dataSize);
  182. memcpy(_coap->data, ptr+1, _coap->dataSize);
  183. }
  184. return 1;
  185. }
  186. //---------------------------------------------
  187. #define tocoap(L) ((luat_lib_libcoap_t *)luaL_checkudata(L, 1, LUAT_COAP_HANDLE))
  188. static int libcoap_msgid(lua_State *L) {
  189. luat_lib_libcoap_t *_coap = tocoap(L);
  190. if (_coap == NULL) {
  191. LLOGE("coap sturt is NULL");
  192. lua_pushstring(L, "coap sturt is NULL");
  193. lua_error(L);
  194. return 0;
  195. }
  196. lua_pushinteger(L, _coap->header.msgid);
  197. return 1;
  198. }
  199. static int libcoap_token(lua_State *L) {
  200. luat_lib_libcoap_t *_coap = tocoap(L);
  201. if (_coap == NULL) {
  202. LLOGE("coap sturt is NULL");
  203. lua_pushstring(L, "coap sturt is NULL");
  204. lua_error(L);
  205. return 0;
  206. }
  207. _coap->token[8] = 0x00; // 确保有结束符
  208. lua_pushstring(L, _coap->token);
  209. return 1;
  210. }
  211. static int libcoap_rawdata(lua_State *L) {
  212. luat_lib_libcoap_t *_coap = tocoap(L);
  213. if (_coap == NULL) {
  214. LLOGE("coap sturt is NULL");
  215. lua_pushstring(L, "coap sturt is NULL");
  216. lua_error(L);
  217. return 0;
  218. }
  219. // 开始合成数据吧
  220. size_t len = 0;
  221. char buff[512] = {0}; // 最大长度暂定512
  222. // 首先, 拷贝头部
  223. _coap->header.version = 0x01;
  224. _coap->header.tokenLen = strlen(_coap->token);
  225. memcpy(buff, _coap, 4); // 头部固定4个字节
  226. len += 4;
  227. //LLOGD("libcoap header len=%d", len);
  228. // 有没有token呢?
  229. if (_coap->header.tokenLen > 0) {
  230. memcpy((char*)(buff) + len, _coap->token, _coap->header.tokenLen);
  231. len += _coap->header.tokenLen;
  232. //LLOGD("libcoap add token %ld", _coap->header.tokenLen);
  233. }
  234. // 然后处理opt
  235. if (_coap->optSize > 0) {
  236. memcpy((char*)(buff) + len, _coap->opt, _coap->optSize);
  237. len += _coap->optSize;
  238. //LLOGD("libcoap add opt %ld ,first=%d", _coap->optSize, _coap->opt[0]);
  239. }
  240. // 最后添加data
  241. if (_coap->dataSize > 0) {
  242. buff[len] = 0xFF;
  243. len ++;
  244. memcpy((char*)(buff) + len, _coap->data, _coap->dataSize);
  245. len += _coap->dataSize;
  246. //LLOGD("libcoap add data %ld", _coap->dataSize);
  247. }
  248. lua_pushlstring(L, buff, len);
  249. return 1;
  250. }
  251. static int libcoap_code(lua_State *L) {
  252. luat_lib_libcoap_t *_coap = tocoap(L);
  253. if (_coap == NULL) {
  254. LLOGE("coap sturt is NULL");
  255. lua_pushstring(L, "coap sturt is NULL");
  256. lua_error(L);
  257. return 0;
  258. }
  259. lua_pushinteger(L, _coap->header.code);
  260. return 1;
  261. }
  262. static int libcoap_httpcode(lua_State *L) {
  263. luat_lib_libcoap_t *_coap = tocoap(L);
  264. if (_coap == NULL) {
  265. LLOGE("coap sturt is NULL");
  266. lua_pushstring(L, "coap sturt is NULL");
  267. lua_error(L);
  268. return 0;
  269. }
  270. lua_pushinteger(L, (_coap->header.code >> 5) * 100 + (_coap->header.code & 0xF));
  271. return 1;
  272. }
  273. static int libcoap_type(lua_State *L) {
  274. luat_lib_libcoap_t *_coap = tocoap(L);
  275. if (_coap == NULL) {
  276. LLOGE("coap sturt is NULL");
  277. lua_pushstring(L, "coap sturt is NULL");
  278. lua_error(L);
  279. return 0;
  280. }
  281. lua_pushinteger(L, _coap->header.type);
  282. return 1;
  283. }
  284. static int libcoap_data(lua_State *L) {
  285. luat_lib_libcoap_t *_coap = tocoap(L);
  286. if (_coap == NULL) {
  287. LLOGE("coap sturt is NULL");
  288. lua_pushstring(L, "coap sturt is NULL");
  289. lua_error(L);
  290. return 0;
  291. }
  292. lua_pushlstring(L, _coap->data, _coap->dataSize);
  293. return 1;
  294. }
  295. static const luaL_Reg lib_libcoap[] = {
  296. {"tp", libcoap_type},
  297. {"msgid", libcoap_msgid},
  298. {"token", libcoap_token},
  299. {"code", libcoap_code},
  300. {"hcode", libcoap_httpcode},
  301. {"rawdata", libcoap_rawdata},
  302. {"data", libcoap_data},
  303. //{"__gc", libcoap_gc},
  304. //{"__tostring", libcoap_tostring},
  305. {NULL, NULL}
  306. };
  307. static void createmeta (lua_State *L) {
  308. luaL_newmetatable(L, LUAT_COAP_HANDLE); /* create metatable for file handles */
  309. lua_pushvalue(L, -1); /* push metatable */
  310. lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
  311. luaL_setfuncs(L, lib_libcoap, 0); /* add file methods to new metatable */
  312. lua_pop(L, 1); /* pop new metatable */
  313. }
  314. #include "rotable.h"
  315. #define CODE(H,L) (H << 5 + L)
  316. static const rotable_Reg reg_libcoap[] =
  317. {
  318. { "new", l_libcoap_new, 0},
  319. { "parse", l_libcoap_parse, 0},
  320. // ----- 类型常量
  321. { "CON", NULL, 0},
  322. { "NON", NULL, 1},
  323. { "ACK", NULL, 2},
  324. { "RST", NULL, 3},
  325. // 请求类
  326. { "NONE", NULL, 0},
  327. { "GET", NULL, 1},
  328. { "POST", NULL, 2},
  329. { "PUT", NULL, 3},
  330. { "DELETE", NULL, 4},
  331. // 响应类
  332. // { "Created", NULL, CODE(2,1)},
  333. // { "Deleted", NULL, CODE(2,2)},
  334. // { "Valid", NULL, CODE(2,3)},
  335. // { "Changed", NULL, CODE(2,4)},
  336. // { "Content", NULL, CODE(2,5)},
  337. // { "Bad Request",NULL, CODE(4,0)},
  338. // { "Unauthorized",NULL, CODE(4,1)},
  339. // { "Bad Option", NULL, CODE(4,2)},
  340. // { "Forbidden", NULL, CODE(4,3)},
  341. // { "Not Found", NULL, CODE(4,4)},
  342. // { "Method Not Allowed",NULL, CODE(4,5)},
  343. // { "Not Acceptable", NULL, CODE(4,6)},
  344. // { "Precondition Failed", NULL, CODE(4,12)},
  345. // { "Request Entity Too Large", NULL, CODE(4,13)},
  346. // { "Unsupported Content-Format", NULL, CODE(4,15)},
  347. // { "Internal Server Error", NULL, CODE(5,0)},
  348. // { "Not Implemented", NULL, CODE(5,1)},
  349. // { "Bad Gateway", NULL, CODE(5,2)},
  350. // { "Service Unavailable", NULL, CODE(5,3)},
  351. // { "Gateway Timeout", NULL, CODE(5,4)},
  352. // { "Proxying Not Supported", NULL, CODE(5,5)},
  353. { NULL, NULL , 0}
  354. };
  355. LUAMOD_API int luaopen_libcoap( lua_State *L ) {
  356. rotable_newlib(L, reg_libcoap);
  357. createmeta(L);
  358. return 1;
  359. }