blob: 14ee87c46fe5e8181e85ee5e99c5faa6fd5eefbd [file] [log] [blame]
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "wefota_main.h"
#include "wefota_socket.h"
#include "wefota_device.h"
#define RECV_WHOLE_PACK 1
static FOTA_Status s_status = FOTA_STATUS_IDLE;
static struct sockaddr_in s_server1_addr = {0};
static struct sockaddr_in s_server2_addr = {0};
static unsigned char s_req[WEFOTA_REQ_MAX_LEN] = {0};
static unsigned char s_resp[WEFOTA_RESP_MAX_LEN] = {0};
static char s_destVersion[32] = {0};
static VerID s_verID = {0};
static DiffPackInfo s_diffpack_info = {0};
static unsigned int s_costTime = 0;
static unsigned int s_pack_date_count = 0;
static DiffPackDataReq s_diffpack_data_req = {0};
const WeFOTA_MSG s_wefota_msg_table[] = {
{FOTA_STATUS_IDLE, 0xFF, 0, 0x00, 0}, // no use
{FOTA_STATUS_GET_IP_1, 0x10, 0, 0x11, 18},
{FOTA_STATUS_CHECK_TASK, 0xBF, 32, 0xC0, 41},
{FOTA_STATUS_GET_IP_2, 0x10, 0, 0x11, 18},
{FOTA_STATUS_GET_VER_ID, 0x04, 68, 0x05, 12},
{FOTA_STATUS_GET_DIFF_PACK_ID, 0x00, 12, 0x02, 35},
{FOTA_STATUS_GET_DIFF_PACK_DATA, 0x01, 23, 0x03, WEFOTA_RESP_DIFF_PACK_DATA_MAX_LEN},
{FOTA_STATUS_GET_DIFF_PACK_END, 0x30, 19, 0x33, 0},
{FOTA_STATUS_INSTALL_DIFF_PACK, 0xFF, 0, 0x00, 0}, // no use
{FOTA_STATUS_MAX, 0xFF, 0, 0x00, 0}, // no use
};
void set_fota_status(FOTA_Status status) {
s_status = status;
}
FOTA_Status get_fota_status(void) {
return s_status;
}
int wefota_header_init(WeFOTAHeader *hdr) {
if(NULL == hdr) {
return -1;
}
memset(hdr, 0, sizeof(WeFOTAHeader));
hdr->magic = WEFOTA_HEADER_MAGIC; // maybe need htonl
hdr->protocol = WEFOTA_HEADER_PROTOCOL;
get_iccid(hdr->iccid);
get_imei(hdr->devid + 16);
hdr->tid = WEFOTA_HEADER_TID;
hdr->code = s_wefota_msg_table[s_status].req_code;
int count = s_wefota_msg_table[s_status].req_count;
hdr->count = htons(count);
printf("header:[imei:%s]\n", hdr->devid + 16);
return count;
}
int is_valid_resp_hdr(const WeFOTAHeader *hdr) {
if(NULL == hdr) {
return 0;
}
if(hdr->magic != WEFOTA_HEADER_MAGIC && hdr->magic != htonl(WEFOTA_HEADER_MAGIC)) {
return 0;
}
if(hdr->protocol != WEFOTA_HEADER_PROTOCOL) {
return 0;
}
return 1;
}
int init_wefota_server1_addr(void) {
char ip[16] = {0};
int port = 0;
get_wefota_server1_cfg(ip, &port);
return init_server_addr(&s_server1_addr, ip, port);
}
int init_wefota_server2_addr(const char *ip, int port) {
int ret = init_server_addr(&s_server2_addr, ip, port);
if(0 == ret) {
set_wefota_server2_cfg(ip, port);
}
return ret;
}
int recv_with_retry(int sock, struct sockaddr_in* server_addr,
unsigned char* response, size_t response_size, int max_retries) {
if (NULL == response || response_size < WEFOTA_HEADER_SIZE) {
return -1;
}
int retry_count = 0;
int recv_date_err = 0;
while (retry_count < max_retries) {
do {
recv_date_err = 0;
WeFOTAHeader *hdr = (WeFOTAHeader *)response;
int received = receive_message(sock, hdr, response_size, server_addr);
printf("received=%d\n", received);
if (received < WEFOTA_HEADER_SIZE) {
printf("recv header failed\n");
break;
}
if (0 == is_valid_resp_hdr(hdr)) {
printf("recv invalid header\n");
break;
}
printf("recv code=%d, count=%d)\n", hdr->code, hdr->count);
if (hdr->count + WEFOTA_HEADER_SIZE != received) {
printf("recv count error\n");
break;
}
if (s_status == FOTA_STATUS_GET_DIFF_PACK_DATA)
{
if (hdr->code == s_wefota_msg_table[s_status].resp_code && hdr->count == s_pack_date_count)
{
DiffPackDataResp * data = (DiffPackDataResp *)(s_resp + WEFOTA_HEADER_SIZE);
printf("proc_get_diff_pack_data recv [data->offset %d offset:%d][data->length %d length:%d]\n",
data->offset, s_diffpack_data_req.offset, data->length, s_diffpack_data_req.length);
if (data->offset == s_diffpack_data_req.offset || data->length == s_diffpack_data_req.length) {
return received;
}
}
printf("proc_get_diff_pack_data recv wrong data\n");
recv_date_err = 1;
break;
}
else
{
if (hdr->code == s_wefota_msg_table[s_status].resp_code
&& hdr->count == s_wefota_msg_table[s_status].resp_count) { // code and count right
return received;
} else { // code or count wrong
break;
}
}
}while(0);
printf("retry (%d/%d)\n", retry_count + 1, max_retries);
if (recv_date_err == 0)
{
retry_count++;
}
}
return -1;
}
#ifdef RECV_WHOLE_PACK
int send_with_retry(int sock, const unsigned char* msg, size_t len, struct sockaddr_in* server_addr,
unsigned char* response, size_t response_size, int max_retries) {
if (NULL == msg || NULL == response || 0 == len || response_size < WEFOTA_HEADER_SIZE) {
return -1;
}
int retry_count = 0;
while (retry_count < max_retries) {
do {
if (send_message(sock, msg, len, server_addr) < 0) {
printf("send message failed\n");
break;
}
#if 0
WeFOTAHeader *hdr = (WeFOTAHeader *)response;;
int received = receive_message(sock, hdr, response_size, server_addr);
printf("received=%d\n", received);
if (received < WEFOTA_HEADER_SIZE) {
printf("recv header failed\n");
break;
}
if (0 == is_valid_resp_hdr(hdr)) {
printf("recv invalid header\n");
break;
}
printf("recv code=%d, count=%d)\n", hdr->code, hdr->count);
if (hdr->count + WEFOTA_HEADER_SIZE != received) {
printf("recv count error\n");
break;
}
if (s_status == FOTA_STATUS_GET_DIFF_PACK_DATA)
{
if (hdr->code == s_wefota_msg_table[s_status].resp_code && hdr->count == s_pack_date_count)
{
return received;
}
else
{
return -1;
}
}
else
{
if (hdr->code == s_wefota_msg_table[s_status].resp_code
&& hdr->count == s_wefota_msg_table[s_status].resp_count) { // code and count right
return received;
} else { // code or count wrong
return -1;
}
}
#endif
int received = recv_with_retry(sock, server_addr, response, response_size, max_retries);
if (received > 0)
{
return received;
}
}while(0);
printf("retry (%d/%d)\n", retry_count + 1, max_retries);
retry_count++;
sleep(WEFOTA_TIMEOUT_SEC);
}
return -1;
}
#else
int send_with_retry(int sock, const unsigned char* msg, size_t len, struct sockaddr_in* server_addr,
unsigned char* response, size_t response_size, int max_retries) {
if (NULL == msg || NULL == response || 0 == len || response_size < WEFOTA_HEADER_SIZE) {
return -1;
}
int retry_count = 0;
while (retry_count < max_retries) {
do {
if (send_message(sock, msg, len, server_addr) < 0) {
printf("send message failed\n");
break;
}
WeFOTAHeader *hdr = (WeFOTAHeader *)response;;
int received = receive_message(sock, hdr, WEFOTA_HEADER_SIZE, server_addr);
printf("received=%d\n", received);
if (received != WEFOTA_HEADER_SIZE) {
printf("recv header failed\n");
break;
}
if (0 == is_valid_resp_hdr(hdr)) {
printf("recv invalid header\n");
break;
}
printf("recv code=%d, count=%d)\n", hdr->code, hdr->count);
if (hdr->count + WEFOTA_HEADER_SIZE > response_size) {
printf("recv count > response_size\n");
break;
}
if (hdr->code == s_wefota_msg_table[s_status].resp_code
&& hdr->count == s_wefota_msg_table[s_status].resp_count) { // code and count right
if (hdr->count == 0) {
return 0;
} else {
received = receive_message(sock, response + WEFOTA_HEADER_SIZE, hdr->count, server_addr);
printf("recv data len=%d\n", received);
return received;
}
} else { // code or count wrong
if (hdr->count == 0) {
return -1;
} else {
received = receive_message(sock, response + WEFOTA_HEADER_SIZE, hdr->count, server_addr);
printf("recv data len=%d, drop\n", received);
return -1;
}
}
}while(0);
printf("retry (%d/%d)\n", retry_count + 1, max_retries);
retry_count++;
sleep(WEFOTA_TIMEOUT_SEC);
}
return -1;
}
#endif
int proc_get_ip(int sock) {
int ret = -1;
WeFOTAHeader * hdr = (WeFOTAHeader *)s_req;
int count = wefota_header_init(hdr);
printf("proc_get_ip send code=%d, count=%d)\n", hdr->code, count);
if (0 > send_with_retry(sock, hdr, WEFOTA_HEADER_SIZE + count, &s_server1_addr, s_resp, sizeof(s_resp), WEFOTA_MAX_RETRIES)) {
printf("comm fail\n");
return ret;
}
ServerAddr * data = (ServerAddr *)(s_resp + WEFOTA_HEADER_SIZE);
ret = init_wefota_server2_addr(data->ip, (int)data->port);
return ret;
}
int proc_get_ip_1(int sock) {
set_fota_status(FOTA_STATUS_GET_IP_1);
return proc_get_ip(sock);
}
int proc_check_task(int sock) {
set_fota_status(FOTA_STATUS_CHECK_TASK);
int ret = -1;
WeFOTAHeader * hdr = (WeFOTAHeader *)s_req;
printf("proc_check_task header\n");
int count = wefota_header_init(hdr);
printf("proc_check_task send code=%d, count=%d)\n", hdr->code, count);
char originVersion [32] = {0};
get_version(originVersion);
memcpy(s_req + WEFOTA_HEADER_SIZE, originVersion, sizeof(originVersion));
printf("proc_check_task originVersion:[%s]\n", originVersion);
if (0 > send_with_retry(sock, hdr, WEFOTA_HEADER_SIZE + count, &s_server2_addr, s_resp, sizeof(s_resp), WEFOTA_MAX_RETRIES)) {
printf("comm fail\n");
return ret;
}
FotaTask * data = (FotaTask *)(s_resp + WEFOTA_HEADER_SIZE);
printf("proc_check_task recv:[flag:%d][interval:%d][delay:%d][destVersion:%s]\n", data->flag, data->interval, data->delay, data->destVersion);
if (data->flag == 1) {
strncpy(s_destVersion, data->destVersion, sizeof(s_destVersion));
printf("exist fota task\n");
return 0;
} else {
printf("no fota task\n");
return ret;
}
}
int proc_get_ip_2(int sock) {
set_fota_status(FOTA_STATUS_GET_IP_2);
return proc_get_ip(sock);
}
int proc_get_ver_id(int sock) {
set_fota_status(FOTA_STATUS_GET_VER_ID);
int ret = -1;
WeFOTAHeader * hdr = (WeFOTAHeader *)s_req;
int count = wefota_header_init(hdr);
printf("proc_get_ver_id send code=%d, count=%d)\n", hdr->code, count);
Version version = {0};
get_version(version.orig_version);
strncpy(version.dest_version, s_destVersion, sizeof(version.dest_version));
strcpy(version.product, WEFOTA_PRODUCT_ID);
memcpy(s_req + WEFOTA_HEADER_SIZE, &version, sizeof(version));
if (0 > send_with_retry(sock, hdr, WEFOTA_HEADER_SIZE + count, &s_server2_addr, s_resp, sizeof(s_resp), WEFOTA_MAX_RETRIES)) {
printf("comm fail\n");
return ret;
}
VerID * data = (VerID *)(s_resp + WEFOTA_HEADER_SIZE);
s_verID = *data;
return 0;
}
int proc_get_diff_pack_id(int sock) {
set_fota_status(FOTA_STATUS_GET_DIFF_PACK_ID);
int ret = -1;
WeFOTAHeader * hdr = (WeFOTAHeader *)s_req;
int count = wefota_header_init(hdr);
printf("proc_get_diff_pack_id send code=%d, count=%d)\n", hdr->code, count);
memcpy(s_req + WEFOTA_HEADER_SIZE, &s_verID, sizeof(s_verID));
if (0 > send_with_retry(sock, hdr, WEFOTA_HEADER_SIZE + count, &s_server2_addr, s_resp, sizeof(s_resp), WEFOTA_MAX_RETRIES)) {
printf("comm fail\n");
return ret;
}
DiffPackInfo * data = (DiffPackInfo *)(s_resp + WEFOTA_HEADER_SIZE);
s_diffpack_info = *data;
printf("proc_get_diff_pack_id [diffPackID:%s][MD5:%s][size:%d]\n", s_diffpack_info.diffPackID, s_diffpack_info.MD5, s_diffpack_info.size);
if (s_diffpack_info.size == 0) {
printf("diff pack size==0\n");
return ret;
}
return 0;
}
int proc_get_diff_pack_data(int sock) {
set_fota_status(FOTA_STATUS_GET_DIFF_PACK_DATA);
unsigned int startTime = time(NULL);
int ret = -1;
int recv_packet_retry = 0;
WeFOTAHeader * hdr = (WeFOTAHeader *)s_req;
int count = wefota_header_init(hdr);
printf("proc_get_diff_pack_data send code=%d, count=%d)\n", hdr->code, count);
system("rm -rf /cache/zte_fota");
system("mkdir /cache/zte_fota");
FILE *fp = fopen(FOTA_DOWNLOAD_FILEPATH, "wb");
if (NULL == fp) {
printf("open file failed\n");
return ret;
}
unsigned int size = s_diffpack_info.size;
while (size > 0) {
unsigned int len = size > WEFOTA_DIFF_PACK_DATA_MAX_LEN ? WEFOTA_DIFF_PACK_DATA_MAX_LEN : size;
s_pack_date_count = len + 39;
unsigned int offset = s_diffpack_info.size - size;
DiffPackDataReq req = {0};
memcpy(req.diffPackID, s_diffpack_info.diffPackID, sizeof(req.diffPackID));
req.length = len;
req.offset = offset;
printf("proc_get_diff_pack_data request [offset %d][req.diffPackID %s][len %d][s_pack_date_count:%d][offset %d]\n",
offset, req.diffPackID, len, s_pack_date_count, offset);
memcpy(s_req + WEFOTA_HEADER_SIZE, &req, sizeof(req));
s_diffpack_data_req = req;
if (0 > send_with_retry(sock, hdr, WEFOTA_HEADER_SIZE + count, &s_server2_addr, s_resp, sizeof(s_resp), WEFOTA_MAX_RETRIES)) {
printf("comm fail\n");
fclose(fp);
return ret;
}
DiffPackDataResp * data = (DiffPackDataResp *)(s_resp + WEFOTA_HEADER_SIZE);
printf("proc_get_diff_pack_data recv [data->offset %d offset:%d][data->length %d en:%d]\n", data->offset, offset, data->length, len);
if (data->offset != offset || data->length != len) {
printf("offset or len error\n");
if (recv_packet_retry < 3)
{
printf("offset error, retry\n");
recv_packet_retry++;
continue;
}
fclose(fp);
return ret;
}
fwrite(data->data, 1, len, fp);
size -= len;
recv_packet_retry = 0;
}
fclose(fp);
s_costTime = time(NULL) - startTime;
return 0;
}
int proc_get_diff_pack_end(int sock) {
set_fota_status(FOTA_STATUS_GET_DIFF_PACK_END);
int ret = -1;
WeFOTAHeader * hdr = (WeFOTAHeader *)s_req;
int count = wefota_header_init(hdr);
printf("proc_get_diff_pack_end send code=%d, count=%d)\n", hdr->code, count);
DiffPackEnd end = {0};
memcpy(end.diffPackID, s_diffpack_info.diffPackID, sizeof(end.diffPackID));
end.costTime = s_costTime;
memcpy(s_req + WEFOTA_HEADER_SIZE, &end, sizeof(end));
if (0 > send_with_retry(sock, hdr, WEFOTA_HEADER_SIZE + count, &s_server2_addr, s_resp, sizeof(s_resp), WEFOTA_MAX_RETRIES)) {
printf("comm fail\n");
return ret;
}
return 0;
}
static int verify_md5(const unsigned char *expected_md5, const char *file_path)
{
char command[256];
char expected_md5_str[33];
char md5sum_output[33];
int i = 0;
snprintf(command, sizeof(command), "md5sum \"%s\"", file_path);
FILE *pipe = popen(command, "r");
if (!pipe)
{
printf("verify_md5 pipe error\n");
return -1;
}
if (fgets(md5sum_output, sizeof(md5sum_output), pipe) == NULL)
{
printf("verify_md5 fgets error\n");
pclose(pipe);
return -1;
}
pclose(pipe);
for (i = 0; i < 16; ++i)
{
sprintf(expected_md5_str + i * 2, "%02x", expected_md5[i]);
}
if (strncmp(expected_md5_str, md5sum_output, 32) == 0)
{
printf("md5 check OK\n");
return 1;
}
else
{
printf("md5 check error\n");
return 0;
}
}
int proc_install_diff_pack(void)
{
const char *file_path = "/cache/zte_fota/delta.package";
int result = 0;
printf("**********proc_install_diff_pack begin \n");
set_fota_status(FOTA_STATUS_INSTALL_DIFF_PACK);
result = verify_md5(s_diffpack_info.MD5, file_path);
if (result == 1)
{
return start_wefota_install();
}
else
{
return -1;
}
}
int wefota_proc(void) {
printf("**********wefota_proc\n");
int ret = -1;
int sock = -1;
do {
sock = create_udp_socket();
if (sock < 0) {
printf("**********create_udp_socket socket < 0 \n");
break;
}
ret = init_wefota_server1_addr();
if (ret < 0) {
printf("**********init_wefota_server1_addr error \n");
break;
}
ret = proc_get_ip_1(sock);
if (ret < 0) {
printf("**********proc_get_ip_1 error \n");
break;
}
ret = proc_check_task(sock);
if (ret < 0) {
printf("**********proc_check_task error \n");
break;
}
ret = proc_get_ip_2(sock);
if (ret < 0) {
printf("**********proc_get_ip_2 error \n");
break;
}
ret = proc_get_ver_id(sock);
if (ret < 0) {
printf("**********proc_get_ver_id error \n");
break;
}
ret = proc_get_diff_pack_id(sock);
if (ret < 0) {
printf("**********proc_get_diff_pack_id error \n");
break;
}
ret = proc_get_diff_pack_data(sock);
if (ret < 0) {
printf("**********proc_get_diff_pack_data error \n");
break;
}
ret = proc_get_diff_pack_end(sock);
close_udp_socket(sock);
sock = -1;
ret = proc_install_diff_pack();
}while(0);
if (sock >= 0) {
close_udp_socket(sock);
}
return ret;
}
int main(void) {
printf("**********main\n");
while (1) {
wait_fota_conditions();
wefota_proc();
}
return 0;
}