X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/fa3135d48530930aefd5ef4ca9d0def3faae474d..75d27f8ef0873157c4ca14dc41d1eb4139e0180d:/Projects/Webserver/Lib/HTTPServerApp.c diff --git a/Projects/Webserver/Lib/HTTPServerApp.c b/Projects/Webserver/Lib/HTTPServerApp.c index 3f8a2c338..5f0b2cfcd 100644 --- a/Projects/Webserver/Lib/HTTPServerApp.c +++ b/Projects/Webserver/Lib/HTTPServerApp.c @@ -96,62 +96,64 @@ void WebserverApp_Callback(void) char* AppData = (char*)uip_appdata; uint16_t AppDataSize = 0; - if (uip_aborted() || uip_timedout()) - { - /* Close the file before terminating, if it is open */ - f_close(&AppState->FileToSend); - - AppState->CurrentState = WEBSERVER_STATE_Closed; - - return; - } - else if (uip_closed()) + if (uip_aborted() || uip_timedout() || uip_closed()) { + /* Check if the open file needs to be closed */ + if (AppState->FileOpen) + { + f_close(&AppState->FileHandle); + AppState->FileOpen = false; + } + + AppState->PrevState = WEBSERVER_STATE_Closed; AppState->CurrentState = WEBSERVER_STATE_Closed; return; } else if (uip_connected()) { - /* New connection - initialize connection state and data pointer to the appropriate HTTP header */ + /* New connection - initialize connection state values */ + AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile; AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile; + AppState->FileOpen = false; + } + else if (uip_rexmit()) + { + /* Re-try last state */ + AppState->CurrentState = AppState->PrevState; } switch (AppState->CurrentState) { case WEBSERVER_STATE_OpenRequestedFile: /* Wait for the packet containing the request header */ - if (uip_datalen()) + if (uip_newdata()) { + char* RequestToken = strtok(AppData, " "); + /* Must be a GET request, abort otherwise */ - if (strncmp(AppData, "GET ", (sizeof("GET ") - 1)) != 0) + if (strcmp(RequestToken, "GET") != 0) { uip_abort(); break; } - /* Copy over the requested filename from the GET request as all-lowercase */ - for (uint8_t i = 0; i < (sizeof(AppState->FileName) - 1); i++) - { - AppState->FileName[i] = tolower(AppData[sizeof("GET ") + i]); - - if (AppState->FileName[i] == ' ') - { - AppState->FileName[i] = 0x00; - break; - } - } + char* RequestedFileName = strtok(NULL, " "); - /* Ensure requested filename is null-terminated */ - AppState->FileName[(sizeof(AppState->FileName) - 1)] = 0x00; - - /* If no filename specified, assume the default of index.htm */ - if (AppState->FileName[0] == 0x00) + /* If the requested filename has more that just the leading '/' path in it, copy it over */ + if (strlen(RequestedFileName) > 1) + strncpy(AppState->FileName, &RequestedFileName[1], (sizeof(AppState->FileName) - 1)); + else strcpy(AppState->FileName, "index.htm"); + + /* Ensure filename is null-terminated */ + AppState->FileName[(sizeof(AppState->FileName) - 1)] = 0x00; /* Try to open the file from the Dataflash disk */ - AppState->FileOpen = (f_open(&AppState->FileToSend, AppState->FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK); + AppState->FileOpen = (f_open(&AppState->FileHandle, AppState->FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK); + AppState->CurrentFilePos = 0; + AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile; AppState->CurrentState = WEBSERVER_STATE_SendResponseHeader; } @@ -169,8 +171,7 @@ void WebserverApp_Callback(void) strncpy_P(AppData, HTTP404Header, AppDataSize); } - uip_send(AppData, AppDataSize); - + AppState->PrevState = WEBSERVER_STATE_SendResponseHeader; AppState->CurrentState = WEBSERVER_STATE_SendMIMETypeHeader; break; case WEBSERVER_STATE_SendMIMETypeHeader: @@ -205,32 +206,45 @@ void WebserverApp_Callback(void) /* Add the end-of line terminator and end-of-headers terminator after the MIME type */ strncpy(&AppData[AppDataSize], "\r\n\r\n", sizeof("\r\n\r\n")); AppDataSize += (sizeof("\r\n\r\n") - 1); - - uip_send(AppData, AppDataSize); } + AppState->PrevState = WEBSERVER_STATE_SendMIMETypeHeader; AppState->CurrentState = WEBSERVER_STATE_SendData; break; case WEBSERVER_STATE_SendData: /* If end of file/file not open, progress to the close state */ - if (!(AppState->FileOpen)) + if (!(AppState->FileOpen) && !(uip_rexmit())) { - f_close(&AppState->FileToSend); + f_close(&AppState->FileHandle); uip_close(); + + AppState->PrevState = WEBSERVER_STATE_Closed; AppState->CurrentState = WEBSERVER_STATE_Closed; break; } uint16_t MaxSegSize = uip_mss(); + /* Return file pointer to the last ACKed position */ + f_lseek(&AppState->FileHandle, AppState->CurrentFilePos); + /* Read the next chunk of data from the open file */ - f_read(&AppState->FileToSend, AppData, MaxSegSize, &AppDataSize); - AppState->FileOpen = (MaxSegSize == AppDataSize); + f_read(&AppState->FileHandle, AppData, MaxSegSize, &AppDataSize); + + /* If we are not re-transmitting a lost segment, advance file position */ + if (uip_acked() && !(uip_rexmit())) + { + AppState->FileOpen = (AppDataSize > 0); + AppState->CurrentFilePos += AppDataSize; + } + + /* Stay in the SendData state if retransmission is required until all data sent */ + AppState->PrevState = WEBSERVER_STATE_SendData; - /* If data was read, send it to the client */ - if (AppDataSize) - uip_send(AppData, AppDataSize); - break; } + + /* If data has been loaded into the application buffer by the server, send it to the client */ + if (AppDataSize) + uip_send(AppData, AppDataSize); }