char* AppData = (char*)uip_appdata;\r
uint16_t AppDataSize = 0;\r
\r
- if (uip_aborted() || uip_timedout())\r
+ if (uip_aborted() || uip_timedout() || uip_closed())\r
{\r
- /* Close the file before terminating, if it is open */\r
- f_close(&AppState->FileToSend);\r
+ /* Check if the open file needs to be closed */\r
+ if (AppState->FileOpen)\r
+ {\r
+ f_close(&AppState->FileHandle);\r
+ AppState->FileOpen = false;\r
+ }\r
\r
- AppState->CurrentState = WEBSERVER_STATE_Closed;\r
-\r
- return;\r
- }\r
- else if (uip_closed())\r
- {\r
+ AppState->PrevState = WEBSERVER_STATE_Closed;\r
AppState->CurrentState = WEBSERVER_STATE_Closed;\r
\r
return;\r
else if (uip_connected())\r
{\r
/* New connection - initialize connection state and data pointer to the appropriate HTTP header */\r
+ AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile;\r
AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile;\r
}\r
+ else if (uip_rexmit())\r
+ {\r
+ /* Re-try last state */\r
+ AppState->CurrentState = AppState->PrevState;\r
+ }\r
\r
switch (AppState->CurrentState)\r
{\r
case WEBSERVER_STATE_OpenRequestedFile:\r
/* Wait for the packet containing the request header */\r
- if (uip_datalen())\r
+ if (uip_newdata())\r
{\r
/* Must be a GET request, abort otherwise */\r
if (strncmp(AppData, "GET ", (sizeof("GET ") - 1)) != 0)\r
strcpy(AppState->FileName, "index.htm");\r
\r
/* Try to open the file from the Dataflash disk */\r
- AppState->FileOpen = (f_open(&AppState->FileToSend, AppState->FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK);\r
+ AppState->FileOpen = (f_open(&AppState->FileHandle, AppState->FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK);\r
+ AppState->CurrentFilePos = 0;\r
\r
+ AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile;\r
AppState->CurrentState = WEBSERVER_STATE_SendResponseHeader;\r
}\r
\r
\r
uip_send(AppData, AppDataSize);\r
\r
+ AppState->PrevState = WEBSERVER_STATE_SendResponseHeader;\r
AppState->CurrentState = WEBSERVER_STATE_SendMIMETypeHeader;\r
break;\r
case WEBSERVER_STATE_SendMIMETypeHeader:\r
uip_send(AppData, AppDataSize);\r
}\r
\r
+ AppState->PrevState = WEBSERVER_STATE_SendMIMETypeHeader;\r
AppState->CurrentState = WEBSERVER_STATE_SendData; \r
break;\r
case WEBSERVER_STATE_SendData:\r
/* If end of file/file not open, progress to the close state */\r
- if (!(AppState->FileOpen))\r
+ if (!(AppState->FileOpen) && !(uip_rexmit()))\r
{\r
- f_close(&AppState->FileToSend);\r
+ f_close(&AppState->FileHandle);\r
uip_close();\r
+\r
+ AppState->PrevState = WEBSERVER_STATE_Closed;\r
AppState->CurrentState = WEBSERVER_STATE_Closed;\r
break;\r
}\r
\r
uint16_t MaxSegSize = uip_mss();\r
\r
+ /* Return file pointer to the last ACKed position if retransmitting */\r
+ f_lseek(&AppState->FileHandle, AppState->CurrentFilePos);\r
+\r
/* Read the next chunk of data from the open file */\r
- f_read(&AppState->FileToSend, AppData, MaxSegSize, &AppDataSize);\r
- AppState->FileOpen = (MaxSegSize == AppDataSize);\r
+ f_read(&AppState->FileHandle, AppData, MaxSegSize, &AppDataSize);\r
+ AppState->FileOpen = (AppDataSize > 0);\r
\r
/* If data was read, send it to the client */\r
if (AppDataSize)\r
- uip_send(AppData, AppDataSize);\r
- \r
+ {\r
+ /* If we are not re-transmitting a lost segment, advance file position */\r
+ if (!(uip_rexmit()))\r
+ AppState->CurrentFilePos += AppDataSize;\r
+\r
+ uip_send(AppData, AppDataSize);\r
+ }\r
+ \r
+ AppState->PrevState = WEBSERVER_STATE_SendData;\r
+\r
break;\r
}\r
}\r