#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; | |
} |