http_put_demo.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*================================================================
  2. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  3. Quectel Wireless Solution Proprietary and Confidential.
  4. =================================================================*/
  5. /*=================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ------------ ------- -------------------------------------------------------------------------------
  11. =================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include "ql_api_osi.h"
  16. #include "ql_log.h"
  17. #include "ql_api_datacall.h"
  18. #include "ql_http_client.h"
  19. #include "ql_fs.h"
  20. #define QL_HTTP_LOG_LEVEL QL_LOG_LEVEL_INFO
  21. #define QL_HTTP_LOG(msg, ...) QL_LOG(QL_HTTP_LOG_LEVEL, "ql_HTTP", msg, ##__VA_ARGS__)
  22. #define QL_HTTP_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_HTTP", msg, ##__VA_ARGS__)
  23. #define DLOAD_FILE "UFS:http_dload.txt"
  24. #define UPLOAD_FILE "UFS:test_device.txt"
  25. typedef enum{
  26. QHTTPC_EVENT_RESPONSE = 1001,
  27. QHTTPC_EVENT_END,
  28. }qhttpc_event_code_e;
  29. typedef struct
  30. {
  31. http_client_t http_client;
  32. ql_queue_t queue;
  33. ql_mutex_t simple_lock;
  34. bool dl_block;
  35. int dl_high_line;
  36. int dl_total_len;
  37. QFILE upload_fd;
  38. QFILE dload_fd;
  39. }qhttpc_ctx_t;
  40. #define HTTP_MAX_MSG_CNT 8
  41. #define HTTP_DLOAD_HIGH_LINE 10240
  42. ql_task_t http_put_task = NULL;
  43. qhttpc_ctx_t http_demo_client = {0};
  44. static void http_event_cb(http_client_t *client, int evt, int evt_code, void *arg)
  45. {
  46. qhttpc_ctx_t *client_ptr = (qhttpc_ctx_t *)arg;
  47. ql_event_t qhttpc_event_send = {0};
  48. QL_HTTP_LOG("enter");
  49. if(client_ptr == NULL)
  50. return;
  51. QL_HTTP_LOG("*client:%d, http_cli:%d", *client, client_ptr->http_client);
  52. if(*client != client_ptr->http_client)
  53. return;
  54. QL_HTTP_LOG("evt:%d, evt_code:%d", evt, evt_code);
  55. switch(evt){
  56. case HTTP_EVENT_SESSION_ESTABLISH:{
  57. if(evt_code != QL_HTTP_OK){
  58. QL_HTTP_LOG("HTTP session create failed!!!!!");
  59. qhttpc_event_send.id = QHTTPC_EVENT_END;
  60. qhttpc_event_send.param1 = (uint32)client_ptr;
  61. ql_rtos_queue_release(client_ptr->queue, sizeof(ql_event_t), (uint8 *)&qhttpc_event_send, QL_WAIT_FOREVER);
  62. }
  63. }
  64. break;
  65. case HTTP_EVENT_RESPONE_STATE_LINE:{
  66. if(evt_code == QL_HTTP_OK){
  67. int resp_code = 0;
  68. int content_length = 0;
  69. int chunk_encode = 0;
  70. char *location = NULL;
  71. ql_httpc_getinfo(client, HTTP_INFO_RESPONSE_CODE, &resp_code);
  72. QL_HTTP_LOG("response code:%d", resp_code);
  73. ql_httpc_getinfo(client, HTTP_INFO_CHUNK_ENCODE, &chunk_encode);
  74. if(chunk_encode == 0){
  75. ql_httpc_getinfo(client, HTTP_INFO_CONTENT_LEN, &content_length);
  76. QL_HTTP_LOG("content_length:%d",content_length);
  77. }else{
  78. QL_HTTP_LOG("http chunk encode!!!");
  79. }
  80. if(resp_code >= 300 && resp_code < 400){
  81. ql_httpc_getinfo(client, HTTP_INFO_LOCATION, &location);
  82. QL_HTTP_LOG("redirect location:%s", location);
  83. free(location);
  84. }
  85. }
  86. }
  87. break;
  88. case HTTP_EVENT_SESSION_DISCONNECT:{
  89. if(evt_code == QL_HTTP_OK){
  90. QL_HTTP_LOG("===http transfer end!!!!");
  91. }else{
  92. QL_HTTP_LOG("===http transfer occur exception!!!!!");
  93. }
  94. qhttpc_event_send.id = QHTTPC_EVENT_END;
  95. qhttpc_event_send.param1 = (uint32)client_ptr;
  96. ql_rtos_queue_release(client_ptr->queue, sizeof(ql_event_t), (uint8 *)&qhttpc_event_send, QL_WAIT_FOREVER);
  97. }
  98. break;
  99. }
  100. }
  101. static int http_write_response_data(http_client_t *client, void *arg, char *data, int size, unsigned char end)
  102. {
  103. int ret = size;
  104. uint32 msg_cnt = 0;
  105. char *read_buff = NULL;
  106. qhttpc_ctx_t *client_ptr = (qhttpc_ctx_t *)arg;
  107. ql_event_t qhttpc_event_send = {0};
  108. QL_HTTP_LOG("enter");
  109. if(client_ptr == NULL)
  110. return 0;
  111. QL_HTTP_LOG("*client:%d, http_cli:%d", *client, client_ptr->http_client);
  112. if(*client != client_ptr->http_client)
  113. return 0;
  114. read_buff = (char *)malloc(size+1);
  115. if(read_buff == NULL)
  116. {
  117. QL_HTTP_LOG("mem faild");
  118. return 0;
  119. }
  120. memcpy(read_buff, data, size);
  121. if(QL_OSI_SUCCESS != ql_rtos_queue_get_cnt(client_ptr->queue, &msg_cnt))
  122. {
  123. free(read_buff);
  124. QL_HTTP_LOG("ql_rtos_queue_get_cnt faild");
  125. return 0;
  126. }
  127. ql_rtos_mutex_lock(client_ptr->simple_lock, 100);
  128. if(msg_cnt >= (HTTP_MAX_MSG_CNT-1) || (client_ptr->dl_total_len + size) >= client_ptr->dl_high_line)
  129. {
  130. client_ptr->dl_block = true;
  131. ret = QL_HTTP_ERROR_WONDBLOCK;
  132. }
  133. ql_rtos_mutex_unlock(client_ptr->simple_lock);
  134. QL_HTTP_LOG("msg_cnt %d, total_len+size %d", msg_cnt, (client_ptr->dl_total_len + size));
  135. qhttpc_event_send.id = QHTTPC_EVENT_RESPONSE;
  136. qhttpc_event_send.param1 = (uint32)client_ptr;
  137. qhttpc_event_send.param2 = (uint32)read_buff;
  138. qhttpc_event_send.param3 = (uint32)size;
  139. if(QL_OSI_SUCCESS != ql_rtos_queue_release(client_ptr->queue, sizeof(ql_event_t), (uint8 *)&qhttpc_event_send, 0))
  140. {
  141. free(read_buff);
  142. QL_HTTP_LOG("ql_rtos_queue_release faild");
  143. return 0;
  144. }
  145. ql_rtos_mutex_lock(client_ptr->simple_lock, 100);
  146. client_ptr->dl_total_len += size;
  147. ql_rtos_mutex_unlock(client_ptr->simple_lock);
  148. QL_HTTP_LOG("http response :%d bytes data", size);
  149. return ret;
  150. }
  151. static int http_read_request_data(http_client_t *client, void *arg, char *data, int size)
  152. {
  153. int ret = 0;
  154. QFILE fd = 0;
  155. qhttpc_ctx_t *client_ptr = (qhttpc_ctx_t *)arg;
  156. QL_HTTP_LOG("enter");
  157. if(client_ptr == NULL)
  158. return 0;
  159. QL_HTTP_LOG("*client:%d, http_cli:%d", *client, client_ptr->http_client);
  160. if(*client != client_ptr->http_client)
  161. return 0;
  162. ql_rtos_mutex_lock(client_ptr->simple_lock, 100);
  163. fd = client_ptr->upload_fd;
  164. ql_rtos_mutex_unlock(client_ptr->simple_lock);
  165. QL_HTTP_LOG("fd:%d", fd);
  166. if(fd < 0)
  167. return 0;
  168. QL_HTTP_LOG("read size:%d", size);
  169. ret = ql_fread(data, size, 1, fd);
  170. QL_HTTP_LOG("http read :%d bytes data", ret);
  171. if(ret > 0)
  172. return ret;
  173. return 0;
  174. }
  175. static void http_write_response_data_func(void *param)
  176. {
  177. int ret = 0;
  178. int size = 0;
  179. QFILE fd = 0;
  180. bool dload_block = false;
  181. char *read_buff = NULL;
  182. qhttpc_ctx_t *client_ptr = NULL;
  183. ql_event_t *qhttpc_event_recv = (ql_event_t *)param;
  184. QL_HTTP_LOG("enter");
  185. if(qhttpc_event_recv == NULL || qhttpc_event_recv->param1 == 0 || qhttpc_event_recv->param2 == 0 || qhttpc_event_recv->param3 == 0)
  186. return;
  187. client_ptr = (qhttpc_ctx_t *)qhttpc_event_recv->param1;
  188. read_buff = (char *)qhttpc_event_recv->param2;
  189. size = (int)qhttpc_event_recv->param3;
  190. fd = (QFILE)client_ptr->dload_fd;
  191. ret = ql_fwrite(read_buff, size, 1, fd);
  192. free(read_buff);
  193. ql_rtos_mutex_lock(client_ptr->simple_lock, 100);
  194. client_ptr->dl_total_len -= size;
  195. if(client_ptr->dl_total_len < 0)
  196. client_ptr->dl_total_len = 0;
  197. if(client_ptr->dl_block == true && client_ptr->dl_total_len < client_ptr->dl_high_line)
  198. {
  199. dload_block = client_ptr->dl_block;
  200. client_ptr->dl_block = false;
  201. }
  202. ql_rtos_mutex_unlock(client_ptr->simple_lock);
  203. if(dload_block == true)
  204. ql_httpc_continue_dload(&client_ptr->http_client);
  205. QL_HTTP_LOG("http write :%d bytes data", ret);
  206. }
  207. static int sim_net_register(int nSim, int profile_idx)
  208. {
  209. int ret = 0, i = 0;
  210. ql_data_call_info_s info;
  211. char ip4_addr_str[16] = {0};
  212. while((ret = ql_network_register_wait(nSim, 120)) != 0 && i < 10){
  213. i++;
  214. ql_rtos_task_sleep_ms(1000);
  215. }
  216. if(ret == 0) {
  217. i = 0;
  218. QL_HTTP_LOG("====network registered!!!!====");
  219. } else {
  220. QL_HTTP_LOG("====network register failure!!!!!====");
  221. return ret;
  222. }
  223. ql_set_data_call_asyn_mode(nSim, profile_idx, 0);
  224. ret=ql_start_data_call(nSim, profile_idx, QL_PDP_TYPE_IP, "uninet", NULL, NULL, 0);
  225. if(ret != 0) {
  226. QL_HTTP_LOG("====data call failure!!!!=====");
  227. }
  228. memset(&info, 0x00, sizeof(ql_data_call_info_s));
  229. ret = ql_get_data_call_info(nSim, profile_idx, &info);
  230. if(ret != 0) {
  231. QL_HTTP_LOG("ql_get_data_call_info ret: %d", ret);
  232. ql_stop_data_call(nSim, profile_idx);
  233. return ret;
  234. }
  235. QL_HTTP_LOG("info->profile_idx: %d", info.profile_idx);
  236. QL_HTTP_LOG("info->ip_version: %d", info.ip_version);
  237. QL_HTTP_LOG("info->v4.state: %d", info.v4.state);
  238. inet_ntop(AF_INET, &info.v4.addr.ip, ip4_addr_str, sizeof(ip4_addr_str));
  239. QL_HTTP_LOG("info.v4.addr.ip: %s\r\n", ip4_addr_str);
  240. inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_addr_str, sizeof(ip4_addr_str));
  241. QL_HTTP_LOG("info.v4.addr.pri_dns: %s\r\n", ip4_addr_str);
  242. inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_addr_str, sizeof(ip4_addr_str));
  243. QL_HTTP_LOG("info.v4.addr.sec_dns: %s\r\n", ip4_addr_str);
  244. return ret;
  245. }
  246. static int http_uplaod_file_init()
  247. {
  248. QFILE fp;
  249. char write_buffer[1024] = {0};
  250. int length = 1000;
  251. int ret = 0;
  252. fp = ql_fopen(UPLOAD_FILE, "w+");
  253. if( fp < 0 ) {
  254. QL_HTTP_LOG("open upload file %s failure", UPLOAD_FILE);
  255. return -1;
  256. }
  257. memset(write_buffer, 'a', length);
  258. ret = ql_fwrite(write_buffer, length, 1, fp);
  259. if(ret <= 0 ) {
  260. QL_HTTP_LOG("http write :%d bytes data fail", length);
  261. return -1;
  262. }
  263. ql_fclose(fp);
  264. return 0;
  265. }
  266. static void http_put_app_thread(void * arg)
  267. {
  268. int ret = 0;
  269. int run_num = 0;
  270. struct stat dload_stat;
  271. uint8_t nSim = 0;
  272. int profile_idx = 1;
  273. char url[] = "http://220.180.239.212:9632/put_file";
  274. struct stat stat_buf;
  275. int flags_break = 0;
  276. ql_event_t qhttpc_event_msg = {0};
  277. ql_rtos_task_sleep_s(5);
  278. QL_HTTP_LOG("========== http new demo start ==========");
  279. QL_HTTP_LOG("wait for network register done");
  280. ret = sim_net_register(nSim, profile_idx);
  281. if( ret != 0 ) {
  282. QL_HTTP_LOG("sim register net failure , ret= %d", ret);
  283. goto exit;
  284. }
  285. ret = http_uplaod_file_init();
  286. if( ret != 0 ) goto exit;
  287. do {
  288. QL_HTTP_LOG("==============http_client_put_test[%d]================\n",run_num+1);
  289. memset(&http_demo_client, 0x00, sizeof(qhttpc_ctx_t));
  290. http_demo_client.dl_block = false;
  291. http_demo_client.dl_high_line = HTTP_DLOAD_HIGH_LINE;
  292. ret = ql_rtos_mutex_create(&http_demo_client.simple_lock);
  293. if (ret)
  294. {
  295. QL_HTTP_LOG("ql_rtos_mutex_create failed!!!!");
  296. break;
  297. }
  298. ret = ql_rtos_queue_create(&http_demo_client.queue, sizeof(ql_event_t), HTTP_MAX_MSG_CNT);
  299. if (ret)
  300. {
  301. QL_HTTP_LOG("ql_rtos_queue_create failed!!!!");
  302. break;
  303. }
  304. if(ql_httpc_new(&http_demo_client.http_client, http_event_cb, (void *)&http_demo_client) != QL_HTTP_OK){
  305. QL_HTTP_LOG("http client create failed!!!!");
  306. break;
  307. }
  308. http_demo_client.dload_fd = ql_fopen(DLOAD_FILE, "w+");
  309. if(http_demo_client.dload_fd < 0){
  310. QL_HTTP_LOG("open file failed!!!!");
  311. ql_httpc_release(&http_demo_client.http_client);
  312. goto exit;
  313. }
  314. http_demo_client.upload_fd = ql_fopen(UPLOAD_FILE, "r");
  315. if( http_demo_client.upload_fd < 0 ) {
  316. ql_httpc_release(&http_demo_client.http_client);
  317. QL_HTTP_LOG("open upload file %s failure", UPLOAD_FILE);
  318. goto exit;
  319. }
  320. memset(&stat_buf, 0x00, sizeof(struct stat));
  321. ql_fstat(http_demo_client.upload_fd, &stat_buf);
  322. if( stat_buf.st_size == 0 ) {
  323. ql_fclose(http_demo_client.upload_fd);
  324. ql_httpc_release(&http_demo_client.http_client);
  325. QL_HTTP_LOG("upload file %s NULL", UPLOAD_FILE);
  326. goto exit;
  327. }
  328. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_SIM_ID, nSim);
  329. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_PDPCID, profile_idx);
  330. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_WRITE_FUNC, http_write_response_data);
  331. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_WRITE_DATA, (void *)&http_demo_client);
  332. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_METHOD, HTTP_METHOD_PUT);
  333. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_URL, (char *)url);
  334. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_REQUEST_HEADER, "Content-type: multipart/form-data");
  335. ql_httpc_formadd(&http_demo_client.http_client, HTTP_FORM_NAME, "file");
  336. ql_httpc_formadd(&http_demo_client.http_client, HTTP_FORM_FILENAME, "http_test.txt");
  337. ql_httpc_formadd(&http_demo_client.http_client, HTTP_FORM_CONTENT_TYPE, "text/plain");
  338. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_READ_FUNC, http_read_request_data);
  339. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_READ_DATA, (void *)&http_demo_client);
  340. ql_httpc_setopt(&http_demo_client.http_client, HTTP_CLIENT_OPT_UPLOAD_LEN, stat_buf.st_size);
  341. if( ql_httpc_perform(&http_demo_client.http_client) == QL_HTTP_OK )
  342. {
  343. QL_HTTP_LOG("wait http perform end!!!!!!");
  344. flags_break = 0;
  345. for (;;)
  346. {
  347. memset(&qhttpc_event_msg, 0x00, sizeof(ql_event_t));
  348. ql_rtos_queue_wait(http_demo_client.queue, (uint8 *)&qhttpc_event_msg, sizeof(ql_event_t), QL_WAIT_FOREVER);
  349. switch(qhttpc_event_msg.id)
  350. {
  351. case QHTTPC_EVENT_RESPONSE:
  352. {
  353. http_write_response_data_func((void *)&qhttpc_event_msg);
  354. }
  355. break;
  356. case QHTTPC_EVENT_END:
  357. {
  358. flags_break = 1;
  359. }
  360. break;
  361. default:
  362. break;
  363. }
  364. if(flags_break)
  365. break;
  366. }
  367. } else {
  368. QL_HTTP_LOG("http perform failed!!!!!!!!!!");
  369. }
  370. memset(&dload_stat, 0x00, sizeof(struct stat));
  371. ql_fstat(http_demo_client.dload_fd, &dload_stat);
  372. QL_HTTP_LOG("=========dload_file_size:%d", dload_stat.st_size);
  373. if(http_demo_client.dload_fd >= 0) {
  374. ql_fclose(http_demo_client.dload_fd);
  375. http_demo_client.dload_fd = -1;
  376. }
  377. ql_rtos_mutex_lock(http_demo_client.simple_lock, 100);
  378. if(http_demo_client.upload_fd >= 0) {
  379. ql_fclose(http_demo_client.upload_fd);
  380. http_demo_client.upload_fd = -1;
  381. }
  382. ql_rtos_mutex_unlock(http_demo_client.simple_lock);
  383. ql_httpc_release(&http_demo_client.http_client);
  384. http_demo_client.http_client = 0;
  385. QL_HTTP_LOG("==============http_client_test_end[%d]================\n",run_num+1);
  386. run_num++;
  387. if(http_demo_client.queue != NULL)
  388. {
  389. while(1)
  390. {
  391. memset(&qhttpc_event_msg, 0x00, sizeof(ql_event_t));
  392. if(QL_OSI_SUCCESS != ql_rtos_queue_wait(http_demo_client.queue, (uint8 *)&qhttpc_event_msg, sizeof(ql_event_t), 0))
  393. break;
  394. switch(qhttpc_event_msg.id)
  395. {
  396. case QHTTPC_EVENT_RESPONSE:
  397. {
  398. free((void *)(qhttpc_event_msg.param2));
  399. }
  400. break;
  401. default:
  402. break;
  403. }
  404. }
  405. ql_rtos_queue_delete(http_demo_client.queue);
  406. http_demo_client.queue = NULL;
  407. }
  408. ql_rtos_mutex_delete(http_demo_client.simple_lock);
  409. http_demo_client.simple_lock = NULL;
  410. ql_rtos_task_sleep_s(3);
  411. }while(1);
  412. exit:
  413. if(http_demo_client.queue != NULL)
  414. {
  415. while(1)
  416. {
  417. memset(&qhttpc_event_msg, 0x00, sizeof(ql_event_t));
  418. if(QL_OSI_SUCCESS != ql_rtos_queue_wait(http_demo_client.queue, (uint8 *)&qhttpc_event_msg, sizeof(ql_event_t), 0))
  419. break;
  420. switch(qhttpc_event_msg.id)
  421. {
  422. case QHTTPC_EVENT_RESPONSE:
  423. {
  424. free((void *)(qhttpc_event_msg.param2));
  425. }
  426. break;
  427. default:
  428. break;
  429. }
  430. }
  431. ql_rtos_queue_delete(http_demo_client.queue);
  432. }
  433. if(http_demo_client.simple_lock != NULL)
  434. ql_rtos_mutex_delete(http_demo_client.simple_lock);
  435. ql_rtos_task_delete(http_put_task);
  436. return;
  437. }
  438. void ql_http_put_app_init(void)
  439. {
  440. QlOSStatus err = QL_OSI_SUCCESS;
  441. err = ql_rtos_task_create(&http_put_task, 4096, APP_PRIORITY_NORMAL, "QhttpPut", http_put_app_thread, NULL, 5);
  442. if(err != QL_OSI_SUCCESS)
  443. {
  444. QL_HTTP_LOG("created task failed");
  445. }
  446. }