1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 #include "iotx_ota_internal.h"
6 
7 #if (OTA_SIGNAL_CHANNEL) == 1
8 #include "ota_mqtt.c"
9 #elif (OTA_SIGNAL_CHANNEL) == 2
10 #include "ota_coap.c"
11 #else
12 #error "NOT support yet!"
13 #endif
14 
15 /* check whether the progress state is valid or not */
16 /* return: true, valid progress state; false, invalid progress state. */
ota_check_progress(IOT_OTA_Progress_t progress)17 static int ota_check_progress(IOT_OTA_Progress_t progress)
18 {
19     return ((progress >= IOT_OTAP_BURN_FAILED) &&
20             (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX));
21 }
22 
ota_callback(void * pcontext,const char * msg,uint32_t msg_len,iotx_ota_topic_types_t type)23 static int ota_callback(void *pcontext, const char *msg, uint32_t msg_len,
24                         iotx_ota_topic_types_t type)
25 {
26     const char *pvalue;
27     uint32_t val_len;
28 
29     OTA_Struct_pt h_ota = (OTA_Struct_pt)pcontext;
30 
31     if (h_ota->state == IOT_OTAS_FETCHING) {
32         OTA_LOG_INFO("In downloading state");
33         return -1;
34     }
35 
36     switch (type) {
37     case IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST:
38     case IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE:
39         {
40             pvalue = otalib_JsonValueOf(msg, msg_len, "message", &val_len);
41             if (NULL == pvalue) {
42                 OTA_LOG_ERROR("invalid json doc of OTA ");
43                 return -1;
44             }
45 
46             /* check whether is positive message */
47             if (!((strlen("success") == val_len) &&
48                   (0 == strncmp(pvalue, "success", val_len)))) {
49                 OTA_LOG_ERROR("fail state of json doc of OTA");
50                 return -1;
51             }
52 
53             /* get value of 'data' key */
54             pvalue = otalib_JsonValueOf(msg, msg_len, "data", &val_len);
55             if (NULL == pvalue) {
56                 OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
57                 return -1;
58             }
59 
60             if (0 != otalib_GetParams(pvalue, val_len, &h_ota->purl,
61                                       &h_ota->version, h_ota->md5sum,
62                                       &h_ota->size_file)) {
63                 OTA_LOG_ERROR("Get config parameter failed");
64                 return -1;
65             }
66 
67             h_ota->ch_fetch =
68                              ofc_Init(h_ota->purl, h_ota->size_fetched);
69             if (h_ota->ch_fetch == NULL) {
70                 OTA_LOG_ERROR("Initialize fetch module failed");
71                 return -1;
72             }
73 
74             h_ota->type = IOT_OTAT_FOTA;
75             h_ota->state = IOT_OTAS_PUSHED;
76         }
77         break;
78 
79     case IOTX_OTA_TOPIC_TYPE_CONFIG_GET:
80         {
81             pvalue = otalib_JsonValueOf(msg, msg_len, "code", &val_len);
82             if (NULL == pvalue) {
83                 OTA_LOG_ERROR("invalid json doc of OTA ");
84                 return -1;
85             }
86 
87             /* check whether is positive message */
88             if (!((strlen("200") == val_len) &&
89                   (0 == strncmp(pvalue, "200", val_len)))) {
90                 OTA_LOG_ERROR("fail state of json doc of OTA");
91                 return -1;
92             }
93 
94             /* get value of 'data' key */
95             pvalue = otalib_JsonValueOf(msg, msg_len, "data", &val_len);
96             if (NULL == pvalue) {
97                 OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
98                 return -1;
99             }
100 
101             if (0 != otalib_GetConfigParams(
102                          pvalue, val_len, &h_ota->configId, &h_ota->configSize,
103                          &h_ota->sign, &h_ota->signMethod, &h_ota->cota_url,
104                          &h_ota->getType)) {
105                 OTA_LOG_ERROR("Get firmware parameter failed");
106                 return -1;
107             }
108 
109             h_ota->size_file = h_ota->configSize;
110             h_ota->size_fetched = 0;
111             if (NULL != h_ota->md5) {
112                 otalib_MD5Deinit(h_ota->md5);
113             }
114             h_ota->md5 = otalib_MD5Init();
115 
116             if (NULL != h_ota->sha256) {
117                 otalib_Sha256Deinit(h_ota->sha256);
118             }
119             h_ota->sha256 = otalib_Sha256Init();
120 
121             h_ota->ch_fetch = ofc_Init(h_ota->cota_url, h_ota->size_fetched);
122             if (h_ota->ch_fetch == NULL) {
123                 OTA_LOG_ERROR("Initialize fetch module failed");
124                 return -1;
125             }
126 
127             h_ota->type = IOT_OTAT_COTA;
128             h_ota->state = IOT_OTAS_PUSHED;
129         }
130         break;
131 
132     case IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH:
133         {
134             /* get value of 'params' key */
135             pvalue = otalib_JsonValueOf(msg, msg_len, "params", &val_len);
136             if (NULL == pvalue) {
137                 OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
138                 return -1;
139             }
140 
141             if (0 != otalib_GetConfigParams(
142                          pvalue, val_len, &h_ota->configId, &h_ota->configSize,
143                          &h_ota->sign, &h_ota->signMethod, &h_ota->cota_url,
144                          &h_ota->getType)) {
145                 OTA_LOG_ERROR("Get firmware parameter failed");
146                 return -1;
147             }
148 
149             h_ota->size_file = h_ota->configSize;
150             h_ota->size_fetched = 0;
151             if (NULL != h_ota->md5) {
152                 otalib_MD5Deinit(h_ota->md5);
153             }
154             h_ota->md5 = otalib_MD5Init();
155 
156             if (NULL != h_ota->sha256) {
157                 otalib_Sha256Deinit(h_ota->sha256);
158             }
159             h_ota->sha256 = otalib_Sha256Init();
160 
161             h_ota->ch_fetch = ofc_Init(h_ota->cota_url, h_ota->size_fetched);
162             if (h_ota->ch_fetch == NULL) {
163                 OTA_LOG_ERROR("Initialize fetch module failed");
164                 return -1;
165             }
166 
167             h_ota->type = IOT_OTAT_COTA;
168             h_ota->state = IOT_OTAS_PUSHED;
169         }
170         break;
171 
172     default:
173         return -1;
174         break;
175     }
176 
177     if (h_ota->ota_event_cb != NULL) {
178         h_ota->ota_event_cb(h_ota);
179     }
180     return 0;
181 }
182 
183 static int g_ota_is_initialized = 0;
184 
IOT_OTA_SetOnPushedCallback(void * handle,int (* cb)(void * context))185 int IOT_OTA_SetOnPushedCallback(void *handle, int (*cb)(void *context))
186 {
187     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
188     if (h_ota == NULL) {
189         return -1;
190     }
191 
192     h_ota->ota_event_cb = cb;
193     return 0;
194 }
195 /* Initialize OTA module */
IOT_OTA_Init(const char * product_key,const char * device_name,void * ch_signal)196 void *IOT_OTA_Init(const char *product_key, const char *device_name,
197                    void *ch_signal)
198 {
199     OTA_Struct_pt h_ota = NULL;
200 
201     if (1 == g_ota_is_initialized) {
202         OTA_LOG_ERROR("iot ota has been initialized");
203         return NULL;
204     }
205 
206     if ((NULL == product_key) || (NULL == device_name)) {
207         OTA_LOG_ERROR("one or more parameters is invalid");
208         return NULL;
209     }
210 
211     h_ota = OTA_MALLOC(sizeof(OTA_Struct_t));
212     if (h_ota == NULL) {
213         OTA_LOG_ERROR("allocate failed");
214         return NULL;
215     }
216     memset(h_ota, 0, sizeof(OTA_Struct_t));
217     h_ota->type = IOT_OTAT_NONE;
218     h_ota->state = IOT_OTAS_UNINITED;
219 
220     h_ota->ch_signal =
221         osc_Init(product_key, device_name, ch_signal, ota_callback, h_ota);
222     if (NULL == h_ota->ch_signal) {
223         OTA_LOG_ERROR("initialize signal channel failed");
224         goto do_exit;
225     }
226 
227     h_ota->md5 = otalib_MD5Init();
228     if (NULL == h_ota->md5) {
229         OTA_LOG_ERROR("initialize md5 failed");
230         goto do_exit;
231     }
232     h_ota->sha256 = otalib_Sha256Init();
233     if (NULL == h_ota->sha256) {
234         OTA_LOG_ERROR("initialize sha256 failed");
235         goto do_exit;
236     }
237 
238     h_ota->product_key = product_key;
239     h_ota->device_name = device_name;
240     h_ota->state = IOT_OTAS_INITED;
241     g_ota_is_initialized = 1;
242     return h_ota;
243 
244 do_exit:
245 
246     if (NULL != h_ota->ch_signal) {
247         osc_Deinit(h_ota->ch_signal);
248     }
249 
250     if (NULL != h_ota->md5) {
251         otalib_MD5Deinit(h_ota->md5);
252     }
253 
254     if (NULL != h_ota->sha256) {
255         otalib_Sha256Deinit(h_ota->sha256);
256     }
257 
258     if (NULL != h_ota) {
259         OTA_FREE(h_ota);
260     }
261 
262     return NULL;
263 
264 #undef AOM_INFO_MSG_LEN
265 }
266 
267 /* deinitialize OTA module */
IOT_OTA_Deinit(void * handle)268 int IOT_OTA_Deinit(void *handle)
269 {
270     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
271 
272     if (NULL == h_ota) {
273         OTA_LOG_ERROR("handle is NULL");
274         return IOT_OTAE_INVALID_PARAM;
275     }
276 
277     if (IOT_OTAS_UNINITED == h_ota->state) {
278         OTA_LOG_ERROR("handle is uninitialized");
279         h_ota->err = IOT_OTAE_INVALID_STATE;
280         return -1;
281     }
282 
283     g_ota_is_initialized = 0;
284 
285     if (NULL != h_ota->ch_signal) {
286         osc_Deinit(h_ota->ch_signal);
287     }
288 
289     if (NULL != h_ota->ch_fetch) {
290         ofc_Deinit(&h_ota->ch_fetch);
291     }
292 
293     if (NULL != h_ota->md5) {
294         otalib_MD5Deinit(h_ota->md5);
295     }
296 
297     if (NULL != h_ota->sha256) {
298         otalib_Sha256Deinit(h_ota->sha256);
299     }
300 
301     if (NULL != h_ota->purl) {
302         OTA_FREE(h_ota->purl);
303     }
304 
305     if (NULL != h_ota->version) {
306         OTA_FREE(h_ota->version);
307     }
308 
309     if (NULL != h_ota->configId) {
310         OTA_FREE(h_ota->configId);
311     }
312 
313     if (NULL != h_ota->sign) {
314         OTA_FREE(h_ota->sign);
315     }
316 
317     if (NULL != h_ota->signMethod) {
318         OTA_FREE(h_ota->signMethod);
319     }
320 
321     if (NULL != h_ota->cota_url) {
322         OTA_FREE(h_ota->cota_url);
323     }
324 
325     if (NULL != h_ota->getType) {
326         OTA_FREE(h_ota->getType);
327     }
328 
329     OTA_FREE(h_ota);
330     return 0;
331 }
332 
333 #define OTA_VERSION_STR_LEN_MIN (1)
334 #define OTA_VERSION_STR_LEN_MAX (32)
335 
IOT_OTA_ReportVersion(void * handle,const char * version)336 int IOT_OTA_ReportVersion(void *handle, const char *version)
337 {
338 #define MSG_INFORM_LEN (128)
339 
340     int ret, len;
341     char *msg_informed;
342     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
343 
344     if ((NULL == h_ota) || (NULL == version)) {
345         OTA_LOG_ERROR("one or more invalid parameter");
346         return IOT_OTAE_INVALID_PARAM;
347     }
348 
349     len = strlen(version);
350     if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
351         OTA_LOG_ERROR("version string is invalid: must be [1, 32] chars");
352         h_ota->err = IOT_OTAE_INVALID_PARAM;
353         return -1;
354     }
355 
356     if (IOT_OTAS_UNINITED == h_ota->state) {
357         OTA_LOG_ERROR("handle is uninitialized");
358         h_ota->err = IOT_OTAE_INVALID_STATE;
359         return -1;
360     }
361 
362     msg_informed = OTA_MALLOC(MSG_INFORM_LEN);
363     if (msg_informed == NULL) {
364         OTA_LOG_ERROR("allocate for msg_informed failed");
365         h_ota->err = IOT_OTAE_NOMEM;
366         return -1;
367     }
368 
369     ret = otalib_GenInfoMsg(msg_informed, MSG_INFORM_LEN, h_ota->id, version);
370     if (ret != 0) {
371         OTA_LOG_ERROR("generate inform message failed");
372         h_ota->err = ret;
373         ret = -1;
374         goto do_exit;
375     }
376 
377     ret = osc_ReportVersion(h_ota->ch_signal, msg_informed);
378     if (0 != ret) {
379         OTA_LOG_ERROR("Report version failed");
380         h_ota->err = ret;
381         ret = -1;
382         goto do_exit;
383     }
384     ret = 0;
385 
386 do_exit:
387     if (NULL != msg_informed) {
388         OTA_FREE(msg_informed);
389     }
390     return ret;
391 
392 #undef MSG_INFORM_LEN
393 }
394 
iotx_req_image(void * handle,const char * version)395 int iotx_req_image(void *handle, const char *version)
396 {
397 #define MSG_REQUEST_LEN (128)
398 
399     int ret, len;
400     char *msg_informed;
401     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
402 
403     if ((NULL == h_ota) || (NULL == version)) {
404         OTA_LOG_ERROR("one or more invalid parameter");
405         return IOT_OTAE_INVALID_PARAM;
406     }
407 
408     len = strlen(version);
409     if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
410         OTA_LOG_ERROR("version string is invalid: must be [1, 32] chars");
411         h_ota->err = IOT_OTAE_INVALID_PARAM;
412         return -1;
413     }
414 
415     if (IOT_OTAS_UNINITED == h_ota->state) {
416         OTA_LOG_ERROR("handle is uninitialized");
417         h_ota->err = IOT_OTAE_INVALID_STATE;
418         return -1;
419     }
420 
421     if (IOT_OTAS_FETCHING == h_ota->state) {
422         OTA_LOG_ERROR("ota is busying");
423         h_ota->err = IOT_OTAE_INVALID_STATE;
424         return -1;
425     }
426 
427     msg_informed = OTA_MALLOC(MSG_REQUEST_LEN);
428     if (msg_informed == NULL) {
429         OTA_LOG_ERROR("allocate for msg_informed failed");
430         h_ota->err = IOT_OTAE_NOMEM;
431         return -1;
432     }
433 
434     ret = otalib_GenInfoMsg(msg_informed, MSG_REQUEST_LEN, h_ota->id, version);
435     if (ret != 0) {
436         OTA_LOG_ERROR("generate request image message failed");
437         h_ota->err = ret;
438         ret = -1;
439         goto do_exit;
440     }
441 
442     ret = osc_RequestImage(h_ota->ch_signal, msg_informed);
443     if (0 != ret) {
444         OTA_LOG_ERROR("Request image failed");
445         h_ota->err = ret;
446         ret = -1;
447         goto do_exit;
448     }
449     ret = 0;
450 
451 do_exit:
452     if (NULL != msg_informed) {
453         OTA_FREE(msg_informed);
454     }
455     return ret;
456 
457 #undef MSG_REQUEST_LEN
458 }
459 
IOT_OTA_ReportProgress(void * handle,IOT_OTA_Progress_t progress,const char * msg)460 int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress,
461                            const char *msg)
462 {
463 #define MSG_REPORT_LEN (256)
464 
465     int ret = -1;
466     char *msg_reported;
467     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
468 
469     if (NULL == handle) {
470         OTA_LOG_ERROR("handle is NULL");
471         return IOT_OTAE_INVALID_PARAM;
472     }
473 
474     if (IOT_OTAS_UNINITED == h_ota->state) {
475         OTA_LOG_ERROR("handle is uninitialized");
476         h_ota->err = IOT_OTAE_INVALID_STATE;
477         return -1;
478     }
479     if (!ota_check_progress(progress)) {
480         OTA_LOG_ERROR("progress is a invalid parameter");
481         h_ota->err = IOT_OTAE_INVALID_PARAM;
482         return -1;
483     }
484 
485     msg_reported = OTA_MALLOC(MSG_REPORT_LEN);
486     if (msg_reported == NULL) {
487         OTA_LOG_ERROR("allocate for msg_reported failed");
488         h_ota->err = IOT_OTAE_NOMEM;
489         return -1;
490     }
491 
492     ret = otalib_GenReportMsg(msg_reported, MSG_REPORT_LEN, h_ota->id, progress,
493                               msg);
494     if (0 != ret) {
495         OTA_LOG_ERROR("generate reported message failed");
496         h_ota->err = ret;
497         goto do_exit;
498     }
499 
500     ret = osc_ReportProgress(h_ota->ch_signal, msg_reported);
501     if (0 != ret) {
502         OTA_LOG_ERROR("Report progress failed");
503         h_ota->err = ret;
504         goto do_exit;
505     }
506 
507     ret = 0;
508 
509 do_exit:
510     if (NULL != msg_reported) {
511         OTA_FREE(msg_reported);
512     }
513     return ret;
514 
515 #undef MSG_REPORT_LEN
516 }
517 
iotx_ota_get_config(void * handle,const char * configScope,const char * getType,const char * attributeKeys)518 int iotx_ota_get_config(void *handle, const char *configScope,
519                         const char *getType, const char *attributeKeys)
520 {
521 #define MSG_REPORT_LEN (256)
522 
523     int ret = -1;
524     char *msg_get;
525     char topic[OTA_MQTT_TOPIC_LEN] = { 0 };
526     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
527     iotx_mqtt_topic_info_t topic_info;
528 
529     memset(&topic_info, 0, sizeof(iotx_mqtt_topic_info_t));
530 
531     if (NULL == handle) {
532         OTA_LOG_ERROR("handle is NULL");
533         return IOT_OTAE_INVALID_PARAM;
534     }
535 
536     if (IOT_OTAS_UNINITED == h_ota->state) {
537         OTA_LOG_ERROR("handle is uninitialized");
538         h_ota->err = IOT_OTAE_INVALID_STATE;
539         return -1;
540     }
541 
542     if (IOT_OTAS_FETCHING == h_ota->state) {
543         OTA_LOG_ERROR("ota is busying");
544         h_ota->err = IOT_OTAE_INVALID_STATE;
545         return -1;
546     }
547 
548     msg_get = OTA_MALLOC(MSG_REPORT_LEN);
549     if (msg_get == NULL) {
550         OTA_LOG_ERROR("allocate for msg_reported failed");
551         h_ota->err = IOT_OTAE_NOMEM;
552         return -1;
553     }
554 
555     if (0 > HAL_Snprintf(topic, OTA_MQTT_TOPIC_LEN,
556                          "/sys/%s/%s/thing/config/get", h_ota->product_key,
557                          h_ota->device_name)) {
558         goto do_exit;
559     };
560 
561     if (0 > HAL_Snprintf(msg_get, MSG_REPORT_LEN,
562                          "{\"id\" : "
563                          "%d,\"version\":\"1.0\",\"params\":{\"configScope\":"
564                          "\"%s\",\"getType\":\"%s\",\"attributeKeys\":\"%s\"},"
565                          "\"method\":\"thing.config.get\"}",
566                          h_ota->id, configScope, getType, attributeKeys)) {
567         goto do_exit;
568     };
569     OTA_LOG_INFO(msg_get);
570     topic_info.qos = IOTX_MQTT_QOS0;
571     topic_info.payload = (void *)msg_get;
572     topic_info.payload_len = strlen(msg_get);
573 
574     ret = osc_RequestConfig(h_ota->ch_signal, topic, &topic_info);
575     if (ret < 0) {
576         OTA_LOG_ERROR("publish failed");
577         return IOT_OTAE_OSC_FAILED;
578     }
579 
580     ret = 0;
581 
582 do_exit:
583     if (NULL != msg_get) {
584         OTA_FREE(msg_get);
585     }
586     return ret;
587 
588 #undef MSG_REPORT_LEN
589 }
590 
591 /* check whether is downloading */
IOT_OTA_IsFetching(void * handle)592 int IOT_OTA_IsFetching(void *handle)
593 {
594     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
595 
596     if (NULL == handle) {
597         OTA_LOG_ERROR("handle is NULL");
598         return 0;
599     }
600 
601     if (IOT_OTAS_UNINITED == h_ota->state) {
602         OTA_LOG_ERROR("handle is uninitialized");
603         h_ota->err = IOT_OTAE_INVALID_STATE;
604         return 0;
605     }
606 
607     return (IOT_OTAS_PUSHED == h_ota->state ||
608             IOT_OTAS_FETCHING == h_ota->state);
609 }
610 
611 /* check whether fetch over */
IOT_OTA_IsFetchFinish(void * handle)612 int IOT_OTA_IsFetchFinish(void *handle)
613 {
614     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
615 
616     if (NULL == handle) {
617         OTA_LOG_ERROR("handle is NULL");
618         return 0;
619     }
620 
621     if (IOT_OTAS_UNINITED == h_ota->state) {
622         OTA_LOG_ERROR("handle is uninitialized");
623         h_ota->err = IOT_OTAE_INVALID_STATE;
624         return 0;
625     }
626 
627     return (IOT_OTAS_FETCHED == h_ota->state);
628 }
629 
IOT_OTA_FetchYield(void * handle,char * buf,uint32_t buf_len,uint32_t timeout_s)630 int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len,
631                        uint32_t timeout_s)
632 {
633     int ret;
634     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
635 
636     if ((NULL == handle) || (NULL == buf) || (0 == buf_len)) {
637         OTA_LOG_ERROR("invalid parameter");
638         return IOT_OTAE_INVALID_PARAM;
639     }
640 
641     if (IOT_OTAS_PUSHED == h_ota->state) {
642         h_ota->state = IOT_OTAS_FETCHING;
643     } else if (IOT_OTAS_FETCHING != h_ota->state) {
644         h_ota->err = IOT_OTAE_INVALID_STATE;
645         return IOT_OTAE_INVALID_STATE;
646     }
647 
648     if (h_ota->md5 == NULL) {
649         h_ota->md5 = otalib_MD5Init();
650         if (h_ota->md5 == NULL) {
651             return FAIL_RETURN;
652         }
653     }
654     if (h_ota->sha256 == NULL) {
655         h_ota->sha256 = otalib_Sha256Init();
656         if (h_ota->sha256 == NULL) {
657             return FAIL_RETURN;
658         }
659     }
660 
661     if (h_ota->ch_fetch == NULL) {
662         if (h_ota->type == IOT_OTAT_FOTA) {
663             OTA_LOG_ERROR("h_ota->size_fetched: %d", h_ota->size_fetched);
664             h_ota->ch_fetch = ofc_Init(h_ota->purl, h_ota->size_fetched);
665         } else if (h_ota->type == IOT_OTAT_COTA) {
666             h_ota->ch_fetch = ofc_Init(h_ota->cota_url, h_ota->size_fetched);
667         }
668 
669         if (h_ota->ch_fetch == NULL) {
670             OTA_LOG_ERROR("Re-Initialize HTTP handle failed");
671             return FAIL_RETURN;
672         }
673     }
674 
675     ret = ofc_Fetch(h_ota->ch_fetch, buf, buf_len, timeout_s);
676     if (ret < 0) {
677         OTA_LOG_ERROR("OTA Internal Error: %d", ret);
678         ofc_Deinit(&h_ota->ch_fetch);
679         return ret;
680     } else if (0 == h_ota->size_fetched) {
681         otalib_MD5Deinit(h_ota->md5);
682         h_ota->md5 = otalib_MD5Init();
683         if (h_ota->md5 == NULL) {
684             OTA_LOG_ERROR("md5 init failed");
685             return -1;
686         }
687 
688         otalib_Sha256Deinit(h_ota->sha256);
689         h_ota->sha256 = otalib_Sha256Init();
690         if (h_ota->sha256 == NULL) {
691             OTA_LOG_ERROR("sha256 init failed");
692             return -1;
693         }
694         /* force report status in the first */
695         IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_PERCENTAGE_MIN,
696                                "Enter in downloading state");
697     }
698 
699     otalib_MD5Update(h_ota->md5, buf, ret);
700     otalib_Sha256Update(h_ota->sha256, buf, ret);
701     h_ota->size_last_fetched = ret;
702     h_ota->size_fetched += ret;
703 
704     if (h_ota->size_fetched >= h_ota->size_file) {
705         h_ota->type = IOT_OTAT_NONE;
706         h_ota->state = IOT_OTAS_FETCHED;
707     }
708 
709     return ret;
710 }
711 
IOT_OTA_Ioctl(void * handle,IOT_OTA_CmdType_t type,void * buf,int buf_len)712 int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len)
713 {
714     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
715 
716     if ((NULL == handle) || (NULL == buf) || (0 == buf_len)) {
717         OTA_LOG_ERROR("invalid parameter");
718         return IOT_OTAE_INVALID_PARAM;
719     }
720 
721     if (h_ota->state < IOT_OTAS_PUSHED) {
722         h_ota->err = IOT_OTAE_INVALID_STATE;
723         return IOT_OTAE_INVALID_STATE;
724     }
725 
726     switch (type) {
727     case IOT_OTAG_COTA_CONFIG_ID:
728         {
729             char **value = (char **)buf;
730             if (value == NULL || *value != NULL || h_ota->configId == NULL) {
731                 OTA_LOG_ERROR("Invalid parameter");
732                 h_ota->err = IOT_OTAE_INVALID_PARAM;
733                 return -1;
734             } else {
735                 *value = OTA_API_MALLOC(strlen(h_ota->configId) + 1);
736                 if (*value == NULL) {
737                     h_ota->err = IOT_OTAE_INVALID_PARAM;
738                     return -1;
739                 }
740                 memset(*value, 0, strlen(h_ota->configId) + 1);
741                 memcpy(*value, h_ota->configId, strlen(h_ota->configId));
742                 return 0;
743             }
744         }
745         break;
746     case IOT_OTAG_COTA_CONFIG_SIZE:
747         {
748             if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
749                 OTA_LOG_ERROR("Invalid parameter");
750                 h_ota->err = IOT_OTAE_INVALID_PARAM;
751                 return -1;
752             } else {
753                 *((uint32_t *)buf) = h_ota->configSize;
754                 return 0;
755             }
756         }
757         break;
758     case IOT_OTAG_COTA_SIGN:
759         {
760             char **value = (char **)buf;
761             if (value == NULL || *value != NULL || h_ota->sign == NULL) {
762                 OTA_LOG_ERROR("Invalid parameter");
763                 h_ota->err = IOT_OTAE_INVALID_PARAM;
764                 return -1;
765             } else {
766                 *value = OTA_API_MALLOC(strlen(h_ota->sign) + 1);
767                 if (*value == NULL) {
768                     h_ota->err = IOT_OTAE_INVALID_PARAM;
769                     return -1;
770                 }
771                 memset(*value, 0, strlen(h_ota->sign) + 1);
772                 memcpy(*value, h_ota->sign, strlen(h_ota->sign));
773                 return 0;
774             }
775         }
776         break;
777     case IOT_OTAG_COTA_SIGN_METHOD:
778         {
779             char **value = (char **)buf;
780             if (value == NULL || *value != NULL || h_ota->signMethod == NULL) {
781                 OTA_LOG_ERROR("Invalid parameter");
782                 h_ota->err = IOT_OTAE_INVALID_PARAM;
783                 return -1;
784             } else {
785                 *value = OTA_API_MALLOC(strlen(h_ota->signMethod) + 1);
786                 if (*value == NULL) {
787                     h_ota->err = IOT_OTAE_INVALID_PARAM;
788                     return -1;
789                 }
790                 memset(*value, 0, strlen(h_ota->signMethod) + 1);
791                 memcpy(*value, h_ota->signMethod, strlen(h_ota->signMethod));
792                 return 0;
793             }
794         }
795         break;
796     case IOT_OTAG_COTA_URL:
797         {
798             char **value = (char **)buf;
799             if (value == NULL || *value != NULL || h_ota->cota_url == NULL) {
800                 OTA_LOG_ERROR("Invalid parameter");
801                 h_ota->err = IOT_OTAE_INVALID_PARAM;
802                 return -1;
803             } else {
804                 *value = OTA_API_MALLOC(strlen(h_ota->cota_url) + 1);
805                 if (*value == NULL) {
806                     h_ota->err = IOT_OTAE_INVALID_PARAM;
807                     return -1;
808                 }
809                 memset(*value, 0, strlen(h_ota->cota_url) + 1);
810                 memcpy(*value, h_ota->cota_url, strlen(h_ota->cota_url));
811                 return 0;
812             }
813         }
814         break;
815     case IOT_OTAG_COTA_GETTYPE:
816         {
817             char **value = (char **)buf;
818             if (value == NULL || *value != NULL || h_ota->getType == NULL) {
819                 OTA_LOG_ERROR("Invalid parameter");
820                 h_ota->err = IOT_OTAE_INVALID_PARAM;
821                 return -1;
822             } else {
823                 *value = OTA_API_MALLOC(strlen(h_ota->getType) + 1);
824                 if (*value == NULL) {
825                     h_ota->err = IOT_OTAE_INVALID_PARAM;
826                     return -1;
827                 }
828                 memset(*value, 0, strlen(h_ota->getType) + 1);
829                 memcpy(*value, h_ota->getType, strlen(h_ota->getType));
830                 return 0;
831             }
832         }
833         break;
834     case IOT_OTAG_OTA_TYPE:
835         {
836             if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
837                 OTA_LOG_ERROR("Invalid parameter");
838                 h_ota->err = IOT_OTAE_INVALID_PARAM;
839                 return -1;
840             } else {
841                 *((uint32_t *)buf) = h_ota->type;
842                 return 0;
843             }
844         }
845         break;
846     case IOT_OTAG_FETCHED_SIZE:
847         if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
848             OTA_LOG_ERROR("Invalid parameter");
849             h_ota->err = IOT_OTAE_INVALID_PARAM;
850             return -1;
851         } else {
852             *((uint32_t *)buf) = h_ota->size_fetched;
853             return 0;
854         }
855 
856     case IOT_OTAG_FILE_SIZE:
857         if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
858             OTA_LOG_ERROR("Invalid parameter");
859             h_ota->err = IOT_OTAE_INVALID_PARAM;
860             return -1;
861         } else {
862             *((uint32_t *)buf) = h_ota->size_file;
863             return 0;
864         };
865 
866     case IOT_OTAG_VERSION:
867         {
868             strncpy(buf, h_ota->version, buf_len);
869             ((char *)buf)[buf_len - 1] = '\0';
870         }
871         break;
872 
873     case IOT_OTAG_MD5SUM:
874         strncpy(buf, h_ota->md5sum, buf_len);
875         ((char *)buf)[buf_len - 1] = '\0';
876         break;
877 
878     case IOT_OTAG_CHECK_FIRMWARE:
879         if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
880             OTA_LOG_ERROR("Invalid parameter");
881             h_ota->err = IOT_OTAE_INVALID_PARAM;
882             return -1;
883         } else if (h_ota->state != IOT_OTAS_FETCHED) {
884             h_ota->err = IOT_OTAE_INVALID_STATE;
885             OTA_LOG_ERROR(
886                 "Firmware can be checked in IOT_OTAS_FETCHED state only");
887             return -1;
888         } else {
889             char md5_str[33];
890             otalib_MD5Finalize(h_ota->md5, md5_str);
891             otalib_MD5Deinit(h_ota->md5);
892             h_ota->md5 = NULL;
893 
894             OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->md5sum, md5_str);
895             if (0 == strcmp(h_ota->md5sum, md5_str)) {
896                 *((uint32_t *)buf) = 1;
897             } else {
898                 *((uint32_t *)buf) = 0;
899                 IOT_OTA_ReportProgress(h_ota, IOT_OTAP_CHECK_FALIED, NULL);
900                 OTA_LOG_ERROR("image checksum compare failed");
901             }
902             return 0;
903         }
904     case IOT_OTAG_CHECK_CONFIG:
905         if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
906             OTA_LOG_ERROR("Invalid parameter");
907             h_ota->err = IOT_OTAE_INVALID_PARAM;
908             return -1;
909         } else if (h_ota->state != IOT_OTAS_FETCHED) {
910             h_ota->err = IOT_OTAE_INVALID_STATE;
911             OTA_LOG_ERROR(
912                 "Config can be checked in IOT_OTAS_FETCHED state only");
913             return -1;
914         } else {
915             if (0 ==
916                 strncmp(h_ota->signMethod, "Md5", strlen(h_ota->signMethod))) {
917                 char md5_str[33];
918                 otalib_MD5Finalize(h_ota->md5, md5_str);
919                 OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->sign, md5_str);
920                 if (0 == strcmp(h_ota->sign, md5_str)) {
921                     *((uint32_t *)buf) = 1;
922                 } else {
923                     *((uint32_t *)buf) = 0;
924                 }
925             }
926             if (0 == strncmp(h_ota->signMethod, "Sha256",
927                              strlen(h_ota->signMethod))) {
928                 char sha256_str[65];
929                 otalib_Sha256Finalize(h_ota->sha256, sha256_str);
930                 OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->sign, sha256_str);
931                 if (0 == strcmp(h_ota->sign, sha256_str)) {
932                     *((uint32_t *)buf) = 1;
933                 } else {
934                     *((uint32_t *)buf) = 0;
935                 }
936             }
937             return 0;
938         }
939     case IOT_OTAG_RESET_FETCHED_SIZE:
940         {
941             h_ota->size_fetched = 0;
942             return 0;
943         }
944     case IOT_OTAG_RESET_STATE:
945         {
946             h_ota->type = IOT_OTAT_NONE;
947             h_ota->state = IOT_OTAS_INITED;
948             h_ota->size_fetched = 0;
949             return 0;
950         }
951     default:
952         OTA_LOG_ERROR("invalid cmd type");
953         h_ota->err = IOT_OTAE_INVALID_PARAM;
954         return -1;
955     }
956 
957     return 0;
958 }
959 
960 /* Get last error code */
IOT_OTA_GetLastError(void * handle)961 int IOT_OTA_GetLastError(void *handle)
962 {
963     OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
964 
965     if (NULL == handle) {
966         OTA_LOG_ERROR("handle is NULL");
967         return IOT_OTAE_INVALID_PARAM;
968     }
969 
970     return h_ota->err;
971 }
972