Files

274 lines
8.4 KiB
C

/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "iotx_ota_internal.h"
/* ofc, OTA fetch channel */
#define OFC_HTTP_HEADER_MAXLEN (512)
typedef struct
{
char *payload;
int alread_download;
int payload_len;
} ota_http_response_t;
typedef struct
{
const char *url;
void *http_handle;
int fetch_size;
unsigned int file_size;
} otahttp_Struct_t, *otahttp_Struct_pt;
void *ofc_Init(char *url, int offset)
{
otahttp_Struct_pt h_odc;
char *pub_key = NULL;
int port = 0;
char header[OFC_HTTP_HEADER_MAXLEN] = {0};
char *header_fmt = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Range: bytes=%d-\r\n";
char *protocol_end = NULL, *port_start = NULL, *port_end = NULL;
int protocol_len = 0;
iotx_http_method_t method = IOTX_HTTP_GET;
/* protocol end location */
protocol_end = strstr(url, "://");
if (protocol_end != NULL)
{
protocol_len = strlen(url) - strlen(protocol_end);
/* check protocol, http or https, and assign default port*/
if ((strlen("http") == protocol_len) && (memcmp("http", url, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: http");
port = 11889; // 80;
}
else if ((strlen("https") == protocol_len) && (memcmp("https", url, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: https");
#ifdef SUPPORT_TLS
{
extern const char *iotx_ca_crt;
pub_key = (char *)iotx_ca_crt;
}
port = 443;
#else
port = 80;
#endif
}
else
{
OTA_LOG_ERROR("Invalid URL");
return NULL;
}
}
else
{
OTA_LOG_INFO("protocol: http");
protocol_end = url;
port = 11889; // 80;
}
/* check port, if exist, override port */
port_start = strstr(protocol_end + 1, ":");
if (port_start != NULL)
{
port_end = strstr(port_start + 1, "/");
if (port_end != NULL)
{
OTA_LOG_INFO("port exist: %.*s", (int)(port_end - port_start - 1), port_start + 1);
infra_str2int((const char *)(port_start + 1), &port);
}
}
if (offset == 0)
HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt, offset);
if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t))))
{
OTA_LOG_ERROR("allocate for h_odc failed");
return NULL;
}
memset(h_odc, 0, sizeof(otahttp_Struct_t));
h_odc->http_handle = wrapper_http_init();
if (h_odc->http_handle == NULL)
{
OTA_FREE(h_odc);
return NULL;
}
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_URL, (void *)url);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_PORT, (void *)&port);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_METHOD, (void *)&method);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_HEADER, (void *)header);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_CERT, (void *)pub_key);
return h_odc;
}
void *ofc_Init_new(void *handle)
{
OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
otahttp_Struct_pt h_odc = (otahttp_Struct_pt)h_ota->ch_fetch;
char *pub_key = NULL;
int port = 0;
char header[OFC_HTTP_HEADER_MAXLEN] = {0};
char *header_fmt = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Range: bytes=%d-%d\r\n";
char *header_fmt_1 = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Range: bytes=%d-\r\n";
char *protocol_end = NULL, *port_start = NULL, *port_end = NULL;
int protocol_len = 0;
iotx_http_method_t method = IOTX_HTTP_GET;
protocol_end = strstr(h_ota->purl, "://");
if (protocol_end != NULL)
{
protocol_len = strlen(h_ota->purl) - strlen(protocol_end);
if ((strlen("http") == protocol_len) && (memcmp("http", h_ota->purl, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: http");
port = 11889; // 80;
}
else if ((strlen("https") == protocol_len) && (memcmp("https", h_ota->purl, protocol_len) == 0))
{
OTA_LOG_INFO("protocol: https");
#ifdef SUPPORT_TLS
{
extern const char *iotx_ca_crt;
pub_key = (char *)iotx_ca_crt;
}
port = 443;
#else
port = 80;
#endif
}
else
{
OTA_LOG_ERROR("Invalid URL");
return NULL;
}
}
else
{
OTA_LOG_INFO("protocol: http");
protocol_end = h_ota->purl;
port = 11889; // 80;
}
port_start = strstr(protocol_end + 1, ":");
if (port_start != NULL)
{
port_end = strstr(port_start + 1, "/");
if (port_end != NULL)
{
OTA_LOG_INFO("port exist: %.*s", (int)(port_end - port_start - 1), port_start + 1);
infra_str2int((const char *)(port_start + 1), &port);
}
}
HAL_Printf("size_file = %d, size_fetched = %d, fetched_per_time = %d\n", h_ota->size_file, h_ota->size_fetched, h_ota->size_fetched_per_time);
if ((h_ota->size_file - h_ota->size_fetched) < h_ota->size_fetched_per_time)
{
HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt_1, h_ota->size_fetched);
HAL_Printf("------header_fmt_1-----\n");
}
else
{
HAL_Snprintf(header, OFC_HTTP_HEADER_MAXLEN, header_fmt, h_ota->size_fetched, h_ota->size_fetched + h_ota->size_fetched_per_time - 1);
HAL_Printf("------header_fmt-----\n");
}
if (h_odc == NULL)
{
if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t))))
{
OTA_LOG_ERROR("allocate for h_odc failed");
return NULL;
}
memset(h_odc, 0, sizeof(otahttp_Struct_t));
h_odc->http_handle = wrapper_http_init();
if (h_odc->http_handle == NULL)
{
OTA_FREE(h_odc);
return NULL;
}
}
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_URL, (void *)h_ota->purl);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_PORT, (void *)&port);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_METHOD, (void *)&method);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_HEADER, (void *)header);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_CERT, (void *)pub_key);
return h_odc;
}
static int _ota_fetch_callback(char *ptr, int length, int total_length, void *userdata)
{
ota_http_response_t *response = (ota_http_response_t *)userdata;
if (response->alread_download + length > response->payload_len)
{
return FAIL_RETURN;
}
memcpy(response->payload + response->alread_download, ptr, length);
response->alread_download += length;
return length;
}
int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
{
int current_fetch_size = 0;
int http_timeout_s = timeout_s * 1000;
int http_recv_maxlen = buf_len;
otahttp_Struct_pt h_odc = (otahttp_Struct_pt)handle;
ota_http_response_t response;
memset(&response, 0, sizeof(ota_http_response_t));
memset(buf, 0, buf_len);
response.payload = buf;
response.payload_len = buf_len;
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_TIMEOUT, (void *)&http_timeout_s);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVCALLBACK, (void *)_ota_fetch_callback);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVMAXLEN, (void *)&http_recv_maxlen);
wrapper_http_setopt(h_odc->http_handle, IOTX_HTTPOPT_RECVCONTEXT, (void *)&response);
current_fetch_size = wrapper_http_perform(h_odc->http_handle, NULL, 0);
if (current_fetch_size < 0)
{
OTA_LOG_ERROR("fetch firmware failed");
return current_fetch_size;
}
h_odc->fetch_size += current_fetch_size;
/* OTA_LOG_ERROR("Download This Time: %d",current_fetch_size);
OTA_LOG_ERROR("Download Total : %d",h_odc->fetch_size); */
return current_fetch_size;
}
int ofc_Deinit(void **handle)
{
otahttp_Struct_t *h_odc = NULL;
if (handle == NULL || *handle == NULL)
{
return FAIL_RETURN;
}
h_odc = *(otahttp_Struct_t **)handle;
wrapper_http_deinit(&h_odc->http_handle);
OTA_FREE(h_odc);
*handle = NULL;
return 0;
}