httpserver.c 18 KB

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