restful_utils.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdbool.h>
  19. #include <stdio.h>
  20. #include "native_interface.h"
  21. #include "shared_utils.h"
  22. /* Serialization of request and response message
  23. *
  24. * Choices:
  25. * We considered a few options:
  26. * 1. coap
  27. * 2. flatbuffer
  28. * 3. cbor
  29. * 4. attr-containers of our own
  30. * 5. customized serialization for request/response
  31. *
  32. * Now we choose the #5 mainly because we need to quickly get the URL for dispatching
  33. * and sometimes we want to change the URL in the original packet. the request format:
  34. * fixed part: version: (1 byte), code (1 byte), fmt(2 byte), mid (4 bytes), sender_id(4 bytes), url_len(2 bytes), payload_len(4bytes)
  35. * dynamic part: url (bytes in url_len), payload
  36. *
  37. * response format:
  38. * fixed part: (1 byte), code (1 byte), fmt(2 byte), mid (4 bytes), sender_id(4 bytes), payload_len(4bytes)
  39. * dynamic part: payload
  40. */
  41. #define REQUES_PACKET_VER 1
  42. #define REQUEST_PACKET_FIX_PART_LEN 18
  43. #define REQUEST_PACKET_URL_OFFSET REQUEST_PACKET_FIX_PART_LEN
  44. #define REQUEST_PACKET_URL_LEN *((uint16*)( (char*) buffer + 12))) //!!! to ensure little endian
  45. #define REQUEST_PACKET_PAYLOAD_LEN *((uint32*)( (char*) buffer + 14))) //!!! to ensure little endian
  46. #define REQUEST_PACKET_URL(buffer) ((char*) buffer + REQUEST_PACKET_URL_OFFSET)
  47. #define REQUEST_PACKET_PAYLOAD(buffer) ((char*) buffer + REQUEST_PACKET_URL_OFFSET + REQUEST_PACKET_URL_LEN(buffer))
  48. #define RESPONSE_PACKET_FIX_PART_LEN 16
  49. char * pack_request(request_t *request, int * size)
  50. {
  51. int url_len = strlen(request->url) + 1;
  52. int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len;
  53. char * packet = (char*) wa_malloc(len);
  54. if (packet == NULL)
  55. return NULL;
  56. // TODO: ensure little endian for words and dwords
  57. *packet = REQUES_PACKET_VER;
  58. *((uint8*) (packet + 1)) = request->action;
  59. *((uint16*) (packet + 2)) = htons(request->fmt);
  60. *((uint32*) (packet + 4)) = htonl(request->mid);
  61. *((uint32*) (packet + 8)) = htonl(request->sender);
  62. *((uint16*) (packet + 12)) = htons(url_len);
  63. *((uint32*) (packet + 14)) = htonl(request->payload_len);
  64. strcpy(packet + REQUEST_PACKET_URL_OFFSET, request->url);
  65. memcpy(packet + REQUEST_PACKET_URL_OFFSET + url_len, request->payload,
  66. request->payload_len);
  67. *size = len;
  68. return packet;
  69. }
  70. void free_req_resp_packet(char * packet)
  71. {
  72. wa_free(packet);
  73. }
  74. request_t * unpack_request(char * packet, int size, request_t * request)
  75. {
  76. if (*packet != REQUES_PACKET_VER) {
  77. printf("version fail\n");
  78. return NULL;
  79. }
  80. if (size < REQUEST_PACKET_FIX_PART_LEN) {
  81. printf("size error: %d\n", size);
  82. return NULL;
  83. }
  84. uint16 url_len = ntohs(*((uint16*) (packet + 12)));
  85. uint32 payload_len = ntohl(*((uint32*) (packet + 14)));
  86. if (size != ( REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
  87. printf("size error: %d, expect: %d\n", size,
  88. REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len);
  89. return NULL;
  90. }
  91. if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) {
  92. printf("url not end with 0\n");
  93. return NULL;
  94. }
  95. request->action = *((uint8*) (packet + 1));
  96. request->fmt = ntohs(*((uint16*) (packet + 2)));
  97. request->mid = ntohl(*((uint32*) (packet + 4)));
  98. request->sender = ntohl(*((uint32*) (packet + 8)));
  99. request->payload_len = payload_len;
  100. request->url = REQUEST_PACKET_URL(packet);
  101. if (payload_len > 0)
  102. request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len;
  103. else
  104. request->payload = NULL;
  105. return request;
  106. }
  107. char * pack_response(response_t *response, int * size)
  108. {
  109. int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len;
  110. char * packet = (char*) wa_malloc(len);
  111. if (packet == NULL)
  112. return NULL;
  113. // TODO: ensure little endian for words and dwords
  114. *packet = REQUES_PACKET_VER;
  115. *((uint8*) (packet + 1)) = response->status;
  116. *((uint16*) (packet + 2)) = htons(response->fmt);
  117. *((uint32*) (packet + 4)) = htonl(response->mid);
  118. *((uint32*) (packet + 8)) = htonl(response->reciever);
  119. *((uint32*) (packet + 12)) = htonl(response->payload_len);
  120. memcpy(packet + RESPONSE_PACKET_FIX_PART_LEN, response->payload,
  121. response->payload_len);
  122. *size = len;
  123. return packet;
  124. }
  125. response_t * unpack_response(char * packet, int size, response_t * response)
  126. {
  127. if (*packet != REQUES_PACKET_VER)
  128. return NULL;
  129. if (size < RESPONSE_PACKET_FIX_PART_LEN)
  130. return NULL;
  131. uint32 payload_len = ntohl(*((uint32*) (packet + 12)));
  132. if (size != ( RESPONSE_PACKET_FIX_PART_LEN + payload_len))
  133. return NULL;
  134. response->status = *((uint8*) (packet + 1));
  135. response->fmt = ntohs(*((uint16*) (packet + 2)));
  136. response->mid = ntohl(*((uint32*) (packet + 4)));
  137. response->reciever = ntohl(*((uint32*) (packet + 8)));
  138. response->payload_len = payload_len;
  139. if (payload_len > 0)
  140. response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN;
  141. else
  142. response->payload = NULL;
  143. return response;
  144. }
  145. request_t *clone_request(request_t *request)
  146. {
  147. /* deep clone */
  148. request_t *req = (request_t *) wa_malloc(sizeof(request_t));
  149. if (req == NULL)
  150. return NULL;
  151. memset(req, 0, sizeof(*req));
  152. req->action = request->action;
  153. req->fmt = request->fmt;
  154. req->url = wa_strdup(request->url);
  155. req->sender = request->sender;
  156. req->mid = request->mid;
  157. if (req->url == NULL)
  158. goto fail;
  159. req->payload_len = request->payload_len;
  160. if (request->payload_len) {
  161. req->payload = (char *) wa_malloc(request->payload_len);
  162. if (!req->payload)
  163. goto fail;
  164. memcpy(req->payload, request->payload, request->payload_len);
  165. } else {
  166. // when payload_len is 0, the payload may be used for carrying some handle or integer
  167. req->payload = request->payload;
  168. }
  169. return req;
  170. fail: request_cleaner(req);
  171. return NULL;
  172. }
  173. void request_cleaner(request_t *request)
  174. {
  175. if (request->url != NULL)
  176. wa_free(request->url);
  177. if (request->payload != NULL && request->payload_len > 0)
  178. wa_free(request->payload);
  179. wa_free(request);
  180. }
  181. void response_cleaner(response_t * response)
  182. {
  183. if (response->payload != NULL && response->payload_len > 0)
  184. wa_free(response->payload);
  185. wa_free(response);
  186. }
  187. response_t * clone_response(response_t * response)
  188. {
  189. response_t *clone = (response_t *) wa_malloc(sizeof(response_t));
  190. if (clone == NULL)
  191. return NULL;
  192. memset(clone, 0, sizeof(*clone));
  193. clone->fmt = response->fmt;
  194. clone->mid = response->mid;
  195. clone->status = response->status;
  196. clone->reciever = response->reciever;
  197. clone->payload_len = response->payload_len;
  198. if (clone->payload_len) {
  199. clone->payload = (char *) wa_malloc(response->payload_len);
  200. if (!clone->payload)
  201. goto fail;
  202. memcpy(clone->payload, response->payload, response->payload_len);
  203. } else {
  204. // when payload_len is 0, the payload may be used for carrying some handle or integer
  205. clone->payload = response->payload;
  206. }
  207. return clone;
  208. fail: response_cleaner(clone);
  209. return NULL;
  210. }
  211. response_t * set_response(response_t * response, int status, int fmt,
  212. const char *payload, int payload_len)
  213. {
  214. response->payload = (void *)payload;
  215. response->payload_len = payload_len;
  216. response->status = status;
  217. response->fmt = fmt;
  218. return response;
  219. }
  220. response_t * make_response_for_request(request_t * request,
  221. response_t * response)
  222. {
  223. response->mid = request->mid;
  224. response->reciever = request->sender;
  225. return response;
  226. }
  227. request_t * init_request(request_t * request, char *url, int action, int fmt,
  228. void *payload, int payload_len)
  229. {
  230. static unsigned int mid = 0;
  231. request->url = url;
  232. request->action = action;
  233. request->fmt = fmt;
  234. request->payload = payload;
  235. request->payload_len = payload_len;
  236. request->mid = ++mid;
  237. return request;
  238. }
  239. /*
  240. check if the "url" is starting with "leading_str"
  241. return: 0 - not match; >0 - the offset of matched url, include any "/" at the end
  242. notes:
  243. 1. it ensures the leading_str "/abc" can pass "/abc/cde" and "/abc/, but fail "/ab" and "/abcd".
  244. leading_str "/abc/" can pass "/abc"
  245. 2. it omit the '/' at the first char
  246. 3. it ensure the leading_str "/abc" can pass "/abc?cde
  247. */
  248. int check_url_start(const char* url, int url_len, const char * leading_str)
  249. {
  250. int offset = 0;
  251. if (*leading_str == '/')
  252. leading_str++;
  253. if (url_len > 0 && *url == '/') {
  254. url_len--;
  255. url++;
  256. offset++;
  257. }
  258. int len = strlen(leading_str);
  259. if (len == 0)
  260. return 0;
  261. // ensure leading_str not end with "/"
  262. if (leading_str[len - 1] == '/') {
  263. len--;
  264. if (len == 0)
  265. return 0;
  266. }
  267. // equal length
  268. if (url_len == len) {
  269. if (memcmp(url, leading_str, url_len) == 0) {
  270. return (offset + len);
  271. } else {
  272. return 0;
  273. }
  274. }
  275. if (url_len < len)
  276. return 0;
  277. else if (memcmp(url, leading_str, len) != 0)
  278. return 0;
  279. else if (url[len] != '/' && url[len] != '?')
  280. return 0;
  281. else
  282. return (offset + len + 1);
  283. }
  284. // * @pattern:
  285. // * sample 1: /abcd, match /abcd only
  286. // * sample 2: /abcd/ match match "/abcd" and "/abcd/*"
  287. // * sample 3: /abcd*, match any url started with "/abcd"
  288. // * sample 4: /abcd/*, exclude "/abcd"
  289. bool match_url(char * pattern, char * matched)
  290. {
  291. if (*pattern == '/')
  292. pattern++;
  293. if (*matched == '/')
  294. matched++;
  295. int matched_len = strlen(matched);
  296. if (matched_len == 0)
  297. return false;
  298. if (matched[matched_len - 1] == '/') {
  299. matched_len--;
  300. if (matched_len == 0)
  301. return false;
  302. }
  303. int len = strlen(pattern);
  304. if (len == 0)
  305. return false;
  306. if (pattern[len - 1] == '/') {
  307. len--;
  308. if (strncmp(pattern, matched, len) != 0)
  309. return false;
  310. if (len == matched_len)
  311. return true;
  312. if (matched_len > len && matched[len] == '/')
  313. return true;
  314. return false;
  315. } else if (pattern[len - 1] == '*') {
  316. if (pattern[len - 2] == '/') {
  317. if (strncmp(pattern, matched, len - 1) == 0)
  318. return true;
  319. else
  320. return false;
  321. } else {
  322. return (strncmp(pattern, matched, len - 1) == 0);
  323. }
  324. } else {
  325. return (strcmp(pattern, matched) == 0);
  326. }
  327. }
  328. /*
  329. * get the value of the key from following format buffer:
  330. * key1=value1;key2=value2;key3=value3
  331. */
  332. char * find_key_value(char * buffer, int buffer_len, char * key, char * value,
  333. int value_len, char delimiter)
  334. {
  335. char * p = buffer;
  336. int remaining = buffer_len;
  337. int key_len = strlen(key);
  338. while (*p != 0 && remaining > 0) {
  339. while (*p == ' ' || *p == delimiter) {
  340. p++;
  341. remaining--;
  342. }
  343. if (remaining <= key_len)
  344. return NULL;
  345. // find the key
  346. if (0 == strncmp(p, key, key_len) && p[key_len] == '=') {
  347. p += (key_len + 1);
  348. remaining -= (key_len + 1);
  349. char * v = value;
  350. memset(value, 0, value_len);
  351. value_len--; // ensure last char is 0
  352. while (*p != delimiter && remaining > 0 && value_len > 0) {
  353. *v++ = *p++;
  354. remaining--;
  355. value_len--;
  356. }
  357. return value;
  358. }
  359. // goto next key
  360. while (*p != delimiter && remaining > 0) {
  361. p++;
  362. remaining--;
  363. }
  364. }
  365. return NULL;
  366. }