httpserver.c 18 KB

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