mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-06-13 12:24:18 +00:00
Add TCP retransmission support to the HTTP webserver in the Webserver project, so that lost segments are retransmitted as needed.
This commit is contained in:
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 */
|
/* Check if the open file needs to be closed */
|
||||||
f_close(&AppState->FileToSend);
|
if (AppState->FileOpen)
|
||||||
|
{
|
||||||
AppState->CurrentState = WEBSERVER_STATE_Closed;
|
f_close(&AppState->FileHandle);
|
||||||
|
AppState->FileOpen = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (uip_closed())
|
|
||||||
{
|
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)
|
||||||
|
{
|
||||||
|
/* If we are not re-transmitting a lost segment, advance file position */
|
||||||
|
if (!(uip_rexmit()))
|
||||||
|
AppState->CurrentFilePos += AppDataSize;
|
||||||
|
|
||||||
uip_send(AppData, 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…
Reference in New Issue
Block a user