Add TCP retransmission support to the HTTP webserver in the Webserver project, so that lost segments are retransmitted as needed.

pull/1469/head
Dean Camera 15 years ago
parent 254a0c1ae8
commit e8b8ed2bad

@ -14,7 +14,7 @@
/ Function and Buffer Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 1 /* 0 or 1 */
#define _FS_TINY 0 /* 0 or 1 */
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
/ object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */

@ -96,17 +96,16 @@ void WebserverApp_Callback(void)
char* AppData = (char*)uip_appdata;
uint16_t AppDataSize = 0;
if (uip_aborted() || uip_timedout())
if (uip_aborted() || uip_timedout() || uip_closed())
{
/* Close the file before terminating, if it is open */
f_close(&AppState->FileToSend);
AppState->CurrentState = WEBSERVER_STATE_Closed;
return;
}
else if (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;
@ -114,14 +113,20 @@ void WebserverApp_Callback(void)
else if (uip_connected())
{
/* New connection - initialize connection state and data pointer to the appropriate HTTP header */
AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile;
AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile;
}
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())
{
/* Must be a GET request, abort otherwise */
if (strncmp(AppData, "GET ", (sizeof("GET ") - 1)) != 0)
@ -150,8 +155,10 @@ void WebserverApp_Callback(void)
strcpy(AppState->FileName, "index.htm");
/* 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;
}
@ -171,6 +178,7 @@ void WebserverApp_Callback(void)
uip_send(AppData, AppDataSize);
AppState->PrevState = WEBSERVER_STATE_SendResponseHeader;
AppState->CurrentState = WEBSERVER_STATE_SendMIMETypeHeader;
break;
case WEBSERVER_STATE_SendMIMETypeHeader:
@ -209,27 +217,41 @@ void WebserverApp_Callback(void)
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 if retransmitting */
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);
AppState->FileOpen = (AppDataSize > 0);
/* If data was read, send it to the client */
if (AppDataSize)
{
/* If we are not re-transmitting a lost segment, advance file position */
if (!(uip_rexmit()))
AppState->CurrentFilePos += AppDataSize;
uip_send(AppData, AppDataSize);
}
AppState->PrevState = WEBSERVER_STATE_SendData;
break;
}

@ -52,7 +52,7 @@ void uIPManagement_Init(void)
{
/* uIP Timing Initialization */
clock_init();
timer_set(&ConnectionTimer, CLOCK_SECOND / 2);
timer_set(&ConnectionTimer, CLOCK_SECOND / 100);
timer_set(&ARPTimer, CLOCK_SECOND * 10);
/* uIP Stack Initialization */

@ -5,10 +5,13 @@
typedef struct
{
uint8_t PrevState;
uint8_t CurrentState;
FIL FileHandle;
char FileName[13];
FIL FileToSend;
bool FileOpen;
uint32_t CurrentFilePos;
} uip_tcp_appstate_t;
typedef struct

@ -45,10 +45,10 @@ USB_ClassInfo_RNDIS_Host_t Ethernet_RNDIS_Interface =
.Config =
{
.DataINPipeNumber = 1,
.DataINPipeDoubleBank = false,
.DataINPipeDoubleBank = true,
.DataOUTPipeNumber = 2,
.DataOUTPipeDoubleBank = false,
.DataOUTPipeDoubleBank = true,
.NotificationPipeNumber = 3,
.NotificationPipeDoubleBank = false,

Loading…
Cancel
Save