learnHttp.c 14 KB

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