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 / 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 /* 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 / object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */ / data transfer. This reduces memory consumption 512 bytes each file object. */

@ -96,17 +96,16 @@ void WebserverApp_Callback(void)
char* AppData = (char*)uip_appdata; char* AppData = (char*)uip_appdata;
uint16_t AppDataSize = 0; 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; AppState->CurrentState = WEBSERVER_STATE_Closed;
return; return;
@ -114,14 +113,20 @@ void WebserverApp_Callback(void)
else if (uip_connected()) else if (uip_connected())
{ {
/* New connection - initialize connection state and data pointer to the appropriate HTTP header */ /* New connection - initialize connection state and data pointer to the appropriate HTTP header */
AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile;
AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile; AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile;
} }
else if (uip_rexmit())
{
/* Re-try last state */
AppState->CurrentState = AppState->PrevState;
}
switch (AppState->CurrentState) switch (AppState->CurrentState)
{ {
case WEBSERVER_STATE_OpenRequestedFile: case WEBSERVER_STATE_OpenRequestedFile:
/* Wait for the packet containing the request header */ /* Wait for the packet containing the request header */
if (uip_datalen()) if (uip_newdata())
{ {
/* Must be a GET request, abort otherwise */ /* Must be a GET request, abort otherwise */
if (strncmp(AppData, "GET ", (sizeof("GET ") - 1)) != 0) if (strncmp(AppData, "GET ", (sizeof("GET ") - 1)) != 0)
@ -150,8 +155,10 @@ void WebserverApp_Callback(void)
strcpy(AppState->FileName, "index.htm"); strcpy(AppState->FileName, "index.htm");
/* Try to open the file from the Dataflash disk */ /* 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; AppState->CurrentState = WEBSERVER_STATE_SendResponseHeader;
} }
@ -171,6 +178,7 @@ void WebserverApp_Callback(void)
uip_send(AppData, AppDataSize); uip_send(AppData, AppDataSize);
AppState->PrevState = WEBSERVER_STATE_SendResponseHeader;
AppState->CurrentState = WEBSERVER_STATE_SendMIMETypeHeader; AppState->CurrentState = WEBSERVER_STATE_SendMIMETypeHeader;
break; break;
case WEBSERVER_STATE_SendMIMETypeHeader: case WEBSERVER_STATE_SendMIMETypeHeader:
@ -209,27 +217,41 @@ void WebserverApp_Callback(void)
uip_send(AppData, AppDataSize); uip_send(AppData, AppDataSize);
} }
AppState->PrevState = WEBSERVER_STATE_SendMIMETypeHeader;
AppState->CurrentState = WEBSERVER_STATE_SendData; AppState->CurrentState = WEBSERVER_STATE_SendData;
break; break;
case WEBSERVER_STATE_SendData: case WEBSERVER_STATE_SendData:
/* If end of file/file not open, progress to the close state */ /* 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(); uip_close();
AppState->PrevState = WEBSERVER_STATE_Closed;
AppState->CurrentState = WEBSERVER_STATE_Closed; AppState->CurrentState = WEBSERVER_STATE_Closed;
break; break;
} }
uint16_t MaxSegSize = uip_mss(); 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 */ /* Read the next chunk of data from the open file */
f_read(&AppState->FileToSend, AppData, MaxSegSize, &AppDataSize); f_read(&AppState->FileHandle, AppData, MaxSegSize, &AppDataSize);
AppState->FileOpen = (MaxSegSize == AppDataSize); AppState->FileOpen = (AppDataSize > 0);
/* If data was read, send it to the client */ /* If data was read, send it to the client */
if (AppDataSize) if (AppDataSize)
uip_send(AppData, 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; break;
} }

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

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

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

Loading…
Cancel
Save