forked from mfulz_github/qmk_firmware
Better HTTP GET parsing in the Webserver demo, add application polling.
This commit is contained in:
parent
e8b8ed2bad
commit
97f7cd947b
|
@ -40,7 +40,6 @@
|
|||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/power.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
#include "Lib/RingBuff.h"
|
||||
|
|
|
@ -112,9 +112,10 @@ void WebserverApp_Callback(void)
|
|||
}
|
||||
else if (uip_connected())
|
||||
{
|
||||
/* New connection - initialize connection state and data pointer to the appropriate HTTP header */
|
||||
/* New connection - initialize connection state values */
|
||||
AppState->PrevState = WEBSERVER_STATE_OpenRequestedFile;
|
||||
AppState->CurrentState = WEBSERVER_STATE_OpenRequestedFile;
|
||||
AppState->FileOpen = false;
|
||||
}
|
||||
else if (uip_rexmit())
|
||||
{
|
||||
|
@ -128,31 +129,25 @@ void WebserverApp_Callback(void)
|
|||
/* Wait for the packet containing the request header */
|
||||
if (uip_newdata())
|
||||
{
|
||||
char* RequestToken = strtok(AppData, " ");
|
||||
|
||||
/* Must be a GET request, abort otherwise */
|
||||
if (strncmp(AppData, "GET ", (sizeof("GET ") - 1)) != 0)
|
||||
if (strcmp(RequestToken, "GET") != 0)
|
||||
{
|
||||
uip_abort();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy over the requested filename from the GET request as all-lowercase */
|
||||
for (uint8_t i = 0; i < (sizeof(AppState->FileName) - 1); i++)
|
||||
{
|
||||
AppState->FileName[i] = tolower(AppData[sizeof("GET ") + i]);
|
||||
|
||||
if (AppState->FileName[i] == ' ')
|
||||
{
|
||||
AppState->FileName[i] = 0x00;
|
||||
break;
|
||||
}
|
||||
}
|
||||
char* RequestedFileName = strtok(NULL, " ");
|
||||
|
||||
/* Ensure requested filename is null-terminated */
|
||||
AppState->FileName[(sizeof(AppState->FileName) - 1)] = 0x00;
|
||||
|
||||
/* If no filename specified, assume the default of index.htm */
|
||||
if (AppState->FileName[0] == 0x00)
|
||||
/* If the requested filename has more that just the leading '/' path in it, copy it over */
|
||||
if (strlen(RequestedFileName) > 1)
|
||||
strncpy(AppState->FileName, &RequestedFileName[1], (sizeof(AppState->FileName) - 1));
|
||||
else
|
||||
strcpy(AppState->FileName, "index.htm");
|
||||
|
||||
/* Ensure filename is null-terminated */
|
||||
AppState->FileName[(sizeof(AppState->FileName) - 1)] = 0x00;
|
||||
|
||||
/* Try to open the file from the Dataflash disk */
|
||||
AppState->FileOpen = (f_open(&AppState->FileHandle, AppState->FileName, FA_OPEN_EXISTING | FA_READ) == FR_OK);
|
||||
|
@ -176,8 +171,6 @@ void WebserverApp_Callback(void)
|
|||
strncpy_P(AppData, HTTP404Header, AppDataSize);
|
||||
}
|
||||
|
||||
uip_send(AppData, AppDataSize);
|
||||
|
||||
AppState->PrevState = WEBSERVER_STATE_SendResponseHeader;
|
||||
AppState->CurrentState = WEBSERVER_STATE_SendMIMETypeHeader;
|
||||
break;
|
||||
|
@ -213,8 +206,6 @@ void WebserverApp_Callback(void)
|
|||
/* Add the end-of line terminator and end-of-headers terminator after the MIME type */
|
||||
strncpy(&AppData[AppDataSize], "\r\n\r\n", sizeof("\r\n\r\n"));
|
||||
AppDataSize += (sizeof("\r\n\r\n") - 1);
|
||||
|
||||
uip_send(AppData, AppDataSize);
|
||||
}
|
||||
|
||||
AppState->PrevState = WEBSERVER_STATE_SendMIMETypeHeader;
|
||||
|
@ -234,25 +225,26 @@ void WebserverApp_Callback(void)
|
|||
|
||||
uint16_t MaxSegSize = uip_mss();
|
||||
|
||||
/* Return file pointer to the last ACKed position if retransmitting */
|
||||
/* Return file pointer to the last ACKed position */
|
||||
f_lseek(&AppState->FileHandle, AppState->CurrentFilePos);
|
||||
|
||||
/* Read the next chunk of data from the open file */
|
||||
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_acked() && !(uip_rexmit()))
|
||||
{
|
||||
/* If we are not re-transmitting a lost segment, advance file position */
|
||||
if (!(uip_rexmit()))
|
||||
AppState->CurrentFilePos += AppDataSize;
|
||||
|
||||
uip_send(AppData, AppDataSize);
|
||||
AppState->FileOpen = (AppDataSize > 0);
|
||||
AppState->CurrentFilePos += AppDataSize;
|
||||
}
|
||||
|
||||
/* Stay in the SendData state if retransmission is required until all data sent */
|
||||
AppState->PrevState = WEBSERVER_STATE_SendData;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* If data has been loaded into the application buffer by the server, send it to the client */
|
||||
if (AppDataSize)
|
||||
uip_send(AppData, AppDataSize);
|
||||
}
|
||||
|
|
|
@ -39,9 +39,6 @@
|
|||
/* Includes: */
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <LUFA/Version.h>
|
||||
|
||||
#include <uip.h>
|
||||
#include <ff.h>
|
||||
|
|
|
@ -52,7 +52,7 @@ void uIPManagement_Init(void)
|
|||
{
|
||||
/* uIP Timing Initialization */
|
||||
clock_init();
|
||||
timer_set(&ConnectionTimer, CLOCK_SECOND / 100);
|
||||
timer_set(&ConnectionTimer, CLOCK_SECOND / 2);
|
||||
timer_set(&ARPTimer, CLOCK_SECOND * 10);
|
||||
|
||||
/* uIP Stack Initialization */
|
||||
|
@ -97,13 +97,13 @@ static void uIPManagement_ProcessIncommingPacket(void)
|
|||
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
|
||||
|
||||
/* Read the incomming packet straight into the UIP packet buffer */
|
||||
RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface, &uip_buf[0], &uip_len);
|
||||
RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface, uip_buf, &uip_len);
|
||||
|
||||
if (uip_len > 0)
|
||||
{
|
||||
bool PacketHandled = true;
|
||||
|
||||
struct uip_eth_hdr* EthernetHeader = (struct uip_eth_hdr*)&uip_buf[0];
|
||||
struct uip_eth_hdr* EthernetHeader = (struct uip_eth_hdr*)uip_buf;
|
||||
if (EthernetHeader->type == HTONS(UIP_ETHTYPE_IP))
|
||||
{
|
||||
/* Filter packet by MAC destination */
|
||||
|
@ -128,7 +128,7 @@ static void uIPManagement_ProcessIncommingPacket(void)
|
|||
|
||||
/* If a response was generated, send it */
|
||||
if ((uip_len > 0) && PacketHandled)
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, &uip_buf[0], uip_len);
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
}
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY);
|
||||
|
@ -138,7 +138,22 @@ static void uIPManagement_ProcessIncommingPacket(void)
|
|||
/** Manages the currently open network connections, including TCP and (if enabled) UDP. */
|
||||
static void uIPManagement_ManageConnections(void)
|
||||
{
|
||||
/* Manage open connections */
|
||||
/* Poll TCP connections for more data to send back to the host */
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
uip_poll_conn(&uip_conns[i]);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Manage open connections for timeouts */
|
||||
if (timer_expired(&ConnectionTimer))
|
||||
{
|
||||
timer_reset(&ConnectionTimer);
|
||||
|
@ -156,7 +171,7 @@ static void uIPManagement_ManageConnections(void)
|
|||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, &uip_buf[0], uip_len);
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +187,7 @@ static void uIPManagement_ManageConnections(void)
|
|||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, &uip_buf[0], uip_len);
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
uint8_t CurrentState;
|
||||
|
||||
FIL FileHandle;
|
||||
char FileName[13];
|
||||
char FileName[50];
|
||||
bool FileOpen;
|
||||
uint32_t CurrentFilePos;
|
||||
} uip_tcp_appstate_t;
|
||||
|
|
|
@ -47,8 +47,10 @@ int main(void)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
USBDeviceMode_USBTask();
|
||||
USBHostMode_USBTask();
|
||||
if (USB_CurrentMode == USB_MODE_HOST)
|
||||
USBHostMode_USBTask();
|
||||
else
|
||||
USBDeviceMode_USBTask();
|
||||
|
||||
USB_USBTask();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
*
|
||||
* To use this project, plug the USB AVR into a computer, so that it enumerates as a standard Mass Storage device. Load
|
||||
* HTML files onto the disk, so that they can be served out to clients -- the default file to serve should be called
|
||||
* <i>index.htm</i>. Filenames must be in 8.3 format for them to be retrieved correctly by the webserver.
|
||||
* <i>index.htm</i>. Filenames must be in 8.3 format for them to be retrieved correctly by the webserver, and the total
|
||||
* requested file path must be equal to or less than 50 characters.
|
||||
*
|
||||
* When attached to a RNDIS class device, such as a USB (desktop) modem, the system will enumerate the device, set the
|
||||
* appropriate parameters needed for connectivity and begin listening for new HTTP connections on port 80. The device IP,
|
||||
|
|
Loading…
Reference in New Issue