gagent_httpc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /*
  2. * File : gagent_httpc.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2018, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2018-01-03 flyingcys first version
  23. */
  24. #include "gagent_def.h"
  25. #include "aes.h"
  26. #define MAX_HTTPC_URL_LEN 1024
  27. #define MAX_HTTPC_RECV_LEN 2048
  28. struct cloud_httpc
  29. {
  30. char *recv_buf;
  31. int recv_len;
  32. };
  33. static struct cloud_httpc httpc;
  34. typedef int (*WEBCLIENT_CUSTOM_RESPONSE_CB)(size_t total, size_t offset, char *from, size_t from_len);
  35. static int webclient_common(int method, const char *URI,
  36. const char * data, size_t data_sz,
  37. WEBCLIENT_CUSTOM_RESPONSE_CB webclient_custom_response_cb)
  38. {
  39. struct webclient_session *session = RT_NULL;
  40. char *header = RT_NULL, *header_ptr;
  41. size_t header_sz = 0;
  42. int rc = WEBCLIENT_OK;
  43. int length = 0;
  44. size_t total = 0, offset = 0;
  45. rt_uint8_t *buffer = RT_NULL;
  46. header = (char *)rt_malloc(WEBCLIENT_HEADER_BUFSZ);
  47. if(RT_NULL == header)
  48. {
  49. gagent_err("malloc failed!\n");
  50. rc = -WEBCLIENT_NOMEM;
  51. goto __exit;
  52. }
  53. rt_memset(header, 0, WEBCLIENT_HEADER_BUFSZ);
  54. header_ptr = header;
  55. header_ptr += rt_snprintf(header_ptr,
  56. WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  57. "Content-Type: application/x-www-form-urlencoded;charset:UTF-8\r\n");
  58. if(data)
  59. {
  60. header_ptr += rt_snprintf(header_ptr,
  61. WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  62. "Content-Length:%d\r\n", strlen(data));
  63. }
  64. header_sz = header_ptr - header;
  65. session = webclient_open_custom(URI, method, header, header_sz, data, data_sz);
  66. if(RT_NULL == session)
  67. {
  68. gagent_err("webclient_open_custom failed!\n");
  69. rc = -WEBCLIENT_OK;
  70. goto __exit;
  71. }
  72. gagent_dbg("response:%d\n",session->response);
  73. buffer = (rt_uint8_t *)rt_malloc(WEBCLIENT_RESPONSE_BUFSZ);
  74. if(RT_NULL == buffer)
  75. {
  76. gagent_err("malloc failed!\n");
  77. rc = -WEBCLIENT_NOMEM;
  78. goto __exit;
  79. }
  80. if(session->chunk_sz > 0)
  81. {
  82. gagent_dbg("chunk_sz:%d\n", session->chunk_sz);
  83. total = session->chunk_sz;
  84. }
  85. else if(session->content_length > 0)
  86. {
  87. gagent_dbg("content_length:%d content_length_remainder:%d\n", session->content_length, session->content_length_remainder);
  88. total = session->content_length;
  89. }
  90. while(total != offset)
  91. {
  92. memset(buffer, 0, WEBCLIENT_RESPONSE_BUFSZ);
  93. length = webclient_read(session, buffer, WEBCLIENT_RESPONSE_BUFSZ);
  94. if(length <= 0)
  95. {
  96. rc = length;
  97. break;
  98. }
  99. if(webclient_custom_response_cb)
  100. webclient_custom_response_cb(total, offset, (char *)buffer, (int)length);
  101. offset += length;
  102. }
  103. __exit:
  104. if(RT_NULL != buffer)
  105. {
  106. rt_free(buffer);
  107. buffer = RT_NULL;
  108. }
  109. if(RT_NULL != header)
  110. {
  111. rt_free(header);
  112. header = RT_NULL;
  113. }
  114. if(RT_NULL != session)
  115. {
  116. webclient_close(session);
  117. session = RT_NULL;
  118. }
  119. return rc;
  120. }
  121. int webclient_get(const char *URI, WEBCLIENT_CUSTOM_RESPONSE_CB webclient_custom_response_cb)
  122. {
  123. return webclient_common(WEBCLIENT_GET, URI, NULL, 0, webclient_custom_response_cb);
  124. }
  125. int webclient_post(const char *URI, const char * data, size_t data_sz,
  126. WEBCLIENT_CUSTOM_RESPONSE_CB webclient_custom_response_cb)
  127. {
  128. return webclient_common(WEBCLIENT_POST, URI, data, data_sz, webclient_custom_response_cb);
  129. }
  130. int gagent_cloud_httpc_cb(size_t total, size_t offset, char *from, size_t from_len)
  131. {
  132. extern cloud_st *cloud;
  133. gagent_dbg("total:%d offset:%d len:%d\n", total, offset, from_len);
  134. gagent_dbg("buf:%s\n", from);
  135. rt_memset(httpc.recv_buf, 0, MAX_HTTPC_RECV_LEN);
  136. rt_memcpy(httpc.recv_buf, from, from_len);
  137. httpc.recv_len = from_len;
  138. return RT_EOK;
  139. }
  140. int gagent_cloud_register(cloud_st *cloud)
  141. {
  142. int rc = RT_EOK;
  143. int content_len, aes_len, i;
  144. //
  145. char *content = RT_NULL;
  146. char *url = RT_NULL;
  147. char *ptr = RT_NULL;
  148. uint8_t aes_key[16];
  149. char *aes_buf = RT_NULL;
  150. aes_context *aes_ctx = RT_NULL;
  151. content = (char *)rt_malloc(256);
  152. if(RT_NULL == content)
  153. {
  154. gagent_err("malloc faield!\n");
  155. rc = -RT_ENOMEM;
  156. goto __exit;
  157. }
  158. aes_buf = (char *)rt_malloc(256);
  159. if(RT_NULL == aes_buf)
  160. {
  161. rc = -RT_ENOMEM;
  162. goto __exit;
  163. }
  164. //data
  165. rt_memset(content, 0, 256);
  166. rt_snprintf((char *)content, 256, "mac=%02x%02x%02x%02x%02x%02x&passcode=%s&type=%s", \
  167. cloud->con->mac[0], cloud->con->mac[1], cloud->con->mac[2], cloud->con->mac[3], cloud->con->mac[4], cloud->con->mac[5], \
  168. cloud->con->passcode, "normal");
  169. content_len = strlen(content);
  170. rt_memset(aes_key, 0, sizeof(aes_key));
  171. gagent_strtohex((char *)aes_key, cloud->con->pk_secret, strlen(cloud->con->pk_secret) > 32 ? 32 : strlen(cloud->con->pk_secret));
  172. gagent_dbg("content:%s, pk_secret:%s\n", content, cloud->con->pk_secret);
  173. aes_ctx = (aes_context *)rt_malloc(sizeof(aes_context));
  174. if(RT_NULL == aes_ctx)
  175. {
  176. rc = -RT_ENOMEM;
  177. goto __exit;
  178. }
  179. rt_memset(aes_ctx, 0, sizeof(aes_context));
  180. aes_setkey_enc(aes_ctx, aes_key, 128);
  181. //
  182. rt_memset(aes_buf, 0, 256);
  183. content_len = strlen(content);
  184. if(content_len % 16)
  185. content_len = gagent_add_pkcs(content, content_len);
  186. aes_len = 0;
  187. for(i = 0; i < content_len; i += 16)
  188. {
  189. aes_crypt_ecb(aes_ctx, AES_ENCRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
  190. aes_len += 16;
  191. }
  192. ptr = content;
  193. rt_memset(ptr, 0, 256);
  194. strcpy(ptr, "data=");
  195. ptr += strlen("data=");
  196. if(aes_len > 0)
  197. {
  198. for(i = 0; i < aes_len; i ++)
  199. {
  200. ptr += rt_snprintf(ptr, 256 - (ptr - content), "%02x", aes_buf[i]);
  201. }
  202. }
  203. gagent_dbg("content:%s\n", content);
  204. url = (char *)rt_malloc(MAX_HTTPC_URL_LEN);
  205. if(RT_NULL == url)
  206. {
  207. rc = -RT_ENOMEM;
  208. goto __exit;
  209. }
  210. ptr = url;
  211. memset(ptr, 0, MAX_HTTPC_URL_LEN);
  212. //url
  213. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "http://%s:%s", G_SERVICE_DOMAIN, G_SERVICE_PORT);
  214. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "/dev/%s/device", cloud->con->pk);
  215. gagent_dbg("url:%s\n", url);
  216. httpc.recv_buf = RT_NULL;
  217. httpc.recv_buf = (char *)rt_malloc(MAX_HTTPC_RECV_LEN);
  218. if(RT_NULL == httpc.recv_buf)
  219. {
  220. rc = -RT_ENOMEM;
  221. goto __exit;
  222. }
  223. rc = webclient_post((const char *)url, (const char *)content, strlen(content), gagent_cloud_httpc_cb);
  224. if(rc != RT_EOK)
  225. {
  226. gagent_err("weblient_post failed!\n");
  227. goto __exit;
  228. }
  229. //
  230. rt_memset(content, 0, 256);
  231. aes_len = gagent_strtohex((char *)content, (char *)httpc.recv_buf, httpc.recv_len);
  232. rt_memset(aes_ctx, 0, sizeof(aes_context));
  233. aes_setkey_dec(aes_ctx, aes_key, 128);
  234. rt_memset(aes_buf, 0, 256);
  235. for(i = 0; i < aes_len; i += 16)
  236. aes_crypt_ecb(aes_ctx, AES_DECRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
  237. gagent_dbg("%s\n", aes_buf);
  238. if(strstr(aes_buf, "did=") != NULL)
  239. rt_memcpy(cloud->con->did, aes_buf + strlen("did="), DID_LENGTH);
  240. __exit:
  241. if(RT_NULL != httpc.recv_buf)
  242. {
  243. rt_free(httpc.recv_buf);
  244. httpc.recv_buf = RT_NULL;
  245. }
  246. if(RT_NULL != url)
  247. {
  248. rt_free(url);
  249. url = RT_NULL;
  250. }
  251. if(RT_NULL != aes_ctx)
  252. {
  253. rt_free(aes_ctx);
  254. aes_ctx = RT_NULL;
  255. }
  256. if(RT_NULL != aes_buf)
  257. {
  258. rt_free(aes_buf);
  259. aes_buf = RT_NULL;
  260. }
  261. if(RT_NULL != content)
  262. {
  263. rt_free(content);
  264. content = RT_NULL;
  265. }
  266. return rc;
  267. }
  268. int gagent_cloud_provision(cloud_st *cloud)
  269. {
  270. int rc = RT_EOK;
  271. int content_len, aes_len, i;
  272. char *url = RT_NULL;
  273. char *content = RT_NULL;
  274. char *ptr = RT_NULL;
  275. char *ptr_tail = RT_NULL;
  276. char aes_key[16];
  277. char *aes_buf = RT_NULL;
  278. aes_context *aes_ctx = RT_NULL;
  279. content = (char *)rt_malloc(256);
  280. if(RT_NULL == content)
  281. {
  282. rc = -RT_ENOMEM;
  283. goto __exit;
  284. }
  285. aes_buf = (char *)rt_malloc(256);
  286. if(RT_NULL == aes_buf)
  287. {
  288. rc = -RT_ENOMEM;
  289. goto __exit;
  290. }
  291. //data
  292. rt_memset(content, 0, 256);
  293. strcpy(content, cloud->con->did);
  294. rt_memset(aes_key, 0, sizeof(aes_key));
  295. gagent_strtohex((char *)aes_key, cloud->con->pk_secret, strlen(cloud->con->pk_secret) > 32 ? 32 : strlen(cloud->con->pk_secret));
  296. gagent_dbg("content:%s, pk_secret:%s\n", content, cloud->con->pk_secret);
  297. aes_ctx = (aes_context *)rt_malloc(sizeof(aes_context));
  298. if(RT_NULL == aes_ctx)
  299. {
  300. rc = -RT_ENOMEM;
  301. goto __exit;
  302. }
  303. rt_memset(aes_ctx, 0, sizeof(aes_context));
  304. aes_setkey_enc(aes_ctx, (uint8_t *)aes_key, 128);
  305. //
  306. rt_memset(aes_buf, 0, 256);
  307. content_len = strlen(content);
  308. if(content_len % 16)
  309. content_len = gagent_add_pkcs(content, content_len);
  310. aes_len = 0;
  311. for(i = 0; i < content_len; i += 16)
  312. {
  313. aes_crypt_ecb(aes_ctx, AES_ENCRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
  314. aes_len += 16;
  315. }
  316. ptr = content;
  317. if(aes_len > 0)
  318. {
  319. for(i = 0; i < aes_len; i ++)
  320. {
  321. ptr += rt_snprintf(ptr, 256 - (ptr - content), "%02x", aes_buf[i]);
  322. }
  323. }
  324. gagent_dbg("content:%s\n", content);
  325. url = (char *)rt_malloc(MAX_HTTPC_URL_LEN);
  326. if(RT_NULL == url)
  327. {
  328. rc = -RT_ENOMEM;
  329. return rc;
  330. }
  331. ptr = url;
  332. rt_memset(url, 0, MAX_HTTPC_URL_LEN);
  333. //url
  334. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "http://%s:%s", G_SERVICE_DOMAIN, G_SERVICE_PORT);
  335. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "/dev/%s/device?", cloud->con->pk);
  336. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "did=%s", content);
  337. gagent_dbg("url:%s\n", url);
  338. //
  339. rt_memset(cloud->mqtt_server, 0, sizeof(cloud->mqtt_server));
  340. rt_memcpy(cloud->mqtt_server, G_M2M_DOMAIN, sizeof(G_M2M_DOMAIN));
  341. //
  342. cloud->mqtt_port = 0;
  343. cloud->mqtt_port = atoi(G_M2M_PORT);
  344. httpc.recv_buf = RT_NULL;
  345. httpc.recv_buf = (char *)rt_malloc(MAX_HTTPC_RECV_LEN);
  346. if(RT_NULL == httpc.recv_buf)
  347. {
  348. rc = -RT_ENOMEM;
  349. goto __exit;
  350. }
  351. rc = webclient_get((const char *)url, gagent_cloud_httpc_cb);
  352. if(rc != RT_EOK)
  353. {
  354. rt_kprintf("weblient_post failed!\n");
  355. goto __exit;
  356. }
  357. rt_memset(content, 0, 256);
  358. aes_len = gagent_strtohex(content, httpc.recv_buf, httpc.recv_len);
  359. rt_memset(aes_ctx, 0, sizeof(aes_context));
  360. aes_setkey_dec(aes_ctx, (uint8_t *)aes_key, 128);
  361. rt_memset(aes_buf, 0, 256);
  362. for(i = 0; i < aes_len; i += 16)
  363. aes_crypt_ecb(aes_ctx, AES_DECRYPT, (uint8_t *)content + i, (uint8_t *)aes_buf + i);
  364. gagent_dbg("%s\n", aes_buf);
  365. //mqtt_server
  366. ptr = strstr(aes_buf, "host=");
  367. if(ptr > 0)
  368. {
  369. ptr += strlen("host=");
  370. ptr_tail = strchr(ptr, '&');
  371. if(ptr_tail > 0)
  372. {
  373. rt_memset(cloud->mqtt_server, 0, sizeof(cloud->mqtt_server));
  374. rt_memcpy(cloud->mqtt_server, ptr, (ptr_tail - ptr));
  375. }
  376. }
  377. //mqtt_port
  378. ptr = strstr(aes_buf, "port=");
  379. if(ptr > 0)
  380. {
  381. ptr += strlen("port=");
  382. ptr_tail = strchr(ptr, '&');
  383. if(ptr_tail > 0)
  384. {
  385. *ptr_tail = '\0';
  386. cloud->mqtt_port = 0;
  387. cloud->mqtt_port = atoi(ptr);
  388. }
  389. }
  390. gagent_dbg("mqtt_server:%s port:%d\n", cloud->mqtt_server, cloud->mqtt_port);
  391. __exit:
  392. if(RT_NULL != httpc.recv_buf)
  393. {
  394. rt_free(httpc.recv_buf);
  395. httpc.recv_buf = RT_NULL;
  396. }
  397. if(RT_NULL != url)
  398. {
  399. rt_free(url);
  400. url = RT_NULL;
  401. }
  402. if(RT_NULL != aes_ctx)
  403. {
  404. rt_free(aes_ctx);
  405. aes_ctx = RT_NULL;
  406. }
  407. if(RT_NULL != aes_buf)
  408. {
  409. rt_free(aes_buf);
  410. aes_buf = RT_NULL;
  411. }
  412. if(RT_NULL != content)
  413. {
  414. rt_free(content);
  415. content = RT_NULL;
  416. }
  417. return rc;
  418. }
  419. int gagent_cloud_check_ota(cloud_st *cloud)
  420. {
  421. int rc = RT_EOK;
  422. char *url = RT_NULL;
  423. char *content = RT_NULL;
  424. char *ptr = RT_NULL;
  425. content = (char *)rt_malloc(256);
  426. if(RT_NULL == content)
  427. {
  428. gagent_err("malloc faield!\n");
  429. rc = -RT_ENOMEM;
  430. goto __exit;
  431. }
  432. //data
  433. rt_memset(content, 0, 256);
  434. rt_snprintf((char *)content, 256, "passcode=%s&type=%d&hard_version=%s&soft_version=%s", \
  435. cloud->con->passcode, GAGENT_HARD_SOC, cloud->con->hard_version, cloud->con->soft_version);
  436. gagent_dbg("content:%s\n", content);
  437. url = (char *)rt_malloc(MAX_HTTPC_URL_LEN);
  438. if(RT_NULL == url)
  439. {
  440. rc = -RT_ENOMEM;
  441. return rc;
  442. }
  443. ptr = url;
  444. rt_memset(url, 0, MAX_HTTPC_URL_LEN);
  445. //url
  446. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "http://%s:%s", G_SERVICE_DOMAIN, G_SERVICE_PORT);
  447. ptr += rt_snprintf(ptr, MAX_HTTPC_URL_LEN - (ptr - url), "/dev/ota/v4.1/update_and_check/%s", cloud->con->did);
  448. gagent_dbg("url:%s\n", url);
  449. httpc.recv_buf = RT_NULL;
  450. httpc.recv_buf = (char *)rt_malloc(MAX_HTTPC_RECV_LEN);
  451. if(RT_NULL != httpc.recv_buf)
  452. {
  453. rc = -RT_ENOMEM;
  454. goto __exit;
  455. }
  456. rc = webclient_post((const char *)url, (const char *)content, strlen(content), gagent_cloud_httpc_cb);
  457. if(rc != RT_EOK)
  458. {
  459. gagent_err("weblient_post failed!\n");
  460. goto __exit;
  461. }
  462. __exit:
  463. if(RT_NULL != httpc.recv_buf)
  464. rt_free(httpc.recv_buf);
  465. if(RT_NULL != url)
  466. rt_free(url);
  467. if(RT_NULL != content)
  468. rt_free(content);
  469. return rc;
  470. }