From e8b8ed2bad293b190c6b2ce9a575e73fbf93e9e2 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 29 Jan 2010 09:21:38 +0000 Subject: Add TCP retransmission support to the HTTP webserver in the Webserver project, so that lost segments are retransmitted as needed. --- Projects/Webserver/Lib/FATFs/ffconf.h | 2 +- Projects/Webserver/Lib/HTTPServerApp.c | 56 ++++++++++++++++++++--------- Projects/Webserver/Lib/uIPManagement.c | 2 +- Projects/Webserver/Lib/uip/conf/apps-conf.h | 5 ++- Projects/Webserver/USBHostMode.c | 4 +-- 5 files changed, 47 insertions(+), 22 deletions(-) (limited to 'Projects') diff --git a/Projects/Webserver/Lib/FATFs/ffconf.h b/Projects/Webserver/Lib/FATFs/ffconf.h index 4b19f1326..3ad7a56af 100644 --- a/Projects/Webserver/Lib/FATFs/ffconf.h +++ b/Projects/Webserver/Lib/FATFs/ffconf.h @@ -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. */ diff --git a/Projects/Webserver/Lib/HTTPServerApp.c b/Projects/Webserver/Lib/HTTPServerApp.c index 3f8a2c338..78c1b131c 100644 --- a/Projects/Webserver/Lib/HTTPServerApp.c +++ b/Projects/Webserver/Lib/HTTPServerApp.c @@ -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); + /* Check if the open file needs to be closed */ + if (AppState->FileOpen) + { + f_close(&AppState->FileHandle); + AppState->FileOpen = false; + } - AppState->CurrentState = WEBSERVER_STATE_Closed; - - return; - } - else if (uip_closed()) - { + 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,28 +217,42 @@ 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) - 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; } } diff --git a/Projects/Webserver/Lib/uIPManagement.c b/Projects/Webserver/Lib/uIPManagement.c index dd9f15f42..f00119372 100644 --- a/Projects/Webserver/Lib/uIPManagement.c +++ b/Projects/Webserver/Lib/uIPManagement.c @@ -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 */ diff --git a/Projects/Webserver/Lib/uip/conf/apps-conf.h b/Projects/Webserver/Lib/uip/conf/apps-conf.h index 63a445ca9..88885a303 100644 --- a/Projects/Webserver/Lib/uip/conf/apps-conf.h +++ b/Projects/Webserver/Lib/uip/conf/apps-conf.h @@ -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 diff --git a/Projects/Webserver/USBHostMode.c b/Projects/Webserver/USBHostMode.c index 14f33e07c..b8e2dcee7 100644 --- a/Projects/Webserver/USBHostMode.c +++ b/Projects/Webserver/USBHostMode.c @@ -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, -- cgit v1.2.3