Better HTTP GET parsing in the Webserver demo, add application polling.
authorDean Camera <dean@fourwalledcubicle.com>
Sun, 31 Jan 2010 04:23:55 +0000 (04:23 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Sun, 31 Jan 2010 04:23:55 +0000 (04:23 +0000)
Projects/Benito/Benito.h
Projects/Webserver/Lib/HTTPServerApp.c
Projects/Webserver/Lib/HTTPServerApp.h
Projects/Webserver/Lib/uIPManagement.c
Projects/Webserver/Lib/uip/conf/apps-conf.h
Projects/Webserver/Webserver.c
Projects/Webserver/Webserver.txt

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