httpserver.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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. RTC_WriteBackupRegister(RTC_BKP_DR1, 0);
  217. /* sSettings.bootParams.loadMode = 0;
  218. SETTINGS_Save();*/
  219. Delay_ms(1010);
  220. NVIC_SystemReset();
  221. }
  222. else if (strncmp(data, "GET /favicon.ico", 16) == 0)
  223. {
  224. fs_open("/favicon.ico", &file);
  225. hs->file = file.data;
  226. hs->left = file.len;
  227. send_data(pcb, hs);
  228. tcp_sent(pcb, http_sent);
  229. }
  230. else
  231. {
  232. /*send the login page (which is the index page) */
  233. htmlpage = LoginPage;
  234. fs_open("/index.html", &file);
  235. hs->file = file.data;
  236. hs->left = file.len;
  237. pbuf_free(p);
  238. send_data(pcb, hs);
  239. tcp_sent(pcb, http_sent);
  240. }
  241. }
  242. #if 1
  243. /* process POST request for file upload and incoming data packets after POST request*/
  244. else if ((strncmp(data, "POST /upload.cgi",16) == 0) || (DataFlag >= 1))
  245. {
  246. if (fEraseFlash) {
  247. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  248. fEraseFlash = false;
  249. }
  250. DataOffset = 0;
  251. /* POST Packet received */
  252. if (DataFlag == 0)
  253. {
  254. BrowserFlag = 0;
  255. TotalReceived = 0;
  256. /* parse packet for Content-length field */
  257. size = Parse_Content_Length(data, p->tot_len);
  258. /* parse packet for the octet-stream field */
  259. for (i = 0; i < len; i++)
  260. {
  261. if (strncmp ((char*)(data+i), octet_stream, 13)==0)
  262. {
  263. DataOffset = i + 16;
  264. break;
  265. }
  266. }
  267. /* case of MSIE8 : we do not receive data in the POST packet*/
  268. if (DataOffset == 0)
  269. {
  270. DataFlag++;
  271. BrowserFlag = 1;
  272. pbuf_free(p);
  273. return ERR_OK;
  274. }
  275. /* case of Mozilla Firefox v3.6 : we receive data in the POST packet*/
  276. else
  277. {
  278. TotalReceived = len - (ContentLengthOffset + 4);
  279. }
  280. }
  281. if (((DataFlag ==1)&&(BrowserFlag==1)) || ((DataFlag ==0)&&(BrowserFlag==0)))
  282. {
  283. if ((DataFlag ==0)&&(BrowserFlag==0))
  284. {
  285. DataFlag++;
  286. }
  287. else if ((DataFlag ==1)&&(BrowserFlag==1))
  288. {
  289. /* parse packet for the octet-stream field */
  290. for (i = 0; i < len; i++)
  291. {
  292. if (strncmp ((char*)(data+i), octet_stream, 13)==0)
  293. {
  294. DataOffset = i+16;
  295. break;
  296. }
  297. }
  298. TotalReceived += len;
  299. DataFlag++;
  300. }
  301. /* parse packet for the filename field */
  302. FilenameOffset = 0;
  303. for (i = 0; i < len; i++)
  304. {
  305. if (strncmp ((char*)(data+i), "filename=", 9)==0)
  306. {
  307. FilenameOffset = i+10;
  308. break;
  309. }
  310. }
  311. i = 0;
  312. if (FilenameOffset)
  313. {
  314. while((*(data+FilenameOffset + i)!=0x22 )&&(i<13))
  315. {
  316. filename[i] = *(data+FilenameOffset + i);
  317. i++;
  318. }
  319. filename[i] = 0x0;
  320. }
  321. if (i==0)
  322. {
  323. htmlpage = FileUploadPage;
  324. /* no filename, in this case reload upload page */
  325. fs_open("/upload.html", &file);
  326. hs->file = file.data;
  327. hs->left = file.len;
  328. pbuf_free(p);
  329. /* send index.html page */
  330. send_data(pcb, hs);
  331. /* Tell TCP that we wish be to informed of data that has been
  332. successfully sent by a call to the http_sent() function. */
  333. tcp_sent(pcb, http_sent);
  334. DataFlag=0;
  335. return ERR_OK;
  336. }
  337. PRINT_USART("\n\r IAP using HTTP \n\r");
  338. sprintf(debugMsg, "File: %s\n\r",filename);
  339. PRINT_USART(debugMsg);
  340. PRINT_USART("State: Erasing...\n\r");
  341. TotalData =0 ;
  342. /* init flash */
  343. FLASH_If_Init();
  344. /* erase user flash area */
  345. //FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  346. FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
  347. /*indicate start of flash programming */
  348. PRINT_USART("\n\rState: Programming..\n\r");
  349. }
  350. /* DataFlag >1 => the packet is data only */
  351. else
  352. {
  353. TotalReceived +=len;
  354. }
  355. ptr = (char*)(data + DataOffset);
  356. len-= DataOffset;
  357. /* update Total data received counter */
  358. TotalData +=len;
  359. /* check if last data packet */
  360. if (TotalReceived == size)
  361. {
  362. /* if last packet need to remove the http boundary tag */
  363. /* parse packet for "\r\n--" starting from end of data */
  364. /*
  365. i = 4;
  366. while (strncmp ((char*)(data+ p->tot_len -i),http_crnl_2 , 4))
  367. {
  368. i++;
  369. }
  370. len -= i;
  371. TotalData -= i;
  372. */
  373. /* write data in Flash */
  374. if (len)
  375. IAP_HTTP_writedata(ptr,len);
  376. DataFlag=0;
  377. htmlpage = UploadDonePage;
  378. PRINT_USART("Tot bytes Received:\n\r");
  379. sprintf(debugMsg, "%d bytes \n\r",TotalData);
  380. PRINT_USART(debugMsg);
  381. PRINT_USART("State: Prog Finished \n\r");
  382. /* Проверяем CRC */
  383. if (CRC_Read() == CRC_Calcucate()) {
  384. fs_open("/success.html", &file);
  385. hs->file = file.data;
  386. hs->left = file.len;
  387. send_data(pcb, hs);
  388. tcp_sent(pcb, http_sent);
  389. htmlpage = UploadDonePage;
  390. }
  391. else
  392. {
  393. fs_open("/error.html", &file);
  394. hs->file = file.data;
  395. hs->left = file.len;
  396. send_data(pcb, hs);
  397. tcp_sent(pcb, http_sent);
  398. htmlpage = UploadErrorPage;
  399. }
  400. /*
  401. sSettings.bootParams.loadMode = 0;
  402. SETTINGS_Save();
  403. IO_KeyBlockOn();
  404. Delay_ms(1010);
  405. NVIC_SystemReset();
  406. */
  407. }
  408. /* not last data packet */
  409. else
  410. {
  411. /* write data in flash */
  412. if(len)
  413. IAP_HTTP_writedata(ptr,len);
  414. }
  415. pbuf_free(p);
  416. }
  417. else
  418. {
  419. /* Bad HTTP requests */
  420. PRINT_USART("Bad HTTP request\n\r");
  421. pbuf_free(p);
  422. close_conn(pcb, hs);
  423. }
  424. #endif
  425. }
  426. else
  427. {
  428. pbuf_free(p);
  429. close_conn(pcb,hs);
  430. }
  431. }
  432. if (err == ERR_OK && p == NULL)
  433. {
  434. /* received empty frame */
  435. PRINT_USART("Received empty frame\n\r");
  436. close_conn(pcb, hs);
  437. }
  438. return ERR_OK;
  439. }
  440. /**
  441. * @brief callback function on TCP connection setup ( on port 80)
  442. * @param arg: pointer to an argument structure to be passed to callback function
  443. * @param pcb: pointer to a tcp_pcb structure
  444. * &param err: Lwip stack error code
  445. * @retval err
  446. */
  447. static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
  448. {
  449. struct http_state *hs;
  450. /* Allocate memory for the structure that holds the state of the connection */
  451. hs = mem_malloc(sizeof(struct http_state));
  452. if (hs == NULL)
  453. {
  454. return ERR_MEM;
  455. }
  456. /* Initialize the structure. */
  457. hs->file = NULL;
  458. hs->left = 0;
  459. /* Tell TCP that this is the structure we wish to be passed for our
  460. callbacks. */
  461. tcp_arg(pcb, hs);
  462. /* Tell TCP that we wish to be informed of incoming data by a call
  463. to the http_recv() function. */
  464. tcp_recv(pcb, http_recv);
  465. tcp_err(pcb, conn_err);
  466. tcp_poll(pcb, http_poll, 10);
  467. return ERR_OK;
  468. }
  469. /**
  470. * @brief intialize HTTP webserver
  471. * @param none
  472. * @retval none
  473. */
  474. void IAP_httpd_init(void)
  475. {
  476. struct tcp_pcb *pcb;
  477. /*create new pcb*/
  478. pcb = tcp_new();
  479. /* bind HTTP traffic to pcb */
  480. tcp_bind(pcb, IP_ADDR_ANY, 80);
  481. /* start listening on port 80 */
  482. pcb = tcp_listen(pcb);
  483. /* define callback function for TCP connection setup */
  484. tcp_accept(pcb, http_accept);
  485. }
  486. /**
  487. * @brief Opens a file defined in fsdata.c ROM filesystem
  488. * @param name : pointer to a file name
  489. * @param file : pointer to a fs_file structure
  490. * @retval 1 if success, 0 if fail
  491. */
  492. static int fs_open(char *name, struct fs_file *file)
  493. {
  494. struct fsdata_file_noconst *f;
  495. for (f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next)
  496. {
  497. if (!strcmp(name, f->name))
  498. {
  499. file->data = f->data;
  500. file->len = f->len;
  501. return 1;
  502. }
  503. }
  504. return 0;
  505. }
  506. /**
  507. * @brief Extract the Content_Length data from HTML data
  508. * @param data : pointer on receive packet buffer
  509. * @param len : buffer length
  510. * @retval size : Content_length in numeric format
  511. */
  512. static uint32_t Parse_Content_Length(char *data, uint32_t len)
  513. {
  514. uint32_t i=0,size=0, S=1;
  515. int32_t j=0;
  516. char sizestring[6], *ptr;
  517. ContentLengthOffset =0;
  518. /* find Content-Length data in packet buffer */
  519. for (i=0;i<len;i++)
  520. {
  521. if (strncmp ((char*)(data+i), Content_Length, 16)==0)
  522. {
  523. ContentLengthOffset = i+16;
  524. break;
  525. }
  526. }
  527. /* read Content-Length value */
  528. if (ContentLengthOffset)
  529. {
  530. i=0;
  531. ptr = (char*)(data + ContentLengthOffset);
  532. while(*(ptr+i)!=0x0d)
  533. {
  534. sizestring[i] = *(ptr+i);
  535. i++;
  536. ContentLengthOffset++;
  537. }
  538. if (i>0)
  539. {
  540. /* transform string data into numeric format */
  541. for(j=i-1;j>=0;j--)
  542. {
  543. size += (sizestring[j]-0x30)*S;
  544. S=S*10;
  545. }
  546. }
  547. }
  548. return size;
  549. }
  550. /**
  551. * @brief writes received data in flash
  552. * @param ptr: data pointer
  553. * @param len: data length
  554. * @retval none
  555. */
  556. void IAP_HTTP_writedata(char * ptr, uint32_t len)
  557. {
  558. uint32_t count, i=0, j=0;
  559. /* check if any left bytes from previous packet transfer*/
  560. /* if it is the case do a concat with new data to create a 32-bit word */
  561. if (LeftBytes)
  562. {
  563. while(LeftBytes<=3)
  564. {
  565. if(len>(j+1))
  566. {
  567. LeftBytesTab[LeftBytes++] = *(ptr+j);
  568. }
  569. else
  570. {
  571. LeftBytesTab[LeftBytes++] = 0xFF;
  572. }
  573. j++;
  574. }
  575. FLASH_If_Write(&FlashWriteAddress, (u32*)(LeftBytesTab),1);
  576. LeftBytes =0;
  577. /* update data pointer */
  578. ptr = (char*)(ptr+j);
  579. len = len -j;
  580. }
  581. /* write received bytes into flash */
  582. count = len/4;
  583. /* check if remaining bytes < 4 */
  584. i= len%4;
  585. if (i>0)
  586. {
  587. if (TotalReceived != size)
  588. {
  589. /* store bytes in LeftBytesTab */
  590. LeftBytes=0;
  591. for(;i>0;i--)
  592. LeftBytesTab[LeftBytes++] = *(char*)(ptr+ len-i);
  593. }
  594. else count++;
  595. }
  596. FLASH_If_Write(&FlashWriteAddress, (u32*)ptr ,count);
  597. }
  598. uint32_t ReturnFlashWriteAddress(void)
  599. {
  600. return FlashWriteAddress;
  601. }
  602. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/