httpserver.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. #include "httpserver.h"
  2. #include "lwip/tcp.h"
  3. #include "fsdata.c"
  4. #include "main.h"
  5. #include "flash_if.h"
  6. #include "common_config.h"
  7. #include "settings_api.h"
  8. #include "crc.h"
  9. #include "gpio_io.h"
  10. #include "systick.h"
  11. #include <string.h>
  12. #include "tinystdio.h"
  13. /**
  14. * @brief Общая структура настроек
  15. */
  16. extern SETTINGS_t sSettings;
  17. extern uint8_t fDoneReset;
  18. extern uint8_t fErrorReset;
  19. char debugMsg[40];
  20. static vu32 DataFlag=0;
  21. static vu32 size =0;
  22. static __IO uint32_t FlashWriteAddress;
  23. static u32 TotalReceived=0;
  24. static char LeftBytesTab[4];
  25. static u8 LeftBytes=0;
  26. static __IO u8 resetpage=0;
  27. static uint32_t ContentLengthOffset =0,BrowserFlag=0;
  28. static __IO uint32_t TotalData=0, checklogin=0;
  29. static bool fEraseFlash = true;
  30. static uint8_t reqCounter = 0;
  31. static uint8_t reqTimer = 0;
  32. struct http_state
  33. {
  34. char *file;
  35. u32_t left;
  36. };
  37. htmlpageState htmlpage;
  38. static const char http_crnl_2[4] =
  39. /* "\r\n--" */
  40. {0xd, 0xa,0x2d,0x2d};
  41. static const char octet_stream[14] =
  42. /* "octet-stream" */
  43. {0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,0x0d, };
  44. static const char Content_Length[17] =
  45. /* Content Length */
  46. {0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67,0x74, 0x68, 0x3a, 0x20, };
  47. static uint32_t Parse_Content_Length(char *data, uint32_t len);
  48. static void IAP_HTTP_writedata(char* data, uint32_t len);
  49. /* file must be allocated by caller and will be filled in
  50. by the function. */
  51. static int fs_open(char *name, struct fs_file *file);
  52. uint16_t printLen = 0;
  53. char printBuf[1500];
  54. uint32_t oldAdd = USER_FLASH_FIRST_PAGE_ADDRESS;
  55. uint32_t deltaAdd = 0;
  56. /**
  57. * @brief callback function for handling connection errors
  58. * @param arg: pointer to an argument to be passed to callback function
  59. * @param err: LwIP error code
  60. * @retval none
  61. */
  62. static void conn_err(void *arg, err_t err)
  63. {
  64. struct http_state *hs;
  65. hs = arg;
  66. mem_free(hs);
  67. }
  68. /**
  69. * @brief closes tcp connection
  70. * @param pcb: pointer to a tcp_pcb struct
  71. * @param hs: pointer to a http_state struct
  72. * @retval
  73. */
  74. static void close_conn(struct tcp_pcb *pcb, struct http_state *hs)
  75. {
  76. tcp_arg(pcb, NULL);
  77. tcp_sent(pcb, NULL);
  78. tcp_recv(pcb, NULL);
  79. mem_free(hs);
  80. tcp_close(pcb);
  81. reqCounter++;
  82. }
  83. /**
  84. * @brief sends data found in member "file" of a http_state struct
  85. * @param pcb: pointer to a tcp_pcb struct
  86. * @param hs: pointer to a http_state struct
  87. * @retval none
  88. */
  89. static void send_data(struct tcp_pcb *pcb, struct http_state *hs)
  90. {
  91. err_t err;
  92. u16_t len;
  93. /* We cannot send more data than space available in the send
  94. buffer */
  95. if (tcp_sndbuf(pcb) < hs->left)
  96. {
  97. len = tcp_sndbuf(pcb);
  98. }
  99. else
  100. {
  101. len = hs->left;
  102. }
  103. err = tcp_write(pcb, hs->file, len, 0);
  104. if (err == ERR_OK)
  105. {
  106. hs->file += len;
  107. hs->left -= len;
  108. }
  109. }
  110. /**
  111. * @brief tcp poll callback function
  112. * @param arg: pointer to an argument to be passed to callback function
  113. * @param pcb: pointer on tcp_pcb structure
  114. * @retval err_t
  115. */
  116. static err_t http_poll(void *arg, struct tcp_pcb *pcb)
  117. {
  118. if (arg == NULL)
  119. {
  120. tcp_close(pcb);
  121. }
  122. else
  123. {
  124. send_data(pcb, (struct http_state *)arg);
  125. }
  126. return ERR_OK;
  127. }
  128. /**
  129. * @brief callback function called after a successfull TCP data packet transmission
  130. * @param arg: pointer to an argument to be passed to callback function
  131. * @param pcb: pointer on tcp_pcb structure
  132. * @param len
  133. * @retval err : LwIP error code
  134. */
  135. static err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
  136. {
  137. struct http_state *hs;
  138. hs = arg;
  139. if (hs->left > 0)
  140. send_data(pcb, hs);
  141. else
  142. {
  143. close_conn(pcb, hs);
  144. if (htmlpage == UploadDonePage)
  145. fDoneReset = 1;
  146. else if (htmlpage == UploadErrorPage)
  147. fErrorReset = 1;
  148. }
  149. return ERR_OK;
  150. }
  151. /**
  152. * @brief callback function for handling TCP HTTP traffic
  153. * @param arg: pointer to an argument structure to be passed to callback function
  154. * @param pcb: pointer to a tcp_pcb structure
  155. * @param p: pointer to a packet buffer
  156. * @param err: LwIP error code
  157. * @retval err
  158. */
  159. /* goback.cgi - возврат в основную прошивку */
  160. /* upload.cgi - загрузка новой прошивки */
  161. static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
  162. {
  163. int32_t i, len=0;
  164. uint32_t DataOffset, FilenameOffset;
  165. char *data, *ptr, filename[13];
  166. struct fs_file file = {0, 0};
  167. struct http_state *hs;
  168. hs = arg;
  169. if (err == ERR_OK && p != NULL)
  170. {
  171. /* Inform TCP that we have taken the data */
  172. tcp_recved(pcb, p->tot_len);
  173. if (hs->file == NULL)
  174. {
  175. data = p->payload;
  176. len = p->tot_len;
  177. printLen = p->tot_len;
  178. memcpy(printBuf, p->payload , printLen);
  179. //printf(printBuf);
  180. /* process HTTP GET requests */
  181. if (strncmp(data, "GET /", 5) == 0)
  182. {/*
  183. if ((strncmp(data, "GET /resetmcu.cgi", 17) ==0)&&(htmlpage == UploadDonePage))
  184. {
  185. htmlpage = ResetDonePage;
  186. fs_open("/reset.html", &file);
  187. hs->file = file.data;
  188. hs->left = file.len;
  189. pbuf_free(p);
  190. send_data(pcb, hs);
  191. resetpage = 1;
  192. tcp_sent(pcb, http_sent);
  193. }*/
  194. if (strncmp(data, "GET /upload.css", 15) == 0)
  195. {
  196. fs_open("/upload.css", &file);
  197. hs->file = file.data;
  198. hs->left = file.len;
  199. pbuf_free(p);
  200. send_data(pcb, hs);
  201. tcp_sent(pcb, http_sent);
  202. }
  203. else if (strncmp(data, "GET /upload.js", 14) == 0)
  204. {
  205. fs_open("/upload.js", &file);
  206. hs->file = file.data;
  207. hs->left = file.len;
  208. pbuf_free(p);
  209. send_data(pcb, hs);
  210. tcp_sent(pcb, http_sent);
  211. }
  212. /* Возврат в основную прошивку. Сбрасываем флаг loadmode,
  213. сохраняем настройки и перезагружаемся */
  214. else if (strncmp(data, "GET /goback.cgi", 15)==0)
  215. {
  216. sSettings.bootParams.loadMode = 0;
  217. SETTINGS_Save();
  218. Delay_ms(1010);
  219. NVIC_SystemReset();
  220. }
  221. else if (strncmp(data, "GET /favicon.ico", 16) == 0)
  222. {
  223. fs_open("/favicon.ico", &file);
  224. hs->file = file.data;
  225. hs->left = file.len;
  226. send_data(pcb, hs);
  227. tcp_sent(pcb, http_sent);
  228. }
  229. else
  230. {
  231. /*send the login page (which is the index page) */
  232. htmlpage = LoginPage;
  233. fs_open("/index.html", &file);
  234. hs->file = file.data;
  235. hs->left = file.len;
  236. pbuf_free(p);
  237. send_data(pcb, hs);
  238. tcp_sent(pcb, http_sent);
  239. }
  240. }
  241. #if 1
  242. /* process POST request for file upload and incoming data packets after POST request*/
  243. else if ((strncmp(data, "POST /upload.cgi",16) == 0) || (DataFlag >= 1))
  244. {
  245. if (fEraseFlash) {
  246. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  247. fEraseFlash = false;
  248. }
  249. DataOffset = 0;
  250. /* POST Packet received */
  251. if (DataFlag == 0)
  252. {
  253. BrowserFlag = 0;
  254. TotalReceived = 0;
  255. /* parse packet for Content-length field */
  256. size = Parse_Content_Length(data, p->tot_len);
  257. /* parse packet for the octet-stream field */
  258. for (i = 0; i < len; i++)
  259. {
  260. if (strncmp ((char*)(data+i), octet_stream, 13)==0)
  261. {
  262. DataOffset = i + 16;
  263. break;
  264. }
  265. }
  266. /* case of MSIE8 : we do not receive data in the POST packet*/
  267. if (DataOffset == 0)
  268. {
  269. DataFlag++;
  270. BrowserFlag = 1;
  271. pbuf_free(p);
  272. return ERR_OK;
  273. }
  274. /* case of Mozilla Firefox v3.6 : we receive data in the POST packet*/
  275. else
  276. {
  277. TotalReceived = len - (ContentLengthOffset + 4);
  278. }
  279. }
  280. if (((DataFlag ==1)&&(BrowserFlag==1)) || ((DataFlag ==0)&&(BrowserFlag==0)))
  281. {
  282. if ((DataFlag ==0)&&(BrowserFlag==0))
  283. {
  284. DataFlag++;
  285. }
  286. else if ((DataFlag ==1)&&(BrowserFlag==1))
  287. {
  288. /* parse packet for the octet-stream field */
  289. for (i = 0; i < len; i++)
  290. {
  291. if (strncmp ((char*)(data+i), octet_stream, 13)==0)
  292. {
  293. DataOffset = i+16;
  294. break;
  295. }
  296. }
  297. TotalReceived += len;
  298. DataFlag++;
  299. }
  300. /* parse packet for the filename field */
  301. FilenameOffset = 0;
  302. for (i = 0; i < len; i++)
  303. {
  304. if (strncmp ((char*)(data+i), "filename=", 9)==0)
  305. {
  306. FilenameOffset = i+10;
  307. break;
  308. }
  309. }
  310. i = 0;
  311. if (FilenameOffset)
  312. {
  313. while((*(data+FilenameOffset + i)!=0x22 )&&(i<13))
  314. {
  315. filename[i] = *(data+FilenameOffset + i);
  316. i++;
  317. }
  318. filename[i] = 0x0;
  319. }
  320. if (i==0)
  321. {
  322. htmlpage = FileUploadPage;
  323. /* no filename, in this case reload upload page */
  324. fs_open("/upload.html", &file);
  325. hs->file = file.data;
  326. hs->left = file.len;
  327. pbuf_free(p);
  328. /* send index.html page */
  329. send_data(pcb, hs);
  330. /* Tell TCP that we wish be to informed of data that has been
  331. successfully sent by a call to the http_sent() function. */
  332. tcp_sent(pcb, http_sent);
  333. DataFlag=0;
  334. return ERR_OK;
  335. }
  336. PRINT_USART("\n\r IAP using HTTP \n\r");
  337. sprintf(debugMsg, "File: %s\n\r",filename);
  338. PRINT_USART(debugMsg);
  339. PRINT_USART("State: Erasing...\n\r");
  340. TotalData =0 ;
  341. /* init flash */
  342. FLASH_If_Init();
  343. /* erase user flash area */
  344. //FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  345. FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
  346. /*indicate start of flash programming */
  347. PRINT_USART("\n\rState: Programming..\n\r");
  348. }
  349. /* DataFlag >1 => the packet is data only */
  350. else
  351. {
  352. TotalReceived +=len;
  353. }
  354. ptr = (char*)(data + DataOffset);
  355. len-= DataOffset;
  356. /* update Total data received counter */
  357. TotalData +=len;
  358. /* check if last data packet */
  359. if (TotalReceived == size)
  360. {
  361. /* if last packet need to remove the http boundary tag */
  362. /* parse packet for "\r\n--" starting from end of data */
  363. /*
  364. i = 4;
  365. while (strncmp ((char*)(data+ p->tot_len -i),http_crnl_2 , 4))
  366. {
  367. i++;
  368. }
  369. len -= i;
  370. TotalData -= i;
  371. */
  372. /* write data in Flash */
  373. if (len)
  374. IAP_HTTP_writedata(ptr,len);
  375. DataFlag=0;
  376. htmlpage = UploadDonePage;
  377. PRINT_USART("Tot bytes Received:\n\r");
  378. sprintf(debugMsg, "%d bytes \n\r",TotalData);
  379. PRINT_USART(debugMsg);
  380. PRINT_USART("State: Prog Finished \n\r");
  381. /* Проверяем CRC */
  382. if (CRC_Read() == CRC_Calcucate()) {
  383. fs_open("/success.html", &file);
  384. hs->file = file.data;
  385. hs->left = file.len;
  386. send_data(pcb, hs);
  387. tcp_sent(pcb, http_sent);
  388. htmlpage = UploadDonePage;
  389. }
  390. else
  391. {
  392. fs_open("/error.html", &file);
  393. hs->file = file.data;
  394. hs->left = file.len;
  395. send_data(pcb, hs);
  396. tcp_sent(pcb, http_sent);
  397. htmlpage = UploadErrorPage;
  398. }
  399. /*
  400. sSettings.bootParams.loadMode = 0;
  401. SETTINGS_Save();
  402. IO_KeyBlockOn();
  403. Delay_ms(1010);
  404. NVIC_SystemReset();
  405. */
  406. }
  407. /* not last data packet */
  408. else
  409. {
  410. /* write data in flash */
  411. if(len)
  412. IAP_HTTP_writedata(ptr,len);
  413. }
  414. pbuf_free(p);
  415. }
  416. else
  417. {
  418. /* Bad HTTP requests */
  419. PRINT_USART("Bad HTTP request\n\r");
  420. pbuf_free(p);
  421. close_conn(pcb, hs);
  422. }
  423. #endif
  424. }
  425. else
  426. {
  427. pbuf_free(p);
  428. close_conn(pcb,hs);
  429. }
  430. }
  431. if (err == ERR_OK && p == NULL)
  432. {
  433. /* received empty frame */
  434. PRINT_USART("Received empty frame\n\r");
  435. close_conn(pcb, hs);
  436. }
  437. return ERR_OK;
  438. }
  439. /**
  440. * @brief callback function on TCP connection setup ( on port 80)
  441. * @param arg: pointer to an argument structure to be passed to callback function
  442. * @param pcb: pointer to a tcp_pcb structure
  443. * &param err: Lwip stack error code
  444. * @retval err
  445. */
  446. static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
  447. {
  448. struct http_state *hs;
  449. /* Allocate memory for the structure that holds the state of the connection */
  450. hs = mem_malloc(sizeof(struct http_state));
  451. if (hs == NULL)
  452. {
  453. return ERR_MEM;
  454. }
  455. /* Initialize the structure. */
  456. hs->file = NULL;
  457. hs->left = 0;
  458. /* Tell TCP that this is the structure we wish to be passed for our
  459. callbacks. */
  460. tcp_arg(pcb, hs);
  461. /* Tell TCP that we wish to be informed of incoming data by a call
  462. to the http_recv() function. */
  463. tcp_recv(pcb, http_recv);
  464. tcp_err(pcb, conn_err);
  465. tcp_poll(pcb, http_poll, 10);
  466. return ERR_OK;
  467. }
  468. /**
  469. * @brief intialize HTTP webserver
  470. * @param none
  471. * @retval none
  472. */
  473. void IAP_httpd_init(void)
  474. {
  475. struct tcp_pcb *pcb;
  476. /*create new pcb*/
  477. pcb = tcp_new();
  478. /* bind HTTP traffic to pcb */
  479. tcp_bind(pcb, IP_ADDR_ANY, 80);
  480. /* start listening on port 80 */
  481. pcb = tcp_listen(pcb);
  482. /* define callback function for TCP connection setup */
  483. tcp_accept(pcb, http_accept);
  484. }
  485. /**
  486. * @brief Opens a file defined in fsdata.c ROM filesystem
  487. * @param name : pointer to a file name
  488. * @param file : pointer to a fs_file structure
  489. * @retval 1 if success, 0 if fail
  490. */
  491. static int fs_open(char *name, struct fs_file *file)
  492. {
  493. struct fsdata_file_noconst *f;
  494. for (f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next)
  495. {
  496. if (!strcmp(name, f->name))
  497. {
  498. file->data = f->data;
  499. file->len = f->len;
  500. return 1;
  501. }
  502. }
  503. return 0;
  504. }
  505. /**
  506. * @brief Extract the Content_Length data from HTML data
  507. * @param data : pointer on receive packet buffer
  508. * @param len : buffer length
  509. * @retval size : Content_length in numeric format
  510. */
  511. static uint32_t Parse_Content_Length(char *data, uint32_t len)
  512. {
  513. uint32_t i=0,size=0, S=1;
  514. int32_t j=0;
  515. char sizestring[6], *ptr;
  516. ContentLengthOffset =0;
  517. /* find Content-Length data in packet buffer */
  518. for (i=0;i<len;i++)
  519. {
  520. if (strncmp ((char*)(data+i), Content_Length, 16)==0)
  521. {
  522. ContentLengthOffset = i+16;
  523. break;
  524. }
  525. }
  526. /* read Content-Length value */
  527. if (ContentLengthOffset)
  528. {
  529. i=0;
  530. ptr = (char*)(data + ContentLengthOffset);
  531. while(*(ptr+i)!=0x0d)
  532. {
  533. sizestring[i] = *(ptr+i);
  534. i++;
  535. ContentLengthOffset++;
  536. }
  537. if (i>0)
  538. {
  539. /* transform string data into numeric format */
  540. for(j=i-1;j>=0;j--)
  541. {
  542. size += (sizestring[j]-0x30)*S;
  543. S=S*10;
  544. }
  545. }
  546. }
  547. return size;
  548. }
  549. /**
  550. * @brief writes received data in flash
  551. * @param ptr: data pointer
  552. * @param len: data length
  553. * @retval none
  554. */
  555. void IAP_HTTP_writedata(char * ptr, uint32_t len)
  556. {
  557. uint32_t count, i=0, j=0;
  558. /* check if any left bytes from previous packet transfer*/
  559. /* if it is the case do a concat with new data to create a 32-bit word */
  560. if (LeftBytes)
  561. {
  562. while(LeftBytes<=3)
  563. {
  564. if(len>(j+1))
  565. {
  566. LeftBytesTab[LeftBytes++] = *(ptr+j);
  567. }
  568. else
  569. {
  570. LeftBytesTab[LeftBytes++] = 0xFF;
  571. }
  572. j++;
  573. }
  574. FLASH_If_Write(&FlashWriteAddress, (u32*)(LeftBytesTab),1);
  575. LeftBytes =0;
  576. /* update data pointer */
  577. ptr = (char*)(ptr+j);
  578. len = len -j;
  579. }
  580. /* write received bytes into flash */
  581. count = len/4;
  582. /* check if remaining bytes < 4 */
  583. i= len%4;
  584. if (i>0)
  585. {
  586. if (TotalReceived != size)
  587. {
  588. /* store bytes in LeftBytesTab */
  589. LeftBytes=0;
  590. for(;i>0;i--)
  591. LeftBytesTab[LeftBytes++] = *(char*)(ptr+ len-i);
  592. }
  593. else count++;
  594. }
  595. FLASH_If_Write(&FlashWriteAddress, (u32*)ptr ,count);
  596. }
  597. uint32_t ReturnFlashWriteAddress(void)
  598. {
  599. return FlashWriteAddress;
  600. }
  601. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/