esp_https_ota.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <esp_https_ota.h>
  17. #include <esp_log.h>
  18. #include <esp_ota_ops.h>
  19. #include <errno.h>
  20. #include <sys/param.h>
  21. #define IMAGE_HEADER_SIZE sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t) + 1
  22. #define DEFAULT_OTA_BUF_SIZE IMAGE_HEADER_SIZE
  23. #define DEFAULT_REQUEST_SIZE (64 * 1024)
  24. static const char *TAG = "esp_https_ota";
  25. typedef enum {
  26. ESP_HTTPS_OTA_INIT,
  27. ESP_HTTPS_OTA_BEGIN,
  28. ESP_HTTPS_OTA_IN_PROGRESS,
  29. ESP_HTTPS_OTA_SUCCESS,
  30. } esp_https_ota_state;
  31. struct esp_https_ota_handle {
  32. esp_ota_handle_t update_handle;
  33. const esp_partition_t *update_partition;
  34. esp_http_client_handle_t http_client;
  35. char *ota_upgrade_buf;
  36. size_t ota_upgrade_buf_size;
  37. int binary_file_len;
  38. int image_length;
  39. int max_http_request_size;
  40. esp_https_ota_state state;
  41. bool bulk_flash_erase;
  42. bool partial_http_download;
  43. };
  44. typedef struct esp_https_ota_handle esp_https_ota_t;
  45. static bool process_again(int status_code)
  46. {
  47. switch (status_code) {
  48. case HttpStatus_MovedPermanently:
  49. case HttpStatus_Found:
  50. case HttpStatus_TemporaryRedirect:
  51. case HttpStatus_Unauthorized:
  52. return true;
  53. default:
  54. return false;
  55. }
  56. return false;
  57. }
  58. static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client, int status_code)
  59. {
  60. esp_err_t err;
  61. if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found || status_code == HttpStatus_TemporaryRedirect) {
  62. err = esp_http_client_set_redirection(http_client);
  63. if (err != ESP_OK) {
  64. ESP_LOGE(TAG, "URL redirection Failed");
  65. return err;
  66. }
  67. } else if (status_code == HttpStatus_Unauthorized) {
  68. esp_http_client_add_auth(http_client);
  69. } else if(status_code == HttpStatus_NotFound || status_code == HttpStatus_Forbidden) {
  70. ESP_LOGE(TAG, "File not found(%d)", status_code);
  71. return ESP_FAIL;
  72. } else if (status_code >= HttpStatus_BadRequest && status_code < HttpStatus_InternalError) {
  73. ESP_LOGE(TAG, "Client error (%d)", status_code);
  74. return ESP_FAIL;
  75. } else if (status_code >= HttpStatus_InternalError) {
  76. ESP_LOGE(TAG, "Server error (%d)", status_code);
  77. return ESP_FAIL;
  78. }
  79. char upgrade_data_buf[DEFAULT_OTA_BUF_SIZE];
  80. // process_again() returns true only in case of redirection.
  81. if (process_again(status_code)) {
  82. while (1) {
  83. /*
  84. * In case of redirection, esp_http_client_read() is called
  85. * to clear the response buffer of http_client.
  86. */
  87. int data_read = esp_http_client_read(http_client, upgrade_data_buf, DEFAULT_OTA_BUF_SIZE);
  88. if (data_read <= 0) {
  89. return ESP_OK;
  90. }
  91. }
  92. }
  93. return ESP_OK;
  94. }
  95. static esp_err_t _http_connect(esp_http_client_handle_t http_client)
  96. {
  97. esp_err_t err = ESP_FAIL;
  98. int status_code, header_ret;
  99. do {
  100. char *post_data = NULL;
  101. /* Send POST request if body is set.
  102. * Note: Sending POST request is not supported if partial_http_download
  103. * is enabled
  104. */
  105. int post_len = esp_http_client_get_post_field(http_client, &post_data);
  106. err = esp_http_client_open(http_client, post_len);
  107. if (err != ESP_OK) {
  108. ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
  109. return err;
  110. }
  111. if (post_len) {
  112. int write_len = 0;
  113. while (post_len > 0) {
  114. write_len = esp_http_client_write(http_client, post_data, post_len);
  115. if (write_len < 0) {
  116. ESP_LOGE(TAG, "Write failed");
  117. return ESP_FAIL;
  118. }
  119. post_len -= write_len;
  120. post_data += write_len;
  121. }
  122. }
  123. header_ret = esp_http_client_fetch_headers(http_client);
  124. if (header_ret < 0) {
  125. return header_ret;
  126. }
  127. status_code = esp_http_client_get_status_code(http_client);
  128. err = _http_handle_response_code(http_client, status_code);
  129. if (err != ESP_OK) {
  130. return err;
  131. }
  132. } while (process_again(status_code));
  133. return err;
  134. }
  135. static void _http_cleanup(esp_http_client_handle_t client)
  136. {
  137. esp_http_client_close(client);
  138. esp_http_client_cleanup(client);
  139. }
  140. static esp_err_t _ota_write(esp_https_ota_t *https_ota_handle, const void *buffer, size_t buf_len)
  141. {
  142. if (buffer == NULL || https_ota_handle == NULL) {
  143. return ESP_FAIL;
  144. }
  145. esp_err_t err = esp_ota_write(https_ota_handle->update_handle, buffer, buf_len);
  146. if (err != ESP_OK) {
  147. ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err);
  148. } else {
  149. https_ota_handle->binary_file_len += buf_len;
  150. ESP_LOGD(TAG, "Written image length %d", https_ota_handle->binary_file_len);
  151. err = ESP_ERR_HTTPS_OTA_IN_PROGRESS;
  152. }
  153. return err;
  154. }
  155. static bool is_server_verification_enabled(esp_https_ota_config_t *ota_config) {
  156. return (ota_config->http_config->cert_pem
  157. || ota_config->http_config->use_global_ca_store
  158. || ota_config->http_config->crt_bundle_attach != NULL);
  159. }
  160. esp_err_t esp_https_ota_begin(esp_https_ota_config_t *ota_config, esp_https_ota_handle_t *handle)
  161. {
  162. esp_err_t err;
  163. if (handle == NULL || ota_config == NULL || ota_config->http_config == NULL) {
  164. ESP_LOGE(TAG, "esp_https_ota_begin: Invalid argument");
  165. if (handle) {
  166. *handle = NULL;
  167. }
  168. return ESP_ERR_INVALID_ARG;
  169. }
  170. if (!is_server_verification_enabled(ota_config)) {
  171. #if CONFIG_OTA_ALLOW_HTTP
  172. ESP_LOGW(TAG, "Continuing with insecure option because CONFIG_OTA_ALLOW_HTTP is set.");
  173. #else
  174. ESP_LOGE(TAG, "No option for server verification is enabled in esp_http_client config.");
  175. *handle = NULL;
  176. return ESP_ERR_INVALID_ARG;
  177. #endif
  178. }
  179. esp_https_ota_t *https_ota_handle = calloc(1, sizeof(esp_https_ota_t));
  180. if (!https_ota_handle) {
  181. ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer");
  182. *handle = NULL;
  183. return ESP_ERR_NO_MEM;
  184. }
  185. https_ota_handle->partial_http_download = ota_config->partial_http_download;
  186. https_ota_handle->max_http_request_size = (ota_config->max_http_request_size == 0) ? DEFAULT_REQUEST_SIZE : ota_config->max_http_request_size;
  187. /* Initiate HTTP Connection */
  188. https_ota_handle->http_client = esp_http_client_init(ota_config->http_config);
  189. if (https_ota_handle->http_client == NULL) {
  190. ESP_LOGE(TAG, "Failed to initialise HTTP connection");
  191. err = ESP_FAIL;
  192. goto failure;
  193. }
  194. if (https_ota_handle->partial_http_download) {
  195. esp_http_client_set_method(https_ota_handle->http_client, HTTP_METHOD_HEAD);
  196. err = esp_http_client_perform(https_ota_handle->http_client);
  197. if (err != ESP_OK || esp_http_client_get_status_code(https_ota_handle->http_client) != HttpStatus_Ok) {
  198. ESP_LOGE(TAG, "Failed to get image length");
  199. goto http_cleanup;
  200. }
  201. https_ota_handle->image_length = esp_http_client_get_content_length(https_ota_handle->http_client);
  202. esp_http_client_close(https_ota_handle->http_client);
  203. if (https_ota_handle->image_length > https_ota_handle->max_http_request_size) {
  204. char *header_val = NULL;
  205. asprintf(&header_val, "bytes=0-%d", https_ota_handle->max_http_request_size - 1);
  206. if (header_val == NULL) {
  207. ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
  208. err = ESP_ERR_NO_MEM;
  209. goto http_cleanup;
  210. }
  211. esp_http_client_set_header(https_ota_handle->http_client, "Range", header_val);
  212. free(header_val);
  213. }
  214. esp_http_client_set_method(https_ota_handle->http_client, HTTP_METHOD_GET);
  215. }
  216. if (ota_config->http_client_init_cb) {
  217. err = ota_config->http_client_init_cb(https_ota_handle->http_client);
  218. if (err != ESP_OK) {
  219. ESP_LOGE(TAG, "http_client_init_cb returned 0x%x", err);
  220. goto failure;
  221. }
  222. }
  223. err = _http_connect(https_ota_handle->http_client);
  224. if (err != ESP_OK) {
  225. ESP_LOGE(TAG, "Failed to establish HTTP connection");
  226. goto http_cleanup;
  227. }
  228. if (!https_ota_handle->partial_http_download) {
  229. https_ota_handle->image_length = esp_http_client_get_content_length(https_ota_handle->http_client);
  230. }
  231. https_ota_handle->update_partition = NULL;
  232. ESP_LOGI(TAG, "Starting OTA...");
  233. https_ota_handle->update_partition = esp_ota_get_next_update_partition(NULL);
  234. if (https_ota_handle->update_partition == NULL) {
  235. ESP_LOGE(TAG, "Passive OTA partition not found");
  236. err = ESP_FAIL;
  237. goto http_cleanup;
  238. }
  239. ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
  240. https_ota_handle->update_partition->subtype, https_ota_handle->update_partition->address);
  241. const int alloc_size = MAX(ota_config->http_config->buffer_size, DEFAULT_OTA_BUF_SIZE);
  242. https_ota_handle->ota_upgrade_buf = (char *)malloc(alloc_size);
  243. if (!https_ota_handle->ota_upgrade_buf) {
  244. ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer");
  245. err = ESP_ERR_NO_MEM;
  246. goto http_cleanup;
  247. }
  248. https_ota_handle->ota_upgrade_buf_size = alloc_size;
  249. https_ota_handle->bulk_flash_erase = ota_config->bulk_flash_erase;
  250. https_ota_handle->binary_file_len = 0;
  251. *handle = (esp_https_ota_handle_t)https_ota_handle;
  252. https_ota_handle->state = ESP_HTTPS_OTA_BEGIN;
  253. return ESP_OK;
  254. http_cleanup:
  255. _http_cleanup(https_ota_handle->http_client);
  256. failure:
  257. free(https_ota_handle);
  258. *handle = NULL;
  259. return err;
  260. }
  261. esp_err_t esp_https_ota_get_img_desc(esp_https_ota_handle_t https_ota_handle, esp_app_desc_t *new_app_info)
  262. {
  263. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  264. if (handle == NULL || new_app_info == NULL) {
  265. ESP_LOGE(TAG, "esp_https_ota_read_img_desc: Invalid argument");
  266. return ESP_ERR_INVALID_ARG;
  267. }
  268. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  269. ESP_LOGE(TAG, "esp_https_ota_read_img_desc: Invalid state");
  270. return ESP_FAIL;
  271. }
  272. /*
  273. * `data_read_size` holds number of bytes needed to read complete header.
  274. * `bytes_read` holds number of bytes read.
  275. */
  276. int data_read_size = IMAGE_HEADER_SIZE;
  277. int data_read = 0, bytes_read = 0;
  278. /*
  279. * while loop is added to download complete image headers, even if the headers
  280. * are not sent in a single packet.
  281. */
  282. while (data_read_size > 0 && !esp_http_client_is_complete_data_received(handle->http_client)) {
  283. data_read = esp_http_client_read(handle->http_client,
  284. (handle->ota_upgrade_buf + bytes_read),
  285. data_read_size);
  286. /*
  287. * As esp_http_client_read doesn't return negative error code if select fails, we rely on
  288. * `errno` to check for underlying transport connectivity closure if any
  289. */
  290. if (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED || data_read < 0) {
  291. ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
  292. break;
  293. }
  294. data_read_size -= data_read;
  295. bytes_read += data_read;
  296. }
  297. if (data_read_size > 0) {
  298. ESP_LOGE(TAG, "Complete headers were not received");
  299. return ESP_FAIL;
  300. }
  301. handle->binary_file_len = bytes_read;
  302. memcpy(new_app_info, &handle->ota_upgrade_buf[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
  303. return ESP_OK;
  304. }
  305. esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle)
  306. {
  307. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  308. if (handle == NULL) {
  309. ESP_LOGE(TAG, "esp_https_ota_perform: Invalid argument");
  310. return ESP_ERR_INVALID_ARG;
  311. }
  312. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  313. ESP_LOGE(TAG, "esp_https_ota_perform: Invalid state");
  314. return ESP_FAIL;
  315. }
  316. esp_err_t err;
  317. int data_read;
  318. const int erase_size = handle->bulk_flash_erase ? OTA_SIZE_UNKNOWN : OTA_WITH_SEQUENTIAL_WRITES;
  319. switch (handle->state) {
  320. case ESP_HTTPS_OTA_BEGIN:
  321. err = esp_ota_begin(handle->update_partition, erase_size, &handle->update_handle);
  322. if (err != ESP_OK) {
  323. ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
  324. return err;
  325. }
  326. handle->state = ESP_HTTPS_OTA_IN_PROGRESS;
  327. /* In case `esp_https_ota_read_img_desc` was invoked first,
  328. then the image data read there should be written to OTA partition
  329. */
  330. if (handle->binary_file_len) {
  331. /*
  332. * Header length gets added to handle->binary_file_len in _ota_write
  333. * Clear handle->binary_file_len to avoid additional 289 bytes in binary_file_len
  334. */
  335. int binary_file_len = handle->binary_file_len;
  336. handle->binary_file_len = 0;
  337. return _ota_write(handle, (const void *)handle->ota_upgrade_buf, binary_file_len);
  338. }
  339. /* falls through */
  340. case ESP_HTTPS_OTA_IN_PROGRESS:
  341. data_read = esp_http_client_read(handle->http_client,
  342. handle->ota_upgrade_buf,
  343. handle->ota_upgrade_buf_size);
  344. if (data_read == 0) {
  345. /*
  346. * esp_http_client_is_complete_data_received is added to check whether
  347. * complete image is received.
  348. */
  349. bool is_recv_complete = esp_http_client_is_complete_data_received(handle->http_client);
  350. /*
  351. * As esp_http_client_read doesn't return negative error code if select fails, we rely on
  352. * `errno` to check for underlying transport connectivity closure if any.
  353. * Incase the complete data has not been received but the server has sent
  354. * an ENOTCONN or ECONNRESET, failure is returned. We close with success
  355. * if complete data has been received.
  356. */
  357. if ((errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED) && !is_recv_complete) {
  358. ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
  359. return ESP_FAIL;
  360. } else if (!is_recv_complete) {
  361. return ESP_ERR_HTTPS_OTA_IN_PROGRESS;
  362. }
  363. ESP_LOGD(TAG, "Connection closed");
  364. } else if (data_read > 0) {
  365. return _ota_write(handle, (const void *)handle->ota_upgrade_buf, data_read);
  366. } else {
  367. ESP_LOGE(TAG, "data read %d, errno %d", data_read, errno);
  368. return ESP_FAIL;
  369. }
  370. if (!handle->partial_http_download || (handle->partial_http_download && handle->image_length == handle->binary_file_len)) {
  371. handle->state = ESP_HTTPS_OTA_SUCCESS;
  372. }
  373. break;
  374. default:
  375. ESP_LOGE(TAG, "Invalid ESP HTTPS OTA State");
  376. return ESP_FAIL;
  377. break;
  378. }
  379. if (handle->partial_http_download) {
  380. if (handle->state == ESP_HTTPS_OTA_IN_PROGRESS && handle->image_length > handle->binary_file_len) {
  381. esp_http_client_close(handle->http_client);
  382. char *header_val = NULL;
  383. if ((handle->image_length - handle->binary_file_len) > handle->max_http_request_size) {
  384. asprintf(&header_val, "bytes=%d-%d", handle->binary_file_len, (handle->binary_file_len + handle->max_http_request_size - 1));
  385. } else {
  386. asprintf(&header_val, "bytes=%d-", handle->binary_file_len);
  387. }
  388. if (header_val == NULL) {
  389. ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
  390. return ESP_ERR_NO_MEM;
  391. }
  392. esp_http_client_set_header(handle->http_client, "Range", header_val);
  393. free(header_val);
  394. err = _http_connect(handle->http_client);
  395. if (err != ESP_OK) {
  396. ESP_LOGE(TAG, "Failed to establish HTTP connection");
  397. return ESP_FAIL;
  398. }
  399. ESP_LOGD(TAG, "Connection start");
  400. return ESP_ERR_HTTPS_OTA_IN_PROGRESS;
  401. }
  402. }
  403. return ESP_OK;
  404. }
  405. bool esp_https_ota_is_complete_data_received(esp_https_ota_handle_t https_ota_handle)
  406. {
  407. bool ret = false;
  408. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  409. if (handle->partial_http_download) {
  410. ret = (handle->image_length == handle->binary_file_len);
  411. } else {
  412. ret = esp_http_client_is_complete_data_received(handle->http_client);
  413. }
  414. return ret;
  415. }
  416. esp_err_t esp_https_ota_finish(esp_https_ota_handle_t https_ota_handle)
  417. {
  418. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  419. if (handle == NULL) {
  420. return ESP_ERR_INVALID_ARG;
  421. }
  422. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  423. return ESP_FAIL;
  424. }
  425. esp_err_t err = ESP_OK;
  426. switch (handle->state) {
  427. case ESP_HTTPS_OTA_SUCCESS:
  428. case ESP_HTTPS_OTA_IN_PROGRESS:
  429. err = esp_ota_end(handle->update_handle);
  430. /* falls through */
  431. case ESP_HTTPS_OTA_BEGIN:
  432. if (handle->ota_upgrade_buf) {
  433. free(handle->ota_upgrade_buf);
  434. }
  435. if (handle->http_client) {
  436. _http_cleanup(handle->http_client);
  437. }
  438. break;
  439. default:
  440. ESP_LOGE(TAG, "Invalid ESP HTTPS OTA State");
  441. break;
  442. }
  443. if ((err == ESP_OK) && (handle->state == ESP_HTTPS_OTA_SUCCESS)) {
  444. esp_err_t err = esp_ota_set_boot_partition(handle->update_partition);
  445. if (err != ESP_OK) {
  446. ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%x", err);
  447. }
  448. }
  449. free(handle);
  450. return err;
  451. }
  452. esp_err_t esp_https_ota_abort(esp_https_ota_handle_t https_ota_handle)
  453. {
  454. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  455. if (handle == NULL) {
  456. return ESP_ERR_INVALID_ARG;
  457. }
  458. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  459. return ESP_FAIL;
  460. }
  461. esp_err_t err = ESP_OK;
  462. switch (handle->state) {
  463. case ESP_HTTPS_OTA_SUCCESS:
  464. case ESP_HTTPS_OTA_IN_PROGRESS:
  465. err = esp_ota_abort(handle->update_handle);
  466. /* falls through */
  467. case ESP_HTTPS_OTA_BEGIN:
  468. if (handle->ota_upgrade_buf) {
  469. free(handle->ota_upgrade_buf);
  470. }
  471. if (handle->http_client) {
  472. _http_cleanup(handle->http_client);
  473. }
  474. break;
  475. default:
  476. err = ESP_ERR_INVALID_STATE;
  477. ESP_LOGE(TAG, "Invalid ESP HTTPS OTA State");
  478. break;
  479. }
  480. free(handle);
  481. return err;
  482. }
  483. int esp_https_ota_get_image_len_read(esp_https_ota_handle_t https_ota_handle)
  484. {
  485. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  486. if (handle == NULL) {
  487. return -1;
  488. }
  489. if (handle->state < ESP_HTTPS_OTA_IN_PROGRESS) {
  490. return -1;
  491. }
  492. return handle->binary_file_len;
  493. }
  494. int esp_https_ota_get_image_size(esp_https_ota_handle_t https_ota_handle)
  495. {
  496. esp_https_ota_t *handle = (esp_https_ota_t *)https_ota_handle;
  497. if (handle == NULL) {
  498. return -1;
  499. }
  500. if (handle->state < ESP_HTTPS_OTA_BEGIN) {
  501. return -1;
  502. }
  503. return handle->image_length;
  504. }
  505. esp_err_t esp_https_ota(const esp_http_client_config_t *config)
  506. {
  507. if (!config) {
  508. ESP_LOGE(TAG, "esp_http_client config not found");
  509. return ESP_ERR_INVALID_ARG;
  510. }
  511. esp_https_ota_config_t ota_config = {
  512. .http_config = config,
  513. };
  514. esp_https_ota_handle_t https_ota_handle = NULL;
  515. esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle);
  516. if (https_ota_handle == NULL) {
  517. return ESP_FAIL;
  518. }
  519. while (1) {
  520. err = esp_https_ota_perform(https_ota_handle);
  521. if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
  522. break;
  523. }
  524. }
  525. if (err != ESP_OK) {
  526. esp_https_ota_abort(https_ota_handle);
  527. return err;
  528. }
  529. esp_err_t ota_finish_err = esp_https_ota_finish(https_ota_handle);
  530. if (ota_finish_err != ESP_OK) {
  531. return ota_finish_err;
  532. }
  533. return ESP_OK;
  534. }