123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- #include "httpserver.h"
- #include "lwip/tcp.h"
- #include "fsdata.c"
- #include "main.h"
- #include "flash_if.h"
- #include "common_config.h"
- #include "settings_api.h"
- #include "crc.h"
- #include "gpio_io.h"
- #include "systick.h"
- #include <string.h>
- #include "tinystdio.h"
- #define FILENAME_MAX_LEN 30
- /**
- * @brief Общая структура настроек
- */
- extern SETTINGS_t sSettings;
- extern uint8_t fDoneReset;
- extern uint8_t fErrorReset;
- char debugMsg[40];
- static vu32 DataFlag=0;
- static vu32 size =0;
- static __IO uint32_t FlashWriteAddress;
- static u32 TotalReceived=0;
- static char LeftBytesTab[4];
- static u8 LeftBytes=0;
- static __IO u8 resetpage=0;
- static uint32_t ContentLengthOffset =0,BrowserFlag=0;
- static __IO uint32_t TotalData=0, checklogin=0;
- static bool fEraseFlash = true;
- static bool hw_validated = false;
- static uint32_t ContentOffset = 0;
- static uint8_t reqCounter = 0;
- static uint8_t reqTimer = 0;
- struct http_state
- {
- char *file;
- u32_t left;
- };
- htmlpageState htmlpage;
-
- static const char http_crnl_2[4] =
- /* "\r\n--" */
- {0xd, 0xa,0x2d,0x2d};
- static const char octet_stream[14] =
- /* "octet-stream" */
- {0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,0x0d, };
- static const char Content_Length[17] =
- /* Content Length */
- {0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67,0x74, 0x68, 0x3a, 0x20, };
- static uint32_t Parse_Content_Length(char *data, uint32_t len);
- char* Parce_Boundary(const char* data, uint32_t len, char* dst, uint8_t dstlen);
- static void IAP_HTTP_writedata(char* data, uint32_t len);
- /* file must be allocated by caller and will be filled in
- by the function. */
- static int fs_open(char *name, struct fs_file *file);
- uint16_t printLen = 0;
- char printBuf[1500];
- uint32_t oldAdd = USER_FLASH_FIRST_PAGE_ADDRESS;
- uint32_t deltaAdd = 0;
- /**
- * @brief callback function for handling connection errors
- * @param arg: pointer to an argument to be passed to callback function
- * @param err: LwIP error code
- * @retval none
- */
- static void conn_err(void *arg, err_t err)
- {
- struct http_state *hs;
- hs = arg;
- mem_free(hs);
- }
- /**
- * @brief closes tcp connection
- * @param pcb: pointer to a tcp_pcb struct
- * @param hs: pointer to a http_state struct
- * @retval
- */
- static void close_conn(struct tcp_pcb *pcb, struct http_state *hs)
- {
- tcp_arg(pcb, NULL);
- tcp_sent(pcb, NULL);
- tcp_recv(pcb, NULL);
- mem_free(hs);
- tcp_close(pcb);
- reqCounter++;
- }
- /**
- * @brief sends data found in member "file" of a http_state struct
- * @param pcb: pointer to a tcp_pcb struct
- * @param hs: pointer to a http_state struct
- * @retval none
- */
- static void send_data(struct tcp_pcb *pcb, struct http_state *hs)
- {
- err_t err;
- u16_t len;
- /* We cannot send more data than space available in the send
- buffer */
- if (tcp_sndbuf(pcb) < hs->left)
- {
- len = tcp_sndbuf(pcb);
- }
- else
- {
- len = hs->left;
- }
- err = tcp_write(pcb, hs->file, len, 0);
- if (err == ERR_OK)
- {
- hs->file += len;
- hs->left -= len;
- }
- }
- /**
- * @brief tcp poll callback function
- * @param arg: pointer to an argument to be passed to callback function
- * @param pcb: pointer on tcp_pcb structure
- * @retval err_t
- */
- static err_t http_poll(void *arg, struct tcp_pcb *pcb)
- {
- if (arg == NULL)
- {
- tcp_close(pcb);
- }
- else
- {
- send_data(pcb, (struct http_state *)arg);
- }
- return ERR_OK;
- }
- /**
- * @brief callback function called after a successfull TCP data packet transmission
- * @param arg: pointer to an argument to be passed to callback function
- * @param pcb: pointer on tcp_pcb structure
- * @param len
- * @retval err : LwIP error code
- */
- static err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
- {
- struct http_state *hs;
- hs = arg;
- if (hs->left > 0){
- // printf("send");
- send_data(pcb, hs);
- }
- else
- {
- printf("close");
- close_conn(pcb, hs);
-
- if (htmlpage == UploadDonePage)
- fDoneReset = 1;
- else if (htmlpage == UploadErrorPage)
- fErrorReset = 1;
- }
- return ERR_OK;
- }
- /**
- * @brief callback function for handling TCP HTTP traffic
- * @param arg: pointer to an argument structure to be passed to callback function
- * @param pcb: pointer to a tcp_pcb structure
- * @param p: pointer to a packet buffer
- * @param err: LwIP error code
- * @retval err
- */
- /* goback.cgi - возврат в основную прошивку */
- /* upload.cgi - загрузка новой прошивки */
- static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
- {
- int32_t i, len=0;
- uint32_t DataOffset, FilenameOffset;
- char *data, *ptr, filename[13];
- struct fs_file file = {0, 0};
- struct http_state *hs;
- hs = arg;
-
-
- if (err == ERR_OK && p != NULL)
- {
- /* Inform TCP that we have taken the data */
- tcp_recved(pcb, p->tot_len);
-
- if (hs->file == NULL)
- {
- data = p->payload;
- len = p->tot_len;
-
- printLen = p->tot_len;
- memcpy(printBuf, p->payload , printLen);
- //printf(printBuf);
-
- /* process HTTP GET requests */
- if (strncmp(data, "GET /", 5) == 0)
- {/*
- if ((strncmp(data, "GET /resetmcu.cgi", 17) ==0)&&(htmlpage == UploadDonePage))
- {
- htmlpage = ResetDonePage;
- fs_open("/reset.html", &file);
- hs->file = file.data;
- hs->left = file.len;
- pbuf_free(p);
- send_data(pcb, hs);
- resetpage = 1;
- tcp_sent(pcb, http_sent);
- }*/
- if (strncmp(data, "GET /upload.css", 15) == 0)
- {
- fs_open("/upload.css", &file);
- hs->file = file.data;
- hs->left = file.len;
- pbuf_free(p);
- send_data(pcb, hs);
- tcp_sent(pcb, http_sent);
- }
- else if (strncmp(data, "GET /upload.js", 14) == 0)
- {
- fs_open("/upload.js", &file);
- hs->file = file.data;
- hs->left = file.len;
- pbuf_free(p);
- send_data(pcb, hs);
- tcp_sent(pcb, http_sent);
- }
- /* Возврат в основную прошивку. Сбрасываем флаг loadmode,
- сохраняем настройки и перезагружаемся */
- else if (strncmp(data, "GET /goback.cgi", 15)==0)
- {
- RTC_WriteBackupRegister(RTC_BKP_DR1, 0);
- /* sSettings.bootParams.loadMode = 0;
- SETTINGS_Save();*/
- Delay_ms(1010);
- NVIC_SystemReset();
- }
- else if (strncmp(data, "GET /favicon.ico", 16) == 0)
- {
- fs_open("/favicon.ico", &file);
- hs->file = file.data;
- hs->left = file.len;
- send_data(pcb, hs);
- tcp_sent(pcb, http_sent);
- }
- else
- {
- /*send the login page (which is the index page) */
- htmlpage = LoginPage;
- fs_open("/index.html", &file);
- hs->file = file.data;
- hs->left = file.len;
- pbuf_free(p);
- send_data(pcb, hs);
- tcp_sent(pcb, http_sent);
- }
- }
- #if 1
- /* process POST request for file upload and incoming data packets after POST request*/
- else if ((strncmp(data, "POST /upload.cgi",16) == 0) || (DataFlag >= 1))
- {
- /*if (fEraseFlash) {
- FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
- fEraseFlash = false;
- }*/
- static char boundary[70];
- static char boundary_buf[70];
- static char *pbound = NULL;
- DataOffset = 0;
-
- /* POST Packet received */
- if (DataFlag == 0)
- {
- BrowserFlag = 0;
- TotalReceived = 0;
- /* parse packet for Content-length field */
- size = Parse_Content_Length(data, p->tot_len);
- pbound = Parce_Boundary(data, p->tot_len, boundary, sizeof(boundary));
- //printf("boundary: %s\r\n", boundary);
- /* parse packet for the octet-stream field */
- for (i = 0; i < len; i++)
- {
- /* TODO remove if tested */
- // if (strncmp ((char*)(data+i), octet_stream, 13)==0)
- // {
- // DataOffset = i + 16;
- // break;
- // }
- if (pbound != NULL) {
- if (strncmp ((char*)(data+i), boundary, strlen(boundary))==0)
- {
- ContentOffset = i;
- /* parse packet for "\r\n\r\n" field */
- for (int32_t j= 0; j < len; j++) {
- if (strncmp ((char*)(data+i+j), "\r\n\r\n", 4)==0)
- {
- DataOffset = i + j + 4;
- break;
- }
- }
- }
- }
- }
- /* case of MSIE8 : we do not receive data in the POST packet*/
- if (DataOffset == 0)
- {
- DataFlag++;
- BrowserFlag = 1;
- pbuf_free(p);
- return ERR_OK;
- }
- /* case of Mozilla Firefox v3.6 : we receive data in the POST packet*/
- else
- {
- TotalReceived = len - ContentOffset;
- }
- }
-
- if (((DataFlag ==1)&&(BrowserFlag==1)) || ((DataFlag ==0)&&(BrowserFlag==0)))
- {
- if ((DataFlag ==0)&&(BrowserFlag==0))
- {
- DataFlag++;
- }
- else if ((DataFlag ==1)&&(BrowserFlag==1))
- {
- /* parse packet for the octet-stream field */
- for (i = 0; i < len; i++)
- {
- if (pbound != NULL) {
- if (strncmp ((char*)(data+i), boundary, strlen(boundary))==0)
- {
- /* parse packet for "\r\n\r\n" field */
- for (int32_t j= 0; j < len; j++) {
- if (strncmp ((char*)(data+i+j), "\r\n\r\n", 4)==0)
- {
- DataOffset = i + j + 4;
- break;
- }
- }
- }
- }
- }
- TotalReceived += len;
- DataFlag++;
- }
-
- /* parse packet for the filename field */
- FilenameOffset = 0;
- for (i = 0; i < len; i++)
- {
- if (strncmp ((char*)(data+i), "filename=", 9)==0)
- {
- FilenameOffset = i+10;
- break;
- }
- }
- i = 0;
- if (FilenameOffset)
- {
- while((*(data+FilenameOffset + i)!=0x22 )&&(i<FILENAME_MAX_LEN))
- {
- filename[i] = *(data+FilenameOffset + i);
- i++;
- }
- filename[i] = 0x0;
- }
-
- /* Set HW revision validation marker */
- hw_validated = false;
- if (i==0)
- {
- htmlpage = FileUploadPage;
- /* no filename, in this case reload upload page */
- fs_open("/upload.html", &file);
- hs->file = file.data;
- hs->left = file.len;
- pbuf_free(p);
-
- /* send index.html page */
- send_data(pcb, hs);
-
- /* Tell TCP that we wish be to informed of data that has been
- successfully sent by a call to the http_sent() function. */
- tcp_sent(pcb, http_sent);
- DataFlag=0;
- return ERR_OK;
- }
- PRINT_USART("\n\r IAP using HTTP \n\r");
- sprintf(debugMsg, "File: %s\n\r",filename);
- PRINT_USART(debugMsg);
- PRINT_USART("State: Erasing...\n\r");
-
- TotalData =0 ;
- /* init flash */
- /// FLASH_If_Init();
- /* erase user flash area */
- //FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
- // / FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
-
- /*indicate start of flash programming */
- PRINT_USART("\n\rState: Programming..\n\r");
- }
- /* DataFlag >1 => the packet is data only */
- else
- {
- TotalReceived +=len;
- }
-
- ptr = (char*)(data + DataOffset);
- len-= DataOffset;
-
- /* update Total data received counter */
- TotalData +=len;
-
- /* check if last data packet */
- if (TotalReceived == size)
- {
- /* if last packet need to remove the http boundary tag */
- /* parse packet for "\r\n--" starting from end of data */
- /*
- i = 4;
- while (strncmp ((char*)(data+ p->tot_len -i),http_crnl_2 , 4))
- {
- i++;
- }
- len -= i;
- TotalData -= i;
- */
- /* write data in Flash */
- if(hw_validated){
- if (len)
- IAP_HTTP_writedata(ptr,len);
- DataFlag=0;
- htmlpage = UploadDonePage;
- PRINT_USART("Tot bytes Received:\n\r");
- sprintf(debugMsg, "%d bytes \n\r",TotalData);
- PRINT_USART(debugMsg);
- PRINT_USART("State: Prog Finished \n\r");
- }
- /* Проверяем CRC */
- if (hw_validated && CRC_Read() == CRC_Calcucate()) {
- fs_open("/success.html", &file);
- hs->file = file.data;
- hs->left = file.len;
- send_data(pcb, hs);
- tcp_sent(pcb, http_sent);
- htmlpage = UploadDonePage;
- }
- else
- {
- if(hw_validated)
- FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
- fEraseFlash = false;
- fs_open("/error.html", &file);
- hs->file = file.data;
- hs->left = file.len;
- send_data(pcb, hs);
- tcp_sent(pcb, http_sent);
- htmlpage = UploadErrorPage;
- }
- /*
- sSettings.bootParams.loadMode = 0;
- SETTINGS_Save();
- IO_KeyBlockOn();
- Delay_ms(1010);
- NVIC_SystemReset();
- */
- }
- /* not last data packet */
- else
- {
- if ((TotalData >= HW_REV_OFFSET + HW_REV_LEN) && (!hw_validated)) {
- char rev[HW_REV_LEN];
- strncpy(rev, HW_REV, HW_REV_LEN);
- if (strcmp((char *)(ptr + HW_REV_OFFSET), rev) != 0) {
- // DataFlag = 0;
- pbuf_free(p);
- /* fs_open("/error.html", &file);
- hs->file = file.data;
- hs->left = file.len;*/
- /* send_data(pcb, hs);
- tcp_sent(pcb, http_sent);*/
- // printf("start");
- // htmlpage = UploadErrorPage;
- // fErrorReset = 1;
- // pbuf_free(p);
- //close_conn(pcb, hs);
- return ERR_OK;
- }
- else {
- hw_validated = true;
- // Erase flash
- if (fEraseFlash) {
- FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
- fEraseFlash = false;
- }
- // Init flash
- FLASH_If_Init();
- FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
- }
- }
- /* write data in flash */
- if(len)
- IAP_HTTP_writedata(ptr,len);
- }
- pbuf_free(p);
- }
- else
- {
- /* Bad HTTP requests */
- PRINT_USART("Bad HTTP request\n\r");
- pbuf_free(p);
- close_conn(pcb, hs);
- }
- #endif
- }
- else
- {
- pbuf_free(p);
- close_conn(pcb,hs);
- }
- }
- if (err == ERR_OK && p == NULL)
- {
- /* received empty frame */
- PRINT_USART("Received empty frame\n\r");
- close_conn(pcb, hs);
- }
- return ERR_OK;
- }
- /**
- * @brief callback function on TCP connection setup ( on port 80)
- * @param arg: pointer to an argument structure to be passed to callback function
- * @param pcb: pointer to a tcp_pcb structure
- * ¶m err: Lwip stack error code
- * @retval err
- */
- static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
- {
- struct http_state *hs;
- /* Allocate memory for the structure that holds the state of the connection */
- hs = mem_malloc(sizeof(struct http_state));
- if (hs == NULL)
- {
- return ERR_MEM;
- }
- /* Initialize the structure. */
- hs->file = NULL;
- hs->left = 0;
- /* Tell TCP that this is the structure we wish to be passed for our
- callbacks. */
- tcp_arg(pcb, hs);
- /* Tell TCP that we wish to be informed of incoming data by a call
- to the http_recv() function. */
- tcp_recv(pcb, http_recv);
- tcp_err(pcb, conn_err);
- tcp_poll(pcb, http_poll, 10);
- return ERR_OK;
- }
- /**
- * @brief intialize HTTP webserver
- * @param none
- * @retval none
- */
- void IAP_httpd_init(void)
- {
- struct tcp_pcb *pcb;
- /*create new pcb*/
- pcb = tcp_new();
- /* bind HTTP traffic to pcb */
- tcp_bind(pcb, IP_ADDR_ANY, 80);
- /* start listening on port 80 */
- pcb = tcp_listen(pcb);
- /* define callback function for TCP connection setup */
- tcp_accept(pcb, http_accept);
- }
- /**
- * @brief Opens a file defined in fsdata.c ROM filesystem
- * @param name : pointer to a file name
- * @param file : pointer to a fs_file structure
- * @retval 1 if success, 0 if fail
- */
- static int fs_open(char *name, struct fs_file *file)
- {
- struct fsdata_file_noconst *f;
- for (f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next)
- {
- if (!strcmp(name, f->name))
- {
- file->data = f->data;
- file->len = f->len;
- return 1;
- }
- }
- return 0;
- }
- /**
- * @brief Extract the Content_Length data from HTML data
- * @param data : pointer on receive packet buffer
- * @param len : buffer length
- * @retval size : Content_length in numeric format
- */
- static uint32_t Parse_Content_Length(char *data, uint32_t len)
- {
- uint32_t i=0,size=0, S=1;
- int32_t j=0;
- char sizestring[6], *ptr;
-
- ContentLengthOffset =0;
- /* find Content-Length data in packet buffer */
- for (i=0;i<len;i++)
- {
- if (strncmp ((char*)(data+i), Content_Length, 16)==0)
- {
- ContentLengthOffset = i+16;
- break;
- }
- }
- /* read Content-Length value */
- if (ContentLengthOffset)
- {
- i=0;
- ptr = (char*)(data + ContentLengthOffset);
- while(*(ptr+i)!=0x0d)
- {
- sizestring[i] = *(ptr+i);
- i++;
- ContentLengthOffset++;
- }
- if (i>0)
- {
- /* transform string data into numeric format */
- for(j=i-1;j>=0;j--)
- {
- size += (sizestring[j]-0x30)*S;
- S=S*10;
- }
- }
- }
- return size;
- }
- char* Parce_Boundary(const char* data, uint32_t len, char* dst, uint8_t dstlen) {
- char *ptr = NULL;
- char *boundary = NULL;
- uint8_t i = 0;
- for (uint32_t j = 0; j < len; j++) {
- if (strncmp ((char*)(data + j), "boundary=", 9) == 0) {
- boundary = (char*)data + j + 9;
- break;
- }
- }
- if (!boundary) return NULL;
- *dst++ = '-';
- *dst++ = '-';
- ptr = boundary;
- while ((*ptr != 0x0d) && (i < dstlen - 4))
- {
- *dst++ = *ptr++;
- i++;
- }
- //*dst++ = '-';
- //*dst++ = '-';
- *dst = '\0';
- if (i > 0)
- return boundary;
- else
- return NULL;
- }
- /**
- * @brief writes received data in flash
- * @param ptr: data pointer
- * @param len: data length
- * @retval none
- */
- void IAP_HTTP_writedata(char * ptr, uint32_t len)
- {
- uint32_t count, i=0, j=0;
- /* check if any left bytes from previous packet transfer*/
- /* if it is the case do a concat with new data to create a 32-bit word */
- if (LeftBytes)
- {
- while(LeftBytes<=3)
- {
- if(len>(j+1))
- {
- LeftBytesTab[LeftBytes++] = *(ptr+j);
- }
- else
- {
- LeftBytesTab[LeftBytes++] = 0xFF;
- }
- j++;
- }
- FLASH_If_Write(&FlashWriteAddress, (u32*)(LeftBytesTab),1);
-
- LeftBytes =0;
-
- /* update data pointer */
- ptr = (char*)(ptr+j);
- len = len -j;
- }
-
- /* write received bytes into flash */
- count = len/4;
-
- /* check if remaining bytes < 4 */
- i= len%4;
- if (i>0)
- {
- if (TotalReceived != size)
- {
- /* store bytes in LeftBytesTab */
- LeftBytes=0;
- for(;i>0;i--)
- LeftBytesTab[LeftBytes++] = *(char*)(ptr+ len-i);
- }
- else count++;
- }
- FLASH_If_Write(&FlashWriteAddress, (u32*)ptr ,count);
- }
- uint32_t ReturnFlashWriteAddress(void)
- {
- return FlashWriteAddress;
- }
- /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
|