#include #include #include "cJSON.h" #include "ql_http_client.h" #include "ql_http_client.h" #include "ql_fota.h" #include "ql_dev.h" #include "ql_nw.h" #include "ql_fs.h" #include "app_inc.h" #if 1 const static SSLCertPathPtr rootCA_path = "\ -----BEGIN CERTIFICATE-----\n\ MIIE5zCCA0+gAwIBAgIJANUsoTOuGtIeMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\n\ VQQGEwJDTjELMAkGA1UECAwCQUgxCzAJBgNVBAcMAkhGMRAwDgYDVQQKDAdRVUVD\n\ VEVMMQwwCgYDVQQLDANEVFcxGDAWBgNVBAMMDzIyMC4xODAuMjM5LjIxMjEmMCQG\n\ CSqGSIb3DQEJARYXZWRkaWUuemhhbmdAcXVlY3RlbC5jb20wHhcNMjAwMTAyMTEy\n\ NTQzWhcNMjMwMTAxMTEyNTQzWjCBiTELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkFI\n\ MQswCQYDVQQHDAJIRjEQMA4GA1UECgwHUVVFQ1RFTDEMMAoGA1UECwwDRFRXMRgw\n\ FgYDVQQDDA8yMjAuMTgwLjIzOS4yMTIxJjAkBgkqhkiG9w0BCQEWF2VkZGllLnpo\n\ YW5nQHF1ZWN0ZWwuY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA\n\ tDYkNFB5TYS7XZ2F+eW6zGWOmy2xV3OcTpnz10JHUwSdvUI5xWQ//ACCxG9QeN4f\n\ ALAzkj8tVzeKj5oP9Gz8LnVqhIxv13m8GJDO/dVZEXtpBNgjv7DvsXa1TMjy3QcV\n\ bXfqtWuTSzVCovMkvj+R16uWRWgqSMLCG73FLPE2E2vRGlBQVzAVi2fXYPq346QT\n\ ZLyELoFErGCFgVEaAF1Pnwu1R8Ly0CI45y/riC47Sb3bE/MaBUbR0R7+T5jhnK8G\n\ E0GTLorOZq6CBf8NliRjnEQVtjhUniQju1Dx/35Tifel460kK9ThkmxEddn1w+VH\n\ ZQYG9XWuqdPA6am5rBI+AKUCPeoMRVVlY3lK3J7L4OyRTovY0+IyVT4MKucrzK4z\n\ FfnACTgKr151yMxY3Ar4EPI1iQeuKu5Ha2bZuXLnVZau8NohbdUXBSN+ifPH2uu7\n\ BT91jG6zfS9k6AKhBkGncf0dpuT9c6w06UAplxeakSpnSz5p7O9XGeAZeemahq43\n\ AgMBAAGjUDBOMB0GA1UdDgQWBBSHgJS+a77WT6PHLTVoW+qqVK80uTAfBgNVHSME\n\ GDAWgBSHgJS+a77WT6PHLTVoW+qqVK80uTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3\n\ DQEBCwUAA4IBgQA6WSdvLq+MMmNJAAI8XCANzWq69fxcrvRhLl69hipueomivrFx\n\ cqiG6oI38CBxqiPC9y69fXBY9B7f29emMHnjpC5xoOqfBSVKqR+EbhYUx/n0/Ykx\n\ Pcz6Lad0/8JRLa0QthhnLzMPpeAY7Z3HmcHR0mZFu+vu0irw/3E1GkDm2MQ2958Y\n\ 5geLGbktFKF2yGueajcoR8qSmeD+tspBqTWqmdPaDEipPNBvLduOzcGqOnQMKy4/\n\ LLQMZ/OuXTjuJjYE4YtN2wV3/ks02Ae94FE8ZaaMYThMHBz4NITKbLhbMn9cP66w\n\ 27B+nt5+DG4zc9AYZRuKhaW6AiMfAewAvFxIyofmPxAKMpC+JBwzDxdbo0ez/Dqr\n\ CFbKuQeWAY3YwgG33pdzOuREMphdGZnJgkd1MqUCNFxMGnZF6WhV31I/e1+uCMYr\n\ 4Rw86GtDfs697qxBOXHmNBVqLLekayQxGh7d2UxIVghdCuO6rHjTfmkfvzNH/Vxf\n\ t/YY6UlQvij187Q=\n\ -----END CERTIFICATE-----\n\ "; #define QL_DL_HTTP_LOG ql_trace #define QL_DL_PACK_NAME_MAX_LEN (64) #define QL_DL_PACK_URL_MAX_LEN (128) #define TRY_DOWN_TIMES 1 #define WRITE_TO_FILESIZE (1024*4) typedef enum { DL_HTTP_DOWN_INIT, //初始阶段 DL_HTTP_DOWN_DOWNING, //下载中 DL_HTTP_DOWN_INTR, //下载被中断 DL_HTTP_DOWN_DOWNED, //下载完成 DL_HTTP_DOWN_NOSPACE, //没有空间 }e_dl_down_stage; typedef struct { bool is_show; //是否显示进度 uint total_size; //文件总共大小 uint dload_size; //已经下载大小 uint file_size; //上次升级中断保存的文件大小 }dl_http_progress_t; typedef struct { QL_HTTP_CLIENT_T *http_cli; //和http交互创建的struct http_client_s类型的指针 int profile_idx; //cid uint8_t sim_id; //simid char dl_path[QL_DL_PACK_NAME_MAX_LEN]; //下载到本地的升级文件的位置 char dl_url[QL_DL_PACK_URL_MAX_LEN]; dl_http_progress_t http_progress; //http进度 e_dl_down_stage e_stage; //http下载固件包的阶段 QFILE *fd; //写文件的文件描述符 int i_save_size; //在一次下载的过程中,分为多次写入,保存的是上次的写入大小,用于控制满多少字节写一次 uint last_precent; //下载最后一次百分比 bool b_is_have_space; //存储空间是否可用 ql_sem_t dl_http_semp; }dl_http_client_t; static int dl_http_get_fileszie(char *filename); static void dl_http_close_fd(dl_http_client_t* dl_http_cli_p); int dl_dload_file_clran(dl_http_client_t* dl_http_cli_p) { if ( dl_http_cli_p->fd == NULL ) { QL_DL_HTTP_LOG("clran write file [%s] err",dl_http_cli_p->dl_path); dl_http_cli_p->fd = NULL; } else { ql_fclose(dl_http_cli_p->fd); ql_rtos_task_sleep_ms(10); } dl_http_cli_p->fd = ql_fopen(dl_http_cli_p->dl_path, "wb+"); if(dl_http_cli_p->fd == NULL) { QL_DL_HTTP_LOG("clran open write file [%s] failed",dl_http_cli_p->dl_path); return -1; } dl_http_cli_p->http_progress.file_size = 0; dl_http_cli_p->http_progress.dload_size = 0; dl_http_cli_p->http_progress.total_size = 0; dl_http_cli_p->e_stage = DL_HTTP_DOWN_DOWNING; dl_http_cli_p->i_save_size = 0; QL_DL_HTTP_LOG("clran write file [%s] open ",dl_http_cli_p->dl_path); return 0; } static void dl_http_info_cfg(dl_http_client_t* dl_http_cli_p) { if ( dl_http_cli_p == NULL ) { QL_DL_HTTP_LOG("dl_http_cli_p is null"); return; } QL_DL_HTTP_LOG("init file name:[%s]",dl_http_cli_p->dl_path); QL_DL_HTTP_LOG("init file stage:[%d]",dl_http_cli_p->e_stage); QL_DL_HTTP_LOG("init file download:[%d]",dl_http_cli_p->http_progress.dload_size); QL_DL_HTTP_LOG("init file file_size:[%d]",dl_http_cli_p->http_progress.file_size); QL_DL_HTTP_LOG("init file real file_size:[%d]",dl_http_get_fileszie(dl_http_cli_p->dl_path)); QL_DL_HTTP_LOG("init file is_show:[%d]",dl_http_cli_p->http_progress.is_show); QL_DL_HTTP_LOG("init file last_percent:[%d]",dl_http_cli_p->last_precent); QL_DL_HTTP_LOG("init file space:[%d]",dl_http_cli_p->b_is_have_space); } int dl_http_init(dl_http_client_t* dl_http_cli_p, char *filepath, char *uri) { QFILE *fd = NULL; // 安全修复:检查参数有效性 if(dl_http_cli_p == NULL || filepath == NULL || uri == NULL){ QL_DL_HTTP_LOG("dl_http_init: invalid parameters"); return -1; } memset(dl_http_cli_p,0x00,sizeof(dl_http_client_t)); dl_http_cli_p->http_cli = 0; //http连接句柄 dl_http_cli_p->profile_idx = 1; //cid dl_http_cli_p->sim_id = 0; //simid dl_http_cli_p->e_stage =DL_HTTP_DOWN_INIT; dl_http_cli_p->i_save_size = 0; // 安全修复:使用strncpy并确保字符串结束 size_t path_len = strlen(filepath); if(path_len >= sizeof(dl_http_cli_p->dl_path)){ QL_DL_HTTP_LOG("dl_http_init: filepath too long"); return -1; } strncpy(dl_http_cli_p->dl_path, filepath, sizeof(dl_http_cli_p->dl_path)-1); dl_http_cli_p->dl_path[sizeof(dl_http_cli_p->dl_path)-1] = '\0'; size_t uri_len = strlen(uri); if(uri_len >= sizeof(dl_http_cli_p->dl_url)){ QL_DL_HTTP_LOG("dl_http_init: uri too long"); return -1; } strncpy(dl_http_cli_p->dl_url, uri, sizeof(dl_http_cli_p->dl_url)-1); dl_http_cli_p->dl_url[sizeof(dl_http_cli_p->dl_url)-1] = '\0'; ql_rtos_semaphore_create(&dl_http_cli_p->dl_http_semp, 0); //存储空间开始默认为足够 dl_http_cli_p->b_is_have_space = TRUE; dl_http_cli_p->http_progress.is_show = FALSE; //设置展示进度 dl_http_cli_p->last_precent = 0; fd = ql_fopen(dl_http_cli_p->dl_path, "w+"); if(fd == NULL) { QL_DL_HTTP_LOG("init file name:[%s] err",dl_http_cli_p->dl_path); return -1; } ql_fclose(fd); QL_DL_HTTP_LOG("init file name:[%s]",dl_http_cli_p->dl_path); QL_DL_HTTP_LOG("init file size:[%d]",dl_http_get_fileszie(dl_http_cli_p->dl_path)); QL_DL_HTTP_LOG("init file stage:[%d]",dl_http_cli_p->e_stage); return 0; } static void dl_http_release(dl_http_client_t* dl_http_cli_p) { if(dl_http_cli_p->dl_http_semp==NULL)return; ql_rtos_semaphore_delete(dl_http_cli_p->dl_http_semp); //不设置成NULL 会导致restart dl_http_cli_p->dl_http_semp = NULL; } static int dl_http_get_fileszie(char *filename) { int file_size= 0; QFILE *fd = ql_fopen(filename,"r"); if ( fd == NULL ) { QL_DL_HTTP_LOG("open file name:[%s] err",filename); return -1; } file_size = ql_fsize(fd); ql_fclose(fd); return file_size; } static QFILE *dl_http_get_fd(dl_http_client_t* dl_http_cli_p) { if ( dl_http_cli_p->e_stage == DL_HTTP_DOWN_INIT || dl_http_cli_p->e_stage ==DL_HTTP_DOWN_DOWNED \ ||dl_http_cli_p->e_stage == DL_HTTP_DOWN_NOSPACE ) { //已经完成、初始化、或者是没有空间导致的下载中断以覆盖写来打开文件 dl_http_cli_p->fd = ql_fopen(dl_http_cli_p->dl_path, "wb+"); dl_http_cli_p->http_progress.file_size = 0; dl_http_cli_p->http_progress.dload_size = 0; dl_http_cli_p->http_progress.total_size = 0; dl_http_cli_p->e_stage = DL_HTTP_DOWN_INIT; dl_http_cli_p->i_save_size = 0; QL_DL_HTTP_LOG("over write file [%s]",dl_http_cli_p->dl_path); } else { //其他的情况是追加方式打开文件 dl_http_cli_p->fd = ql_fopen(dl_http_cli_p->dl_path, "ab+"); QL_DL_HTTP_LOG("add write file [%s]",dl_http_cli_p->dl_path); } if ( dl_http_cli_p->fd == NULL ) { QL_DL_HTTP_LOG("ql_fopen failed"); } return dl_http_cli_p->fd; } /******************************************************************** * funcname :dl_http_close_fd * description : * 关闭下载升级包的文件描述符 * dl_http_cli_p [in] [dl_http_client_t *] fota http客户端结构体 * return: * 0 -- sucess * other -- failed **********************************************************************/ static void dl_http_close_fd(dl_http_client_t* dl_http_cli_p) { if ( dl_http_cli_p->fd > 0 ) { ql_fclose(dl_http_cli_p->fd); dl_http_cli_p->fd = NULL; } } static int http_dl_response_cb( QL_HTTP_CLIENT_T *client, QL_HTTP_CLIENT_EVENT_E event, int status_code, char *data, int data_len, void *private_data) { int ret=0,write_ret=0; char para[64]={0}; dl_http_client_t* dl_http_cli_p = private_data; static int recv_len = 0; switch(event) { case QL_HTTP_CLIENT_EVENT_SEND_FAIL: QL_DL_HTTP_LOG("http send failed!\n"); dl_http_cli_p->e_stage = DL_HTTP_DOWN_INTR; break; case QL_HTTP_CLIENT_EVENT_SEND_SUCCESSED: QL_DL_HTTP_LOG("http send successed!\n"); break; case QL_HTTP_CLIENT_EVENT_RECV_HEADER_FAIL: QL_DL_HTTP_LOG("http parse response header failed!\n"); dl_http_cli_p->e_stage = DL_HTTP_DOWN_INTR; break; case QL_HTTP_CLIENT_EVENT_RECV_HEADER_FINISHED: QL_DL_HTTP_LOG("http recv header status_code:%d;header_len:%d!\n",status_code,data_len); ret=ql_http_client_get_header(data,"Content-Length",0,para,sizeof(para)); if(ret>0){ dl_http_cli_p->http_progress.total_size = atoi(para); QL_DL_HTTP_LOG("Content-length[]:%d!\n",dl_http_cli_p->http_progress.total_size); } if(status_code==200) QL_DL_HTTP_LOG("http recv response ok!\n"); ret=1; //��������body���ݣ�����0������������body���� break; case QL_HTTP_CLIENT_EVENT_RECV_BODY: QL_DL_HTTP_LOG("http recv body status_code:%d;recv_body_len:%d!\n",status_code,data_len); dl_http_cli_p->http_progress.dload_size+=data_len; write_ret = ql_fwrite((void *)data, data_len,1,dl_http_cli_p->fd); QL_DL_HTTP_LOG("write_ret:%d",write_ret); if(write_ret!=data_len) { QL_DL_HTTP_LOG("*** fota image write fail ***"); ret =0; break; } QL_DL_HTTP_LOG("dl progress %d",(dl_http_cli_p->http_progress.dload_size*100)/dl_http_cli_p->http_progress.total_size); ret=1; //��������body���ݣ�����0������������body���� break; case QL_HTTP_CLIENT_EVENT_RECV_BODY_FINISHED: dl_http_cli_p->e_stage = DL_HTTP_DOWN_DOWNED; QL_DL_HTTP_LOG("http recv body finished!\n"); break; case QL_HTTP_CLIENT_EVENT_DISCONNECTED: QL_DL_HTTP_LOG("http be closed by server!\n"); dl_http_cli_p->e_stage = DL_HTTP_DOWN_INTR; break; default: break; } return ret; } int utils_parse_http_url(char *address, char *host, int *port) { const char *data = address; char *pos = NULL; char hostname[64] = {0}; // If prefix is 'http://' ? if (!memcmp(data, "http", 4)) { if (*(data + 4) == 's') { // https ? if (!memcmp(data, "https://", 8)) { data += 8; } } else if (*(data + 4) == ':') { if (!memcmp(data, "http://", 7)) { data += 7; } } } pos = strchr(data, '/'); if (pos == NULL) { RLOGD("ftp url is not match"); } memcpy(hostname, data, pos - data); pos = strchr(hostname, ':'); if (pos) { *port = atoi(pos + 1); *pos = 0; strcpy(host,hostname); } else { *port = 80; } } /*********************************************************** * funcname :dl_http_active * description : * 初始化http请求的网络环境,组建http请求报文,发起http请求 * return: * 0 -- sucess * other -- failed ************************************************************/ static int dl_http_evn_request(dl_http_client_t* dl_http_cli_p) { int ret; char hostname[128]={0}; int port=80; //发送http请求前创建存储升级包文件的文件描述符,别忘关闭 if ( dl_http_get_fd(dl_http_cli_p) == NULL ) { QL_DL_HTTP_LOG("range_request http data done ,file_size[%d]",dl_http_cli_p->http_progress.file_size); return -1; } if (!strncmp(dl_http_cli_p->dl_url,"https:",6)){ SSLConfig sslConfig = { .en = 1, .profileIdx = 1, .serverName = "220.180.239.212", .serverPort = 80, .protocol = 0, .dbgLevel = 0, .sessionReuseEn = 0, .vsn = SSL_VSN_ALL, .verify = SSL_VERIFY_MODE_OPTIONAL, .cert.from = SSL_CERT_FROM_BUF, .cert.path.rootCA = rootCA_path, .cert.path.clientKey = NULL, .cert.path.clientCert = NULL, .cert.clientKeyPwd.data = NULL, .cert.clientKeyPwd.len = 0, .cipherList = "ALL", .CTRDRBGSeed.data = NULL, .CTRDRBGSeed.len = 0 }; utils_parse_http_url(dl_http_cli_p->dl_url,hostname,&port); sslConfig.serverName = hostname; sslConfig.serverPort = port; QL_DL_HTTP_LOG("server:%s, port %d",sslConfig.serverName,sslConfig.serverPort); ql_http_client_setopt(dl_http_cli_p->http_cli, QL_HTTP_CLIENT_OPT_SSL_CTX, &sslConfig); } ql_http_client_setopt(dl_http_cli_p->http_cli, QL_HTTP_CLIENT_OPT_ASYN, 0); //ͬ��ģʽ ql_http_client_setopt(dl_http_cli_p->http_cli, QL_HTTP_CLIENT_OPT_PDP_CID, dl_http_cli_p->profile_idx); ql_http_client_setopt(dl_http_cli_p->http_cli, QL_HTTP_CLIENT_OPT_PROTOCOL_VER, 1); QL_DL_HTTP_LOG("dl_client:%p address:%s",dl_http_cli_p->http_cli,dl_http_cli_p->dl_url); ret = ql_http_client_request(dl_http_cli_p->http_cli,dl_http_cli_p->dl_url,QL_HTTP_CLIENT_REQUEST_GET,QL_HTTP_CLIENT_AUTH_TYPE_NONE,NULL,NULL,NULL,0,http_dl_response_cb,dl_http_cli_p); if (ret == 0) { #if 0 //阻塞等待信号量 if (ql_rtos_semaphore_wait(dl_http_cli_p->dl_http_semp, 120000) != 0 ) { //获取信号量失败 ql_http_client_release(dl_http_cli_p->http_cli); dl_http_close_fd(dl_http_cli_p); return -1; } #endif QL_DL_HTTP_LOG("http dload size %d=====End,\n",dl_http_cli_p->http_progress.dload_size); ql_http_client_release(dl_http_cli_p->http_cli); QL_DL_HTTP_LOG("http release sucess!!!"); dl_http_close_fd(dl_http_cli_p); return 0; } QL_DL_HTTP_LOG("http ql_http_client_request err %d!!!",ret); ql_http_client_release(dl_http_cli_p->http_cli); dl_http_close_fd(dl_http_cli_p); return -3; } static int dl_http_download_customfile(dl_http_client_t* dl_http_cli_p) { dl_http_info_cfg(dl_http_cli_p); //组http请求报文,发送http请求,阻塞到下载完成或异常 if (dl_http_evn_request(dl_http_cli_p) != 0) { int file_size = dl_http_get_fileszie(dl_http_cli_p->dl_path); QL_DL_HTTP_LOG("failed [%s] size[%d]",dl_http_cli_p->dl_path,file_size); return -1; } dl_http_info_cfg(dl_http_cli_p); return 0; } int hal_http_client_download(char *url, char *file_path) { int ret = -1; dl_http_client_t dl_http_cli; uint8 ui_down_times = TRY_DOWN_TIMES; INT32 file_free_size = ql_internal_fs_free_size_get(); QL_DL_HTTP_LOG("fs free size get:0x%x",file_free_size); //下载前初始化 if(dl_http_init(&dl_http_cli,file_path, url) != 0) { QL_DL_HTTP_LOG("http download init failed"); goto exit; } //尝试下载最多十次 while( ui_down_times-- ) { QL_DL_HTTP_LOG("start [%d] times download file packge",TRY_DOWN_TIMES-ui_down_times); if ( dl_http_download_customfile(&dl_http_cli) == 0 ) { //下载完成 ret = 0; break; } if ( dl_http_cli.b_is_have_space != TRUE ) { //空间不够,删除文件 ql_remove(dl_http_cli.dl_path); QL_DL_HTTP_LOG("have no space"); break; } //下载失败等待5s重新开始下载 ql_rtos_task_sleep_s(5); } exit: dl_http_release(&dl_http_cli); QL_DL_HTTP_LOG("exit hal_http_client_download"); return ret; } int http_ota_fw_download(char *url) { (void)url; RLOGE("legacy HTTP polling FULLOTA1 is disabled; use MQTT FULLOTA2 command\r\n"); return -1; } typedef struct recv_buf { uint8_t *buf; int buf_len; int recv_len; int total_len; }http_recv_buf; #define PRINT_BUF_SIZE 65 static char print_buf[PRINT_BUF_SIZE]; void print_string(const char * string,int len) { int printed = 0; while (printed != len) { if ((len - printed) > (PRINT_BUF_SIZE - 1)) { memcpy(print_buf, string + printed, (PRINT_BUF_SIZE - 1)); printed += (PRINT_BUF_SIZE - 1); print_buf[PRINT_BUF_SIZE - 1] = '\0'; } else { snprintf(print_buf,len - printed+1, "%s", string + printed); printed = len; } printf("%s", print_buf); } printf("\n"); } static int response_cb( QL_HTTP_CLIENT_T *client, QL_HTTP_CLIENT_EVENT_E event, int status_code, char *data, int data_len, void *private_data) { int ret=0; char para[64]={0}; http_recv_buf *recvbuf = (http_recv_buf *)private_data; switch(event) { case QL_HTTP_CLIENT_EVENT_SEND_FAIL: printf("http send failed!\n"); break; case QL_HTTP_CLIENT_EVENT_SEND_SUCCESSED: printf("http send successed!\n"); break; case QL_HTTP_CLIENT_EVENT_RECV_HEADER_FAIL: printf("http parse response header failed!\n"); break; case QL_HTTP_CLIENT_EVENT_RECV_HEADER_FINISHED: printf("http recv header status_code:%d;header_len:%d!\n",status_code,data_len); print_string(data,data_len); ret=ql_http_client_get_header(data,"Content-Type",0,para,sizeof(para)); recvbuf->total_len = atoi(para); if(ret>0) printf("Content-Type[len:%d]:%s!\n",ret,para); if(status_code==200) printf("http recv response ok!\n"); ret=1; //继续接受body数据,返回0,不继续接受body数据 break; case QL_HTTP_CLIENT_EVENT_RECV_BODY: printf("http recv body status_code:%d;recv_body_len:%d!\n",status_code,data_len); print_string(data,data_len); if(recvbuf->recv_len+data_len<=recvbuf->buf_len){ memcpy(recvbuf->buf+recvbuf->recv_len,data,data_len); ret=1; //继续接受body数据,返回0,不继续接受body数据 recvbuf->recv_len += data_len; }else{ ret = 0; } break; case QL_HTTP_CLIENT_EVENT_RECV_BODY_FINISHED: printf("http recv body finished!\n"); break; case QL_HTTP_CLIENT_EVENT_DISCONNECTED: printf("http be closed by server!\n"); break; default: break; } return ret; } int hal_http_client_post(char *url, char *header, char *send, int send_len, char *recvbuf, int *recvlen) { int ret; struct http_client * client = NULL; struct http_client_list * header_list = NULL; http_recv_buf httprecvbuf; httprecvbuf.buf = recvbuf; httprecvbuf.buf_len = *recvlen; httprecvbuf.recv_len = 0; client = ql_http_client_init(); if(client){ ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_PDP_CID, 1); /*set PDP cid,if not set,using default PDP*/ ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_PROTOCOL_VER, 1); /*"0" is HTTP 1.1, "1" is HTTP 1.0*/ ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_ENABLE_COOKIE, 1); /*"0" is HTTP 1.1, "1" is HTTP 1.0*/ header_list=ql_http_client_list_append(header_list, header); ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_HTTPHEADER, header_list); if(ret==QL_HTTP_CLIENT_ERR_LAST_REQUEST_NOT_FINISH) { printf("last request not finish, not to set!\n"); } ret=ql_http_client_request(client,url,QL_HTTP_CLIENT_REQUEST_POST,QL_HTTP_CLIENT_AUTH_TYPE_NONE,NULL,NULL,send,send_len,response_cb,&httprecvbuf); if(ret==QL_HTTP_CLIENT_ERR_LAST_REQUEST_NOT_FINISH) { printf("last request not finish, can not to request again!\n"); } ql_http_client_list_destroy(header_list); ql_http_client_release(client); *recvlen = httprecvbuf.recv_len; printf("ql_http_client_request ret=%d!\n",ret); return ret; } return -1; } int hal_http_client_get(char *url, char *recvbuf, int *recvlen) { int ret; struct http_client * client = NULL; //struct http_client_list * header_list = NULL; http_recv_buf httprecvbuf; httprecvbuf.buf = recvbuf; httprecvbuf.buf_len = *recvlen; httprecvbuf.recv_len = 0; client = ql_http_client_init(); if(client){ ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_PDP_CID, 1); /*set PDP cid,if not set,using default PDP*/ ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_PROTOCOL_VER, 1); /*"0" is HTTP 1.1, "1" is HTTP 1.0*/ ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_ENABLE_COOKIE, 1); /*"0" is HTTP 1.1, "1" is HTTP 1.0*/ //header_list=ql_http_client_list_append(header_list, header); //ret=ql_http_client_setopt(client, QL_HTTP_CLIENT_OPT_HTTPHEADER, header_list); //if(ret==QL_HTTP_CLIENT_ERR_LAST_REQUEST_NOT_FINISH) //{ // printf("last request not finish, not to set!\n"); //} ret=ql_http_client_request(client,url,QL_HTTP_CLIENT_REQUEST_GET,QL_HTTP_CLIENT_AUTH_TYPE_NONE,NULL,NULL,NULL,0,response_cb,&httprecvbuf); if(ret==QL_HTTP_CLIENT_ERR_LAST_REQUEST_NOT_FINISH) { printf("last request not finish, can not to request again!\n"); } //ql_http_client_list_destroy(header_list); ql_http_client_release(client); *recvlen = httprecvbuf.recv_len; printf("ql_http_client_request ret=%d!\n",ret); return ret; } return -1; } ///////////////////////////////////////////////////////////OTA////////////////////////////////////////////////////////////////// int app_http_post_ota_report(); int app_http_post_bind() { char sn[32]={0}; char model[32]={0}; int ret = -1; char *response = NULL; char *header = NULL; int resp_len = 0; char *url = "http://test.afaitoys.com/v1/device/bind"; char *post_data=NULL; cJSON *recv; cJSON *root = cJSON_CreateObject(); char *uuid = "testuuid"; hal_os_get_device_id(sn); hal_os_get_model(model); cJSON_AddItemToObject(root,"user_uuid",cJSON_CreateString(uuid)); cJSON_AddItemToObject(root,"model",cJSON_CreateString(model)); post_data = cJSON_PrintUnformatted(root); if(post_data==NULL)goto error; response = hal_os_malloc(4096); if(response==NULL)goto error; resp_len = 4096; header = hal_os_malloc(1024); if(header==NULL)goto error; sprintf(header, "Content-Type: application/json\r\nX-SERIAL-NO: %s", sn); if (hal_http_client_post(url, header, post_data, strlen(post_data), response, &resp_len) < 0) { RLOGE("webclient send post request failed."); goto error; } RLOGD("app_http_post_bind post response data: %s\n",response); recv = cJSON_Parse(response); if(recv){ cJSON *status = cJSON_GetObjectItem(recv,"status"); if(status && !strcmp("success",status->valuestring)){ cJSON *code = cJSON_GetObjectItem(recv,"code"); if(code && code->valueint == 200){ ret = 0; RLOGD("bind okay."); }else{ ret = -4; } }else{ ret = -3; } cJSON_Delete(recv); }else{ RLOGE("bind recv not json error."); ret = -2; } error: if(post_data){ hal_os_free(post_data); } if(root){ cJSON_Delete(root); } if (header) { hal_os_free(header); } if (response) { hal_os_free(response); } return ret; } int replace_str(char *str, char *oldStr, char *newStr, size_t str_buf_size) { char *start = str; char *p = strstr(str, oldStr); size_t oldLen, newLen, remainingLen; // 安全修复:参数检查 if (str == NULL || oldStr == NULL || newStr == NULL || str_buf_size == 0) { return -1; } if (p == NULL) { return -1; } oldLen = strlen(oldStr); newLen = strlen(newStr); while (p) { remainingLen = strlen(p + oldLen); // 安全修复:检查缓冲区是否足够 if ((p - str) + newLen + remainingLen >= str_buf_size) { QL_DL_HTTP_LOG("replace_str: buffer overflow risk"); return -1; } // 安全修复:使用memmove(处理重叠内存)和snprintf memmove(p + newLen, p + oldLen, remainingLen + 1); // +1 for '\0' memcpy(p, newStr, newLen); str = p + newLen; p = strstr(str, oldStr); } return 0; } int app_http_post_ota_packages(char *durl, char *ver) { char sn[32]={0}; char model[32]={0}; int ret = -1; char *response = NULL; char *header = NULL; int resp_len = 0; char *url = "http://test.afaitoys.com/v1/ota/packages"; char *post_data=NULL; cJSON *recv; cJSON *root = cJSON_CreateObject(); hal_os_get_device_id(sn); hal_os_get_model(model); cJSON_AddItemToObject(root,"serial_no",cJSON_CreateString(sn)); cJSON_AddItemToObject(root,"model",cJSON_CreateString(model)); cJSON_AddItemToObject(root,"apk_version",cJSON_CreateString(APP_VER)); cJSON_AddItemToObject(root,"rom_version",cJSON_CreateString(ROM_VER)); post_data = cJSON_PrintUnformatted(root); if(post_data==NULL)goto error; response = hal_os_malloc(4096); if(response==NULL)goto error; resp_len = 4096; header = hal_os_malloc(1024); if(header==NULL)goto error; sprintf(header, "Content-Type: application/json"); if (hal_http_client_post(url, header, post_data, strlen(post_data), response, &resp_len) < 0) { RLOGE("webclient send post request failed."); goto error; } RLOGD("ota resp: %s\n",response); recv = cJSON_Parse(response); if(recv){ cJSON *status = cJSON_GetObjectItem(recv,"status"); if(status && !strcmp("success",status->valuestring)){ cJSON *code = cJSON_GetObjectItem(recv,"code"); if(code && code->valueint == 200104){ RLOGD("update find."); cJSON *dataj = cJSON_GetObjectItem(recv,"data"); if(dataj){ cJSON *item = cJSON_GetArrayItem(dataj,0); if(item){ cJSON *item_url = cJSON_GetObjectItem(item,"download_url"); if(item_url){ replace_str(item_url->valuestring, "https", "http", sizeof(item_url->valuestring)); RLOGD("download url %s",item_url->valuestring); ret = 0; strcpy(durl,item_url->valuestring); } cJSON *semver_item = cJSON_GetObjectItem(item,"semver"); if(semver_item){ strcpy(ver,semver_item->valuestring); } } } }else{ ret = -4; } }else{ ret = -3; } cJSON_Delete(recv); }else{ RLOGE("app_http_post_ota_packages recv not json error."); ret = -2; } error: if(post_data){ hal_os_free(post_data); } if(root){ cJSON_Delete(root); } if (header) { hal_os_free(header); } if (response) { hal_os_free(response); } return ret; } int app_http_post_ota_packages_check() { char url[128]={0}; char ver[32]={0}; int ret = -1; RLOGD("app_http_post_ota_report 5\r\n"); app_http_post_ota_report(); ret = app_http_post_ota_packages(url,ver); if(ret==0 && strlen(url)>0){ #ifdef AOFEI_AUDIO_URL_SHEEP app_audio_player_by_path("http://alphai-ota.oss-cn-beijing.aliyuncs.com/alpha-intelligence/CNLD/TIPS/sheep/enter_ota_no_cut_power.amr"); #endif #ifdef AOFEI_AUDIO_URL_WOLF app_audio_player_by_path("http://alphai-ota.oss-cn-beijing.aliyuncs.com/alpha-intelligence/CNLD/TIPS/wolf/enter_ota_no_cut_power.amr"); #endif #ifdef TEST_AUDIO_URL app_audio_player_by_path("http://47.113.99.138:7050/TIPS/enter_ota_no_cut_power.amr"); #endif hal_kv_set("update_ver",ver,strlen(ver)+1); hal_kv_set("update_flag","1",strlen("1")+1); ret = http_ota_fw_download(url); RLOGD("http_ota_fw_download ret:%d\r\n", ret); if(ret==0){ //固件升级成功,正在重启 #ifdef AOFEI_AUDIO_URL_SHEEP app_audio_player_by_path("http://alphai-ota.oss-cn-beijing.aliyuncs.com/alpha-intelligence/CNLD/TIPS/sheep/ota_success.amr"); #endif #ifdef AOFEI_AUDIO_URL_WOLF app_audio_player_by_path("http://alphai-ota.oss-cn-beijing.aliyuncs.com/alpha-intelligence/CNLD/TIPS/wolf/ota_success.amr"); #endif #ifdef TEST_AUDIO_URL app_audio_player_by_path("http://47.113.99.138:7050/TIPS/ota_success.amr"); #endif RLOGD("ota download ok and reset\r\n"); }else{ //固件升级失败 #ifdef AOFEI_AUDIO_URL_SHEEP app_audio_player_by_path("http://alphai-ota.oss-cn-beijing.aliyuncs.com/alpha-intelligence/CNLD/TIPS/sheep/ota_fail.amr"); #endif #ifdef AOFEI_AUDIO_URL_WOLF app_audio_player_by_path("http://alphai-ota.oss-cn-beijing.aliyuncs.com/alpha-intelligence/CNLD/TIPS/wolf/ota_fail.amr"); #endif #ifdef TEST_AUDIO_URL app_audio_player_by_path("http://47.113.99.138:7050/TIPS/ota_fail.amr"); #endif RLOGD("ota download error and reset\r\n"); } ret = 1; } return ret; } int app_http_post_ota_report() { char sn[32]={0}; char model[32]={0}; int ret = -1; char *response = NULL; char *header = NULL; int resp_len = 0; char *url = "http://test.afaitoys.com/v1/ota/report"; char *post_data=NULL; cJSON *recv; cJSON *root = NULL; #if 0 hal_kv_get("update_ver",model,sizeof(model)); if(strlen(model)==0){ return -2; } if(strcmp(model,ROM_VER)==0){ RLOGD("ota update okay!!!!!!!!!!!!!!!!!!!!!!!!!"); } memset(model,0,sizeof(model)); hal_kv_set("update_ver","",1); #endif root = cJSON_CreateObject(); hal_os_get_device_id(sn); hal_os_get_model(model); cJSON_AddItemToObject(root,"serial_no",cJSON_CreateString(sn)); cJSON_AddItemToObject(root,"model",cJSON_CreateString(model)); cJSON_AddItemToObject(root,"apk_version",cJSON_CreateString(APP_VER)); cJSON_AddItemToObject(root,"rom_version",cJSON_CreateString(ROM_VER)); post_data = cJSON_PrintUnformatted(root); if(post_data==NULL){ ret = -1; goto error; } response = hal_os_malloc(4096); if(response==NULL)goto error; resp_len = 4096; header = hal_os_malloc(1024); if(header==NULL)goto error; sprintf(header, "Content-Type: application/json"); if (hal_http_client_post(url, header, post_data, strlen(post_data), response, &resp_len) < 0) { RLOGE("webclient send post request failed."); ret = -5; goto error; } RLOGD("app_http_post_ota_report post response data: %s\n",response); recv = cJSON_Parse(response); if(recv){ cJSON *status = cJSON_GetObjectItem(recv,"status"); if(status && strcmp("success",status->valuestring)){ cJSON *code = cJSON_GetObjectItem(recv,"code"); if(code && code->valueint == 200){ ret = 0; RLOGD("report okay."); }else{ ret = -4; } }else{ ret = -3; } cJSON_Delete(recv); }else{ RLOGD("app_http_post_ota_report recv not json error."); ret = -2; } error: if(post_data){ hal_os_free(post_data); } if(root){ cJSON_Delete(root); } if (header) { hal_os_free(header); } if (response) { hal_os_free(response); } return ret; } uint8_t story_cnt = 0; uint8_t app_get_story_cnt(void) { return story_cnt; } int app_http_get_story(char *uuid, char *story) { char tempbuf[128]={0}; int ret = -1; char *response = NULL; int resp_len = 0; char *url = "http://test.afaitoys.com/v1/user/skill/tiny"; cJSON *recv=NULL; //int index = 0; story_cnt = 0; hal_kv_set("story_cnt",&story_cnt,1); /*删除所有的故事*/ //while(1){ // RLOGD(tempbuf,"/flash0/story_%d.txt",index); //if(check_audio_file_exist(tempbuf)){ // dfs_file_unlink(tempbuf); //} //index++; //if(index>50) break; //rt_thread_mdelay(20); //} sprintf(tempbuf,"%s?uuid=%s&sign=%s",url,uuid,story); response = hal_os_malloc(4096); if(response==NULL)goto error; resp_len = 4096; if (hal_http_client_get(tempbuf, response, &resp_len) < 0) { RLOGE("webclient send get request failed."); ret = -5; goto error; } RLOGD("app_http_get_story get response data: %s\n",response); recv = cJSON_Parse(response); if(recv){ cJSON *status = cJSON_GetObjectItem(recv,"status"); if(status && !strcmp("success",status->valuestring)){ cJSON *code = cJSON_GetObjectItem(recv,"code"); if(code && code->valueint == 200){ RLOGD("get story okay."); cJSON *dataj = cJSON_GetObjectItem(recv,"data"); if(dataj){ cJSON *sdataj = cJSON_GetObjectItem(dataj,"storiesData"); if(sdataj){ uint8_t cnt = cJSON_GetArraySize(sdataj); int i; char filename[32]={0}; for(i=0;ivaluestring,"https","http"); rt_kprintf("story url %s\r\n",strurl->valuestring); //todo play the url //strurl->valuestring ret = 0; // write(fd,strurl->valuestring,strlen(strurl->valuestring)); dfs_file_write(&fd, strurl->valuestring, strlen(strurl->valuestring)); if(j