1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5 #include "iotx_ota_internal.h"
6
7 /* ofc, OTA fetch channel */
8
9 #define OFC_HTTP_HEADER_MAXLEN (128)
10
11 typedef struct {
12 char *payload;
13 int alread_download;
14 int payload_len;
15 } ota_http_response_t;
16
17 typedef struct {
18 const char *url;
19 void *http_handle;
20 int fetch_size;
21 } otahttp_Struct_t, *otahttp_Struct_pt;
22
ofc_Init(char * url,int offset)23 void *ofc_Init(char *url, int offset)
24 {
25 otahttp_Struct_pt h_odc;
26 char *pub_key = NULL;
27 int port = 0;
28 char header[OFC_HTTP_HEADER_MAXLEN] = { 0 };
29 char *header_fmt =
30 "Accept: "
31 "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
32 "Accept-Encoding: gzip, deflate\r\n"
33 "Range: bytes=%d-\r\n";
34 char *protocol_end = NULL, *port_start = NULL, *port_end = NULL;
35 int protocol_len = 0;
36 iotx_http_method_t method = IOTX_HTTP_GET;
37
38 /* protocol end location */
39 protocol_end = strstr(url, "://");
40 if (protocol_end != NULL) {
41 protocol_len = strlen(url) - strlen(protocol_end);
42
43 /* check protocol, http or https, and assign default port*/
44 if ((strlen("http") == protocol_len) &&
45 (memcmp("http", url, protocol_len) == 0)) {
46 OTA_LOG_INFO("protocol: http");
47 port = 80;
48 } else if ((strlen("https") == protocol_len) &&
49 (memcmp("https", url, protocol_len) == 0)) {
50 OTA_LOG_INFO("protocol: https");
51 #ifdef SUPPORT_TLS
52 {
53 extern const char *iotx_ca_crt;
54 pub_key = (char *)iotx_ca_crt;
55 }
56 port = 443;
57 #else
58 port = 80;
59 #endif
60
61 } else {
62 OTA_LOG_ERROR("Invalid URL");
63 return NULL;
64 }
65 } else {
66 OTA_LOG_INFO("protocol: http");
67 protocol_end = url;
68 port = 80;
69 }
70
71 /* check port, if exist, override port */
72 port_start = strstr(protocol_end + 1, ":");
73 if (port_start != NULL) {
74 port_end = strstr(port_start + 1, "/");
75 if (port_end != NULL) {
76 OTA_LOG_INFO("port exist: %.*s", (int)(port_end - port_start - 1),
77 port_start + 1);
78 infra_str2int((const char *)(port_start + 1), &port);
79 }
80 }
81
82 HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt, offset);
83
84 h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t));
85 if (h_odc == NULL) {
86 OTA_LOG_ERROR("allocate for h_odc failed");
87 return NULL;
88 }
89
90 memset(h_odc, 0, sizeof(otahttp_Struct_t));
91
92 h_odc->http_handle = wrapper_http_init();
93 if (h_odc->http_handle == NULL) {
94 OTA_FREE(h_odc);
95 return NULL;
96 }
97
98 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_URL, (void *)url);
99 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_PORT, (void *)&port);
100 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_METHOD,
101 (void *)&method);
102 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_HEADER,
103 (void *)header);
104 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_CERT, (void *)pub_key);
105
106 return h_odc;
107 }
108
_ota_fetch_callback(char * ptr,int length,int total_length,void * userdata)109 static int _ota_fetch_callback(char *ptr, int length, int total_length,
110 void *userdata)
111 {
112 ota_http_response_t *response = (ota_http_response_t *)userdata;
113 if (response->alread_download + length > response->payload_len) {
114 return FAIL_RETURN;
115 }
116
117 memcpy(response->payload + response->alread_download, ptr, length);
118 response->alread_download += length;
119
120 return length;
121 }
122
ofc_Fetch(void * handle,char * buf,uint32_t buf_len,uint32_t timeout_s)123 int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
124 {
125 int current_fetch_size = 0;
126 int http_timeout_s = timeout_s * 1000;
127 int http_recv_maxlen = buf_len;
128 otahttp_Struct_pt h_odc = (otahttp_Struct_pt)handle;
129 ota_http_response_t response;
130
131 memset(&response, 0, sizeof(ota_http_response_t));
132 memset(buf, 0, buf_len);
133 response.payload = buf;
134 response.payload_len = buf_len;
135
136 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_TIMEOUT,
137 (void *)&http_timeout_s);
138 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVCALLBACK,
139 (void *)_ota_fetch_callback);
140 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVMAXLEN,
141 (void *)&http_recv_maxlen);
142 wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVCONTEXT,
143 (void *)&response);
144 current_fetch_size = wrapper_http_perform(h_odc->http_handle, NULL, 0);
145
146 if (current_fetch_size < 0) {
147 OTA_LOG_ERROR("fetch firmware failed");
148 return current_fetch_size;
149 }
150
151 h_odc->fetch_size += current_fetch_size;
152
153 /* OTA_LOG_ERROR("Download This Time: %d",current_fetch_size);
154 OTA_LOG_ERROR("Download Total : %d",h_odc->fetch_size); */
155
156 return current_fetch_size;
157 }
158
ofc_Deinit(void ** handle)159 int ofc_Deinit(void **handle)
160 {
161 otahttp_Struct_t *h_odc = NULL;
162
163 if (handle == NULL || *handle == NULL) {
164 return FAIL_RETURN;
165 }
166
167 h_odc = *(otahttp_Struct_t **)handle;
168 wrapper_http_deinit(&h_odc->http_handle);
169 OTA_FREE(h_odc);
170
171 *handle = NULL;
172
173 return 0;
174 }
175