+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2010.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, distribute, and sell this \r
+ software and its documentation for any purpose is hereby granted\r
+ without fee, provided that the above copyright notice appear in \r
+ all copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting \r
+ documentation, and that the name of the author not be used in \r
+ advertising or publicity pertaining to distribution of the \r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Simple HTTP Webserver Application. When connected to the uIP stack,\r
+ * this will serve out files to HTTP clients.\r
+ */\r
+ \r
+#include "WebserverApp.h"\r
+\r
+/** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the\r
+ * given location, and gives extra connection information.\r
+ */\r
+char PROGMEM HTTP200Header[] = "HTTP/1.1 200 OK\r\n"\r
+ "Server: LUFA RNDIS\r\n"\r
+ "Content-type: text/html\r\n"\r
+ "Connection: close\r\n\r\n";\r
+\r
+/** HTTP server response header, for transmission before a resource not found error. This indicates to the host that the given\r
+ * given URL is invalid, and gives extra error information.\r
+ */\r
+char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n"\r
+ "Server: LUFA RNDIS\r\n"\r
+ "Connection: close\r\n\r\n";\r
+\r
+/****************************************************************************************/\r
+/** HTTP page to serve to the host when a HTTP request is made. This page is too long for a single response, thus it is automatically\r
+ * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run.\r
+ */\r
+char PROGMEM HTTPPage[] = \r
+ "<html>"\r
+ " <head>"\r
+ " <title>"\r
+ " LUFA Webserver Demo"\r
+ " </title>"\r
+ " </head>"\r
+ " <body>"\r
+ " <h1>Hello from your USB AVR!</h1>"\r
+ " <p>"\r
+ " Hello! Welcome to the LUFA RNDIS Demo Webserver test page, running on your USB AVR via the LUFA library. This demonstrates the HTTP webserver, TCP/IP stack and RNDIS demo all running atop the LUFA USB stack."\r
+ " <br /><br />"\r
+ " <small>Project Information: <a href=\"http://www.fourwalledcubicle.com/LUFA.php\">http://www.fourwalledcubicle.com/LUFA.php</a>.</small>"\r
+ " <hr />"\r
+ " <i>LUFA Version: </i>" LUFA_VERSION_STRING\r
+ " </p>"\r
+ " </body>"\r
+ "</html>";\r
+\r
+void WebserverAppCallback(void)\r
+{\r
+ char* AppDataPtr = (char*)uip_appdata;\r
+ uint16_t AppDataSize = 0;\r
+\r
+ if (uip_closed() || uip_aborted() || uip_timedout())\r
+ {\r
+ /* Terminated or completed connection - don't send any new data */\r
+ return;\r
+ }\r
+ else if (uip_connected())\r
+ {\r
+ /* New connection - initialize connection state and data pointer to the appropriate HTTP header */\r
+ uip_conn->appstate.SendPos = HTTP200Header;\r
+ uip_conn->appstate.CurrentState = WEBSERVER_STATE_SendHeaders;\r
+ }\r
+\r
+ /* Calculate the maximum segment size and remaining data size */\r
+ uint16_t BytesRemaining = strlen_P(uip_conn->appstate.SendPos);\r
+ uint16_t MaxSegSize = uip_mss();\r
+\r
+ /* No more bytes remaining in the current data being sent - progress to next data chunk or\r
+ * terminate the connection once all chunks are sent */\r
+ if (!(BytesRemaining))\r
+ {\r
+ /* Check which data chunk we are currently sending (header or data) */\r
+ if (uip_conn->appstate.CurrentState == WEBSERVER_STATE_SendHeaders)\r
+ {\r
+ uip_conn->appstate.SendPos = HTTPPage;\r
+ uip_conn->appstate.CurrentState = WEBSERVER_STATE_SendData; \r
+ }\r
+ else if (uip_conn->appstate.CurrentState == WEBSERVER_STATE_SendData)\r
+ {\r
+ uip_close();\r
+ uip_conn->appstate.CurrentState = WEBSERVER_STATE_Closed;\r
+ }\r
+ \r
+ return;\r
+ }\r
+ else if (BytesRemaining > MaxSegSize)\r
+ {\r
+ AppDataSize = MaxSegSize;\r
+ }\r
+ else\r
+ {\r
+ AppDataSize = BytesRemaining;\r
+ }\r
+\r
+ /* Copy over the next data segment to the application buffer, advance send position pointer */\r
+ strncpy_P(uip_appdata, uip_conn->appstate.SendPos, AppDataSize);\r
+ uip_conn->appstate.SendPos += AppDataSize;\r
+\r
+ /* Send the data to the requesting host */\r
+ uip_send(AppDataPtr, AppDataSize);\r
+}\r