ota_lib.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * Tencent is pleased to support the open source community by making IoT Hub
  3. available.
  4. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  5. * Licensed under the MIT License (the "License"); you may not use this file
  6. except in
  7. * compliance with the License. You may obtain a copy of the License at
  8. * http://opensource.org/licenses/MIT
  9. * Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is
  11. * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  12. KIND,
  13. * either express or implied. See the License for the specific language
  14. governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21. #include "ota_lib.h"
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include "lite-utils.h"
  25. #include "ota_client.h"
  26. #include "qcloud_iot_export.h"
  27. #include "qcloud_iot_import.h"
  28. #include "utils_md5.h"
  29. /* Get the specific @key value, and copy to @dest */
  30. /* 0, successful; -1, failed */
  31. static int _qcloud_otalib_get_firmware_fixlen_para(const char *json_doc, const char *key, char *dest, size_t dest_len)
  32. {
  33. IOT_FUNC_ENTRY;
  34. int ret = QCLOUD_RET_SUCCESS;
  35. char *key_bak = HAL_Malloc(strlen(key) + 1);
  36. if (key_bak == NULL) {
  37. Log_e("not enough memory for malloc key");
  38. ret = IOT_OTA_ERR_FAIL;
  39. IOT_FUNC_EXIT_RC(ret);
  40. }
  41. char *json_doc_bak = HAL_Malloc(strlen(json_doc) + 1);
  42. if (json_doc_bak == NULL) {
  43. Log_e("not enough memory for malloc json");
  44. HAL_Free(key_bak);
  45. ret = IOT_OTA_ERR_FAIL;
  46. IOT_FUNC_EXIT_RC(ret);
  47. }
  48. strcpy(key_bak, key);
  49. strcpy(json_doc_bak, json_doc);
  50. char *value = LITE_json_value_of(key_bak, json_doc_bak);
  51. if (value == NULL) {
  52. Log_e("Not '%s' key in json doc of OTA", key);
  53. ret = IOT_OTA_ERR_FAIL;
  54. } else {
  55. uint32_t val_len = strlen(value);
  56. if (val_len > dest_len) {
  57. Log_e("value length of the key is too long");
  58. ret = IOT_OTA_ERR_FAIL;
  59. } else {
  60. memcpy(dest, value, val_len);
  61. ret = QCLOUD_RET_SUCCESS;
  62. }
  63. HAL_Free(value);
  64. }
  65. if (key_bak != NULL) {
  66. HAL_Free(key_bak);
  67. }
  68. if (json_doc_bak != NULL) {
  69. HAL_Free(json_doc_bak);
  70. }
  71. IOT_FUNC_EXIT_RC(ret);
  72. }
  73. /* Get variant length parameter of firmware, and copy to @dest */
  74. /* 0, successful; -1, failed */
  75. static int _qcloud_otalib_get_firmware_varlen_para(const char *json_doc, const char *key, char **dest)
  76. {
  77. #define OTA_FIRMWARE_JSON_VALUE_MAX_LENGTH (64)
  78. IOT_FUNC_ENTRY;
  79. int ret = QCLOUD_RET_SUCCESS;
  80. char *key_bak = HAL_Malloc(strlen(key) + 1);
  81. if (key_bak == NULL) {
  82. Log_e("not enough memory for malloc key");
  83. ret = IOT_OTA_ERR_FAIL;
  84. IOT_FUNC_EXIT_RC(ret);
  85. }
  86. char *json_doc_bak = HAL_Malloc(strlen(json_doc) + 1);
  87. if (json_doc_bak == NULL) {
  88. Log_e("not enough memory for malloc json");
  89. HAL_Free(key_bak);
  90. ret = IOT_OTA_ERR_FAIL;
  91. IOT_FUNC_EXIT_RC(ret);
  92. }
  93. strcpy(key_bak, key);
  94. strcpy(json_doc_bak, json_doc);
  95. *dest = LITE_json_value_of(key_bak, json_doc_bak);
  96. if (*dest == NULL) {
  97. Log_e("Not '%s' key in json '%s' doc of OTA", key_bak, json_doc_bak);
  98. ret = IOT_OTA_ERR_FAIL;
  99. }
  100. if (key_bak != NULL) {
  101. HAL_Free(key_bak);
  102. }
  103. if (json_doc_bak != NULL) {
  104. HAL_Free(json_doc_bak);
  105. }
  106. IOT_FUNC_EXIT_RC(ret);
  107. #undef OTA_FIRMWARE_JSON_VALUE_MAX_LENGTH
  108. }
  109. void *qcloud_otalib_md5_init(void)
  110. {
  111. iot_md5_context *ctx = HAL_Malloc(sizeof(iot_md5_context));
  112. if (NULL == ctx) {
  113. return NULL;
  114. }
  115. utils_md5_init(ctx);
  116. utils_md5_starts(ctx);
  117. return ctx;
  118. }
  119. void qcloud_otalib_md5_update(void *md5, const char *buf, size_t buf_len)
  120. {
  121. utils_md5_update(md5, (unsigned char *)buf, buf_len);
  122. }
  123. void qcloud_otalib_md5_finalize(void *md5, char *output_str)
  124. {
  125. int i;
  126. unsigned char buf_out[16];
  127. utils_md5_finish(md5, buf_out);
  128. for (i = 0; i < 16; ++i) {
  129. output_str[i * 2] = utils_hb2hex(buf_out[i] >> 4);
  130. output_str[i * 2 + 1] = utils_hb2hex(buf_out[i]);
  131. }
  132. output_str[32] = '\0';
  133. }
  134. void qcloud_otalib_md5_deinit(void *md5)
  135. {
  136. if (NULL != md5) {
  137. HAL_Free(md5);
  138. }
  139. }
  140. int qcloud_otalib_get_firmware_type(const char *json, char **type)
  141. {
  142. return _qcloud_otalib_get_firmware_varlen_para(json, TYPE_FIELD, type);
  143. }
  144. int qcloud_otalib_get_report_version_result(const char *json)
  145. {
  146. IOT_FUNC_ENTRY;
  147. char *result_code = NULL;
  148. int rc = _qcloud_otalib_get_firmware_varlen_para(json, RESULT_FIELD, &result_code);
  149. if (rc != QCLOUD_RET_SUCCESS || strcmp(result_code, "0") != 0) {
  150. if (NULL != result_code)
  151. HAL_Free(result_code);
  152. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  153. }
  154. if (NULL != result_code)
  155. HAL_Free(result_code);
  156. IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
  157. }
  158. int qcloud_otalib_get_params(const char *json, char **type, char **url, char **version, char *md5, uint32_t *fileSize)
  159. {
  160. #define OTA_FILESIZE_STR_LEN (16)
  161. IOT_FUNC_ENTRY;
  162. char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0};
  163. /* get type */
  164. if (0 != _qcloud_otalib_get_firmware_varlen_para(json, TYPE_FIELD, type)) {
  165. Log_e("get value of type key failed");
  166. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  167. }
  168. /* get version */
  169. if (0 != _qcloud_otalib_get_firmware_varlen_para(json, VERSION_FIELD, version)) {
  170. Log_e("get value of version key failed");
  171. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  172. }
  173. /* get URL */
  174. if (0 != _qcloud_otalib_get_firmware_varlen_para(json, URL_FIELD, url)) {
  175. Log_e("get value of url key failed");
  176. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  177. }
  178. /* get md5 */
  179. if (0 != _qcloud_otalib_get_firmware_fixlen_para(json, MD5_FIELD, md5, 32)) {
  180. Log_e("get value of md5 key failed");
  181. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  182. }
  183. /* get file size */
  184. if (0 != _qcloud_otalib_get_firmware_fixlen_para(json, FILESIZE_FIELD, file_size_str, OTA_FILESIZE_STR_LEN)) {
  185. Log_e("get value of size key failed");
  186. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  187. }
  188. file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
  189. *fileSize = atoi(file_size_str);
  190. IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
  191. #undef OTA_FILESIZE_STR_LEN
  192. }
  193. int qcloud_otalib_gen_info_msg(char *buf, size_t bufLen, uint32_t id, const char *version)
  194. {
  195. IOT_FUNC_ENTRY;
  196. int ret;
  197. ret = HAL_Snprintf(buf, bufLen, "{\"type\": \"report_version\", \"report\":{\"version\":\"%s\"}}", version);
  198. if (ret < 0) {
  199. Log_e("HAL_Snprintf failed");
  200. IOT_FUNC_EXIT_RC(QCLOUD_ERR_FAILURE);
  201. }
  202. IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
  203. }
  204. int qcloud_otalib_gen_report_msg(char *buf, size_t bufLen, uint32_t id, const char *version, int progress,
  205. IOT_OTAReportType reportType)
  206. {
  207. IOT_FUNC_ENTRY;
  208. int ret;
  209. switch (reportType) {
  210. /* report OTA download begin */
  211. case IOT_OTAR_DOWNLOAD_BEGIN:
  212. ret = HAL_Snprintf(buf, bufLen,
  213. "{\"type\": \"report_progress\", \"report\": "
  214. "{\"progress\": {\"state\":\"downloading\", "
  215. "\"percent\":\"0\", \"result_code\":\"0\", "
  216. "\"result_msg\":\"\"}, \"version\": \"%s\"}}",
  217. version);
  218. break;
  219. /* report OTA download progress */
  220. case IOT_OTAR_DOWNLOADING:
  221. ret = HAL_Snprintf(buf, bufLen,
  222. "{\"type\": \"report_progress\", \"report\": "
  223. "{\"progress\": {\"state\":\"downloading\", "
  224. "\"percent\":\"%d\", \"result_code\":\"0\", "
  225. "\"result_msg\":\"\"}, \"version\": \"%s\"}}",
  226. progress, version);
  227. break;
  228. case IOT_OTAR_DOWNLOAD_TIMEOUT:
  229. case IOT_OTAR_FILE_NOT_EXIST:
  230. case IOT_OTAR_MD5_NOT_MATCH:
  231. case IOT_OTAR_AUTH_FAIL:
  232. case IOT_OTAR_UPGRADE_FAIL:
  233. ret = HAL_Snprintf(buf, bufLen,
  234. "{\"type\": \"report_progress\", \"report\": "
  235. "{\"progress\": {\"state\":\"fail\", "
  236. "\"result_code\":\"%d\", \"result_msg\":\"time_out\"}, "
  237. "\"version\": \"%s\"}}",
  238. reportType, version);
  239. break;
  240. /* report OTA upgrade begin */
  241. case IOT_OTAR_UPGRADE_BEGIN:
  242. ret = HAL_Snprintf(buf, bufLen,
  243. "{\"type\": \"report_progress\", "
  244. "\"report\":{\"progress\":{\"state\":"
  245. "\"burning\", \"result_code\":\"0\", "
  246. "\"result_msg\":\"\"}, \"version\":\"%s\"}}",
  247. version);
  248. break;
  249. /* report OTA upgrade finish */
  250. case IOT_OTAR_UPGRADE_SUCCESS:
  251. ret = HAL_Snprintf(buf, bufLen,
  252. "{\"type\": \"report_progress\", "
  253. "\"report\":{\"progress\":{\"state\":"
  254. "\"done\", \"result_code\":\"0\", "
  255. "\"result_msg\":\"\"}, \"version\":\"%s\"}}",
  256. version);
  257. break;
  258. default:
  259. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  260. break;
  261. }
  262. if (ret < 0) {
  263. Log_e("HAL_Snprintf failed");
  264. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_FAIL);
  265. } else if (ret >= bufLen) {
  266. Log_e("msg is too long");
  267. IOT_FUNC_EXIT_RC(IOT_OTA_ERR_STR_TOO_LONG);
  268. }
  269. IOT_FUNC_EXIT_RC(QCLOUD_RET_SUCCESS);
  270. }
  271. #ifdef __cplusplus
  272. }
  273. #endif