learnHttp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #include "learnHttp.h"
  2. #include "nwy_osi_api.h"
  3. #include "nwy_http.h"
  4. #include "nwy_ftp.h"
  5. #include "log.h"
  6. #include "ohpoc.h"
  7. #include "base64.h"
  8. #include "app.h"
  9. #define GET_FILE_MAX_SIZE 10*1024
  10. #define HTTP_TASK_STACK_SIZE (1024*64)
  11. #define LEN_SEG "Content-Length: "
  12. typedef enum{
  13. HPROC_START,
  14. HPROC_BUSY,
  15. HPROC_OK,
  16. HPROC_FAILED
  17. }HTTP_PRO_ENUM;
  18. typedef struct{
  19. UHTTP_ENUM httpType;
  20. char url[200];
  21. unsigned char lteStatus;//下载文件状态
  22. unsigned char timeout;
  23. HTTP_PRO_ENUM processStatus;
  24. int fsize;
  25. int offset;
  26. unsigned short port;
  27. HttpCallBack recvCb;
  28. unsigned char *data;
  29. unsigned int dlength;
  30. unsigned char done;
  31. }HttpInfoSet;
  32. unsigned char *httpDataPtr=NULL;
  33. HttpInfoSet httpinfo;
  34. nwy_osiThread_t *learnHttpThread=NULL;
  35. typedef enum{
  36. HTTP_STATUS_IDLE,
  37. HTTP_STATUS_SETUP,
  38. HTTP_STATUS_SETUP_OK,
  39. HTTP_STATUS_GET,
  40. HTTP_STATUS_GET_OK,
  41. HTTP_STATUS_DNSERR,
  42. HTTP_STATUS_GET_ERR_HEAD,
  43. HTTP_STATUS_GET_REJECT_HEAD,
  44. HTTP_STATUS_GET_FAILED_HEAD,
  45. HTTP_STATUS_GET_ERR_FSIZE,
  46. HTTP_STATUS_GET_FAILED_FSIZE,
  47. HTTP_STATUS_GET_ERR_OFFSET,
  48. HTTP_STATUS_GET_FSIZE_OVER,
  49. HTTP_STATUS_POST_BUSY,
  50. HTTP_STATUS_POST_BAD,
  51. HTTP_STATUS_POST_DONE,
  52. HTTP_STATUS_DATA_MALLOC_ERR,
  53. HTTP_STATUS_TOUT,
  54. HTTP_STATUS_CLOSED
  55. }HTTP_STATUS_ENUM;
  56. static void learnEntry(void *param);
  57. void learn_http_set_status_false(unsigned char newStatus){
  58. MSG_INFO(1, "learn Status:%d",newStatus);
  59. httpinfo.lteStatus=newStatus;
  60. httpinfo.processStatus=HPROC_FAILED;
  61. }
  62. void learnHttpStart(UHTTP_ENUM httpType, char *url, unsigned short port, HttpCallBack *httpCb, unsigned char *udata, unsigned int dlen){
  63. if(httpCb==NULL){
  64. MSG_INFO(1, "httpCb is invalid");
  65. return;
  66. }
  67. if(NULL != learnHttpThread){
  68. MSG_INFO(1, "learnHttp is busy");
  69. return;
  70. }
  71. memset(&httpinfo, 0, sizeof(HttpInfoSet));
  72. httpinfo.data=udata;
  73. httpinfo.dlength=dlen;
  74. httpinfo.httpType=httpType;
  75. httpinfo.port=port;
  76. httpinfo.recvCb=httpCb;
  77. snprintf(httpinfo.url, sizeof(httpinfo.url), "%s",url);//120.77.66.129、1.txt 不需要http:头
  78. learnHttpThread=nwy_create_thread("learnHttpThread", learnEntry,NULL,NWY_OSI_PRIORITY_NORMAL,HTTP_TASK_STACK_SIZE,15);
  79. if(NULL==learnHttpThread){
  80. MSG_ERR(1,"learnHttpThread thread error");//因为是阻塞的,故需要开线程,且栈要比较大
  81. }
  82. }
  83. #define USER_DATA_SIZE (1024*3) //每次http post最大用户数据长度
  84. static void nwy_http_result_cb(nwy_ftp_result_t *param);
  85. static void learnEntry(void *param){
  86. unsigned char *ptr;
  87. int channel=1;
  88. int keepalive=1;
  89. int pIndex,lLen,pLen,tLen,rLen;
  90. unsigned char *postBuf=NULL;
  91. char tmp[30];
  92. float tmpSpeed;
  93. appSleepCtl(ASLEEP_LEARN, 1);
  94. boolean http_https=false;//http
  95. nwy_osiEvent_t event = {};
  96. MSG_INFO(1,"learn thread start:url=%s",httpinfo.url);
  97. int result = nwy_http_setup(channel, httpinfo.url, httpinfo.port, nwy_http_result_cb);
  98. if(0!=result){
  99. MSG_INFO(1, "learn http setup api failed");
  100. goto HTTP_END;
  101. }
  102. MSG_INFO(1, "learn http wait setup result");
  103. for(;;){
  104. nwy_wait_thead_event(nwy_get_current_thread(), &event,0);
  105. if(OHPOC_EVENT_HTTP==event.id) break;
  106. }
  107. if(httpinfo.lteStatus==HTTP_STATUS_DNSERR) goto HTTP_END;
  108. if(httpinfo.httpType==UHTTP_FILE_GET){
  109. httpinfo.lteStatus=HTTP_STATUS_GET;//start get
  110. result = nwy_http_get(keepalive, 0, GET_FILE_MAX_SIZE, http_https);
  111. if(result!=0){
  112. MSG_INFO(1,"learn http get api failed");
  113. goto HTTP_END;
  114. }
  115. MSG_INFO(1, "learn http wait get ack");
  116. for(;;){
  117. nwy_wait_thead_event(nwy_get_current_thread(), &event,0);
  118. if(OHPOC_EVENT_HTTP==event.id){
  119. if(httpinfo.lteStatus==HTTP_STATUS_GET_OK ||
  120. httpinfo.lteStatus==HTTP_STATUS_CLOSED ||
  121. httpinfo.lteStatus==HTTP_STATUS_TOUT) break;
  122. }
  123. }
  124. }else if(httpinfo.httpType==UHTTP_POST){
  125. httpinfo.processStatus=HPROC_START;
  126. pIndex=0;
  127. #if 0//强制发送长度为20的测试数据
  128. httpinfo.dlength=20;
  129. memset(httpinfo.data, 0x55, httpinfo.dlength);
  130. #endif
  131. lLen=httpinfo.dlength;
  132. postBuf=(unsigned char *)malloc(USER_DATA_SIZE);
  133. if(postBuf==NULL){
  134. MSG_ERR(1, "http post malloc failed");
  135. httpinfo.processStatus=HPROC_FAILED;
  136. goto HTTP_END;
  137. }
  138. for(;;){
  139. httpinfo.lteStatus=HTTP_STATUS_POST_BUSY;
  140. tmpSpeed=learnGetRecordRecSpeed();
  141. //先填充必须的一些字段信息,数据未填充,包有效数据长度未填(原始数据,非base64后)
  142. snprintf(postBuf, USER_DATA_SIZE, "{\"tid\":%s,\"uid\":%d,\"gid\":%d,\"dsv\":%d,\"dss\":%.1f,\"fsize\":%d,\"offset\":%d,\"token\":\"%s\",\"data\":\"",
  143. learnGetTid(),
  144. getLearnUid(),
  145. getLearnGid(),
  146. learnGetRecordMaxVolume(),
  147. tmpSpeed,
  148. httpinfo.dlength,
  149. pIndex,
  150. getLearnToken());
  151. //计算剩下可以填充多少实际数据,最后预留:","size":3000},即14字节,我们给20字节吧
  152. tLen=USER_DATA_SIZE-strlen(postBuf)-20;
  153. //计算tLen最多能装多少个原始数据,每4个base64表示3个原始数据
  154. rLen=tLen/4;//最多能装多少'组'原始数据
  155. rLen *= 3;//最多能装多少字节原始数据
  156. //计算本次填充多少有效数据
  157. if(lLen>rLen) pLen=rLen;
  158. else pLen=lLen;
  159. //填充有效数据
  160. ptr=httpinfo.data+pIndex;
  161. base64_encode(ptr, postBuf+strlen(postBuf), pLen);//结尾会被填充'\0'
  162. //添加size字段
  163. snprintf(tmp, sizeof(tmp), "\",\"size\":%d}", pLen);
  164. strcat(postBuf, tmp);
  165. //MSG_INFO(1, "send:<%s>\r\n", postBuf);
  166. //可以发送了(json)
  167. result = nwy_http_post(keepalive, 2 , postBuf, strlen(postBuf), http_https);
  168. MSG_INFO(1, "Post dataOffset:%d,dataLen:%d,jsonLen:%d %s", pIndex, pLen, strlen(postBuf), (result==0)?"Ok":"Failed");
  169. if(result==0){//执行成功,等待结果
  170. for(;;){
  171. nwy_wait_thead_event(nwy_get_current_thread(), &event,0);
  172. if(OHPOC_EVENT_HTTP==event.id){
  173. if(httpinfo.lteStatus==HTTP_STATUS_POST_DONE ||
  174. httpinfo.lteStatus==HTTP_STATUS_POST_BAD ||
  175. httpinfo.lteStatus==HTTP_STATUS_CLOSED ||
  176. httpinfo.lteStatus==HTTP_STATUS_TOUT) break;
  177. }
  178. }
  179. if(httpinfo.lteStatus==HTTP_STATUS_POST_DONE){
  180. pIndex += pLen;
  181. lLen -= pLen;
  182. MSG_INFO(1, "http post len:%d done", pLen);
  183. httpPostResetUserTimer(pIndex*100/httpinfo.dlength);
  184. if(lLen<=0){
  185. MSG_INFO(1, "http post done");
  186. httpinfo.processStatus=HPROC_OK;
  187. break;
  188. }
  189. }else if(httpinfo.lteStatus==HTTP_STATUS_POST_BAD){
  190. MSG_INFO(1, "http post ack bad");
  191. httpinfo.processStatus=HPROC_FAILED;
  192. break;
  193. }else{
  194. MSG_INFO(1, "http connection close/tout");
  195. httpinfo.processStatus=HPROC_FAILED;
  196. break;
  197. }
  198. }else{
  199. MSG_INFO(1, "http post err");
  200. httpinfo.processStatus=HPROC_FAILED;
  201. break;
  202. }
  203. }
  204. }
  205. MSG_INFO(1, "learn done");
  206. HTTP_END:
  207. if(NULL!=postBuf) free(postBuf);
  208. MSG_INFO(1, "learn http end");
  209. nwy_http_close(http_https);
  210. for(;;){
  211. if(httpinfo.lteStatus==HTTP_STATUS_DNSERR) break;//如果setup未成功,是不会有事件响应的
  212. nwy_wait_thead_event(nwy_get_current_thread(), &event,0);
  213. if(OHPOC_EVENT_HTTP==event.id){
  214. if(httpinfo.lteStatus==HTTP_STATUS_GET_OK ||
  215. httpinfo.lteStatus==HTTP_STATUS_CLOSED ||
  216. httpinfo.lteStatus==HTTP_STATUS_TOUT) break;
  217. }
  218. }
  219. learnHttpThread=NULL;
  220. httpinfo.done=1;
  221. appSleepCtl(ASLEEP_LEARN, 0);
  222. MSG_INFO(1, "learn http thread exit");
  223. nwy_exit_thread();
  224. }
  225. //检测接受到数据是否是成功的
  226. //HTTP/1.1 200
  227. static bool isHttpRecvValid(char *msg){
  228. int i;
  229. //检测是否是HTTP/头
  230. if(0!=memcmp(msg, "HTTP/", 5)) return true;//非首包
  231. //找空格后面的串是否是200
  232. for(i=0;i<strlen(msg);i++){
  233. if(msg[i]==' '){
  234. if(0==memcmp(msg+i+1, "200", 3)) return true;
  235. else return false;
  236. }
  237. }
  238. return false;
  239. }
  240. static void nwy_http_result_cb(nwy_ftp_result_t *param){
  241. char *ptr;
  242. int dlen,i;
  243. char info[55];
  244. snprintf(info,sizeof(info),"[HEvent:%d]",param->event);
  245. switch(param->event){
  246. case NWY_HTTP_DATA_RECVED: strcat(info,"NWY_HTTP_DATA_RECVED");break;
  247. case NWY_HTTP_DNS_ERR: strcat(info,"NWY_HTTP_DNS_ERR");break;
  248. case NWY_HTTP_OPEN_FAIL: strcat(info,"NWY_HTTP_OPEN_FAIL");break;
  249. case NWY_HTTP_OPENED: strcat(info,"NWY_HTTP_OPENED");break;
  250. case NWY_HTTPS_SSL_CONNECTED: strcat(info,"NWY_HTTPS_SSL_CONNECTED");break;
  251. case NWY_HTTP_CLOSED_PASV: strcat(info,"NWY_HTTP_CLOSED_PASV");break;
  252. case NWY_HTTP_CLOSED: strcat(info,"NWY_HTTP_CLOSED");break;
  253. case NWY_HTTP_DATA_SEND_ERR: strcat(info,"NWY_HTTP_DATA_SEND_ERR");break;
  254. case NWY_HTTPS_SSL_INIT_ERROR: strcat(info,"NWY_HTTPS_SSL_INIT_ERROR");break;
  255. case NWY_HTTPS_SSL_HANDSHAKE_ERROR: strcat(info,"NWY_HTTPS_SSL_HANDSHAKE_ERROR");break;
  256. case NWY_HTTPS_SSL_AUTH_FAIL: strcat(info,"NWY_HTTPS_SSL_AUTH_FAIL");break;
  257. case NWY_HTTP_DATA_SEND_FINISHED: strcat(info,"NWY_HTTP_DATA_SEND_FINISHED");break;
  258. default:strcat(info,"Unknown");break;
  259. }
  260. MSG_INFO(1, info);
  261. switch(param->event){
  262. case NWY_HTTP_DATA_RECVED:
  263. //MSG_INFO(1, "httpRecv:%d,%s", param->data_len, param->data);
  264. if(httpinfo.httpType==UHTTP_FILE_GET){//发HTTP_GET指令时的响应处理
  265. if(httpinfo.processStatus==HPROC_START){//响应第一包,需要获取总长度,有效数据长度等信息
  266. //检测是否是HTTP/头或非首包
  267. if(false==isHttpRecvValid(param->data)){
  268. MSG_WARN(1, "UHTTP_FILE_GET Recv Ack Not 200");
  269. break;
  270. }
  271. //获取有效数据总长度
  272. ptr=strstr(param->data, LEN_SEG);
  273. if(NULL==ptr){//没有字段,无法提取
  274. MSG_ERR(1, "No '%s' seg!",LEN_SEG);
  275. learn_http_set_status_false(HTTP_STATUS_GET_ERR_FSIZE);
  276. break;
  277. }
  278. dlen=atoi(ptr+strlen(LEN_SEG));//
  279. if(dlen<=0 || dlen>GET_FILE_MAX_SIZE || dlen==param->data_len){
  280. MSG_ERR(1, "data len invalid:%d",dlen);
  281. learn_http_set_status_false(HTTP_STATUS_GET_FSIZE_OVER);
  282. break;
  283. }
  284. MSG_INFO(1, "total data len:%d", dlen);
  285. httpDataPtr=(unsigned char *)malloc(dlen+2);
  286. if(NULL==httpDataPtr){
  287. MSG_ERR(1, "data malloc err:%d",dlen);
  288. learn_http_set_status_false(HTTP_STATUS_DATA_MALLOC_ERR);
  289. break;
  290. }
  291. //获取有效数据开始索引
  292. ptr=strstr(param->data,"\r\n\r\n");
  293. if(NULL==ptr){
  294. MSG_ERR(1, "data offset err");
  295. learn_http_set_status_false(HTTP_STATUS_GET_ERR_OFFSET);
  296. free(httpDataPtr);
  297. break;
  298. }
  299. httpinfo.fsize=dlen;
  300. httpinfo.offset=0;
  301. //提取本包中的有效数据
  302. ptr += 4;
  303. i=param->data_len-(ptr-(char *)param->data);
  304. memcpy(httpDataPtr+httpinfo.offset, ptr, i);
  305. //更新
  306. httpinfo.offset += i;
  307. httpinfo.processStatus=HPROC_BUSY;
  308. }else if(httpinfo.processStatus==HPROC_BUSY){//第一包以后均为有效数据
  309. memcpy(httpDataPtr+httpinfo.offset, param->data, param->data_len);
  310. httpinfo.offset += param->data_len;
  311. i=param->data_len;
  312. }
  313. if(httpinfo.processStatus<=HPROC_BUSY){
  314. MSG_INFO(1, "learn getdata offset:%d, fsize:%d", i, httpinfo.offset,httpinfo.fsize);
  315. if(httpinfo.offset>=httpinfo.fsize){
  316. MSG_INFO(1,"learn get data done");
  317. httpinfo.lteStatus=HTTP_STATUS_GET_OK;
  318. httpinfo.recvCb(httpDataPtr, httpinfo.fsize);
  319. free(httpDataPtr);
  320. httpinfo.processStatus=HPROC_OK;
  321. }
  322. }
  323. }else if(httpinfo.httpType==UHTTP_POST){//HTTP_POST时的响应处理接口
  324. //MSG_INFO(1, "httpRecv:%d,%s", param->data_len, param->data);
  325. //检测是否是HTTP/头或非首包
  326. if(false==isHttpRecvValid(param->data)){
  327. MSG_WARN(1, "UHTTP_POST Recv Ack Not 200");
  328. httpinfo.lteStatus=HTTP_STATUS_POST_BAD;
  329. break;
  330. }
  331. MSG_INFO(1, "http post get done ack");
  332. httpinfo.lteStatus=HTTP_STATUS_POST_DONE;
  333. }
  334. break;
  335. case NWY_HTTP_DNS_ERR:httpinfo.lteStatus=HTTP_STATUS_DNSERR;break;
  336. case NWY_HTTP_OPEN_FAIL: break;
  337. case NWY_HTTP_OPENED:httpinfo.lteStatus=HTTP_STATUS_SETUP_OK;break;
  338. case NWY_HTTPS_SSL_CONNECTED: break;
  339. case NWY_HTTP_CLOSED_PASV:
  340. case NWY_HTTP_CLOSED:httpinfo.lteStatus=HTTP_STATUS_CLOSED;break;
  341. case NWY_HTTP_DATA_SEND_ERR: break;
  342. case NWY_HTTPS_SSL_INIT_ERROR: break;
  343. case NWY_HTTPS_SSL_HANDSHAKE_ERROR: break;
  344. case NWY_HTTPS_SSL_AUTH_FAIL: break;
  345. case NWY_HTTP_DATA_SEND_FINISHED: break;
  346. }
  347. threadPostEvent(nwy_get_current_thread(),OHPOC_EVENT_HTTP, NULL,NULL,NULL);
  348. }
  349. void hearnHttpOverTime(void){
  350. if(NULL == learnHttpThread) return;
  351. httpinfo.lteStatus=HTTP_STATUS_TOUT;
  352. threadPostEvent(learnHttpThread,OHPOC_EVENT_HTTP, NULL,NULL,NULL);
  353. }
  354. unsigned char getHttpLearnStatus(void){
  355. if(httpinfo.done==0) return 1;//未完成
  356. if(httpinfo.processStatus==HPROC_OK) return 0;//已完成,且获取成功
  357. else return 2;//已完成,且失败
  358. }
  359. #include "cJSON.h"
  360. void jsonTestNow(void){
  361. char* data = "{\"name\":\"Messi\",\"age\":\"29\"}";
  362. //char* buf = "{\"uid\":12345,\"list\":[{\"tid\":\"5126\"},{\"tid\":\"5127\"},{\"tid\":\"8867\"},{\"tid\":\"8868\"},{\"tid\":\"1221\"},{\"tid\":\"2546\"}]}";
  363. const char * buf="{\"uid\":12348,\"list\":[{\"s\":4,\"c\":\"What is your name?\",\"t\":\"task 1\",\"f\":1,\"tid\":5126},{\"s\":3,\"c\":\"Where are you?\",\"t\":\"task 2\",\"f\":1,\"tid\":5127}]}";
  364. //const char * buf="{\"uid\":12348,\"list\":[{\"s\":\"4\",\"c\":\"What is your name?\",\"t\":\"task 1\",\"f\":\"1\",\"tid\":\"5126\"},{\"s\":\"3\",\"c\":\"Where are you?\",\"t\":\"task 2\",\"f\":\"1\",\"tid\":\"5127\"}]}";
  365. cJSON* root = cJSON_Parse(data);
  366. if(NULL==root){
  367. MSG_ERR(1, "root null1");
  368. return;
  369. }
  370. cJSON* itemName = cJSON_GetObjectItem(root, "name");
  371. if(itemName!=NULL) MSG_INFO(1, "name:%s", itemName->valuestring);
  372. else MSG_WARN(1, "name:NULL");
  373. cJSON* itemAge = cJSON_GetObjectItem(root, "age");
  374. if(itemAge!=NULL) MSG_INFO(1, "name:%s", itemAge->valuestring);
  375. else MSG_WARN(1, "age:NULL");
  376. cJSON_Delete(root);
  377. MSG_INFO(1, "JSON DONE");
  378. root = cJSON_Parse(buf);
  379. if(NULL==root){
  380. MSG_ERR(1, "root null2");
  381. return;
  382. }
  383. MSG_INFO(1, "--------------");
  384. itemName = cJSON_GetObjectItem(root, "list");
  385. if(itemName==NULL){
  386. MSG_WARN(1, "list:NULL");
  387. cJSON_Delete(root);
  388. return;
  389. }
  390. int num=cJSON_GetArraySize(itemName);
  391. MSG_INFO(1, "num=%d", num);
  392. int i=0;
  393. cJSON* tmp,*t;
  394. char *buf1;
  395. while(1){
  396. tmp=cJSON_GetArrayItem(itemName, i);
  397. if(tmp==NULL){
  398. MSG_INFO(1, "NULL");
  399. break;
  400. }
  401. buf1=cJSON_Print(tmp);
  402. MSG_INFO(1, "Detail:%s",buf1);
  403. free(buf1);
  404. t=cJSON_GetObjectItem(tmp, "tid");
  405. if(t!=NULL) MSG_INFO(1, "element[%d]%s", i++,t->valuestring);
  406. else MSG_INFO(1, "element[%d]NULL", i++);
  407. }
  408. cJSON_Delete(root);
  409. MSG_INFO(1, "JSON DONE2");
  410. }