diff options
Diffstat (limited to 'lib/lufa/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c')
| -rw-r--r-- | lib/lufa/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/lib/lufa/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c b/lib/lufa/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c new file mode 100644 index 000000000..e0d9e3647 --- /dev/null +++ b/lib/lufa/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c | |||
| @@ -0,0 +1,203 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
| 11 | |||
| 12 | Permission to use, copy, modify, distribute, and sell this | ||
| 13 | software and its documentation for any purpose is hereby granted | ||
| 14 | without fee, provided that the above copyright notice appear in | ||
| 15 | all copies and that both that the copyright notice and this | ||
| 16 | permission notice and warranty disclaimer appear in supporting | ||
| 17 | documentation, and that the name of the author not be used in | ||
| 18 | advertising or publicity pertaining to distribution of the | ||
| 19 | software without specific, written prior permission. | ||
| 20 | |||
| 21 | The author disclaims all warranties with regard to this | ||
| 22 | software, including all implied warranties of merchantability | ||
| 23 | and fitness. In no event shall the author be liable for any | ||
| 24 | special, indirect or consequential damages or any damages | ||
| 25 | whatsoever resulting from loss of use, data or profits, whether | ||
| 26 | in an action of contract, negligence or other tortious action, | ||
| 27 | arising out of or in connection with the use or performance of | ||
| 28 | this software. | ||
| 29 | */ | ||
| 30 | |||
| 31 | /** \file | ||
| 32 | * | ||
| 33 | * Simple webserver application for demonstrating the RNDIS demo and TCP/IP stack. This | ||
| 34 | * application will serve up a static HTTP webpage when requested by the host. | ||
| 35 | */ | ||
| 36 | |||
| 37 | #include "Webserver.h" | ||
| 38 | |||
| 39 | /** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the | ||
| 40 | * given location, and gives extra connection information. | ||
| 41 | */ | ||
| 42 | const char PROGMEM HTTP200Header[] = "HTTP/1.1 200 OK\r\n" | ||
| 43 | "Server: LUFA RNDIS\r\n" | ||
| 44 | "Content-type: text/html\r\n" | ||
| 45 | "Connection: close\r\n\r\n"; | ||
| 46 | |||
| 47 | /** HTTP server response header, for transmission before a resource not found error. This indicates to the host that the given | ||
| 48 | * given URL is invalid, and gives extra error information. | ||
| 49 | */ | ||
| 50 | const char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n" | ||
| 51 | "Server: LUFA RNDIS\r\n" | ||
| 52 | "Connection: close\r\n\r\n"; | ||
| 53 | |||
| 54 | /** 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 | ||
| 55 | * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run. | ||
| 56 | */ | ||
| 57 | const char PROGMEM HTTPPage[] = | ||
| 58 | "<html>" | ||
| 59 | " <head>" | ||
| 60 | " <title>" | ||
| 61 | " LUFA Webserver Demo" | ||
| 62 | " </title>" | ||
| 63 | " </head>" | ||
| 64 | " <body>" | ||
| 65 | " <h1>Hello from your USB AVR!</h1>" | ||
| 66 | " <p>" | ||
| 67 | " 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." | ||
| 68 | " <br /><br />" | ||
| 69 | " <small>Project Information: <a href=\"http://www.lufa-lib.org\">http://www.lufa-lib.org</a>.</small>" | ||
| 70 | " <hr />" | ||
| 71 | " <i>LUFA Version: </i>" LUFA_VERSION_STRING | ||
| 72 | " </p>" | ||
| 73 | " </body>" | ||
| 74 | "</html>"; | ||
| 75 | |||
| 76 | |||
| 77 | /** Initializes the Webserver application, opening the appropriate HTTP port in the TCP handler and registering the application | ||
| 78 | * callback routine for packets sent to the HTTP protocol port. | ||
| 79 | */ | ||
| 80 | void Webserver_Init(void) | ||
| 81 | { | ||
| 82 | /* Open the HTTP port in the TCP protocol so that HTTP connections to the device can be established */ | ||
| 83 | TCP_SetPortState(TCP_PORT_HTTP, TCP_Port_Open, Webserver_ApplicationCallback); | ||
| 84 | } | ||
| 85 | |||
| 86 | /** Indicates if a given request equals the given HTTP command. | ||
| 87 | * | ||
| 88 | * \param[in] RequestHeader HTTP request made by the host | ||
| 89 | * \param[in] Command HTTP command to compare the request to | ||
| 90 | * | ||
| 91 | * \return Boolean \c true if the command matches the request, \c false otherwise | ||
| 92 | */ | ||
| 93 | static bool IsHTTPCommand(uint8_t* RequestHeader, | ||
| 94 | char* Command) | ||
| 95 | { | ||
| 96 | /* Returns true if the non null terminated string in RequestHeader matches the null terminated string Command */ | ||
| 97 | return (strncmp((char*)RequestHeader, Command, strlen(Command)) == 0); | ||
| 98 | } | ||
| 99 | |||
| 100 | /** Application callback routine, executed each time the TCP processing task runs. This callback determines what request | ||
| 101 | * has been made (if any), and serves up appropriate responses. | ||
| 102 | * | ||
| 103 | * \param[in] ConnectionState Pointer to a TCP Connection State structure giving connection information | ||
| 104 | * \param[in,out] Buffer Pointer to the application's send/receive packet buffer | ||
| 105 | */ | ||
| 106 | void Webserver_ApplicationCallback(TCP_ConnectionState_t* const ConnectionState, | ||
| 107 | TCP_ConnectionBuffer_t* const Buffer) | ||
| 108 | { | ||
| 109 | char* BufferDataStr = (char*)Buffer->Data; | ||
| 110 | static uint8_t PageBlock = 0; | ||
| 111 | |||
| 112 | /* Check to see if a packet has been received on the HTTP port from a remote host */ | ||
| 113 | if (TCP_APP_HAS_RECEIVED_PACKET(Buffer)) | ||
| 114 | { | ||
| 115 | if (IsHTTPCommand(Buffer->Data, "GET")) | ||
| 116 | { | ||
| 117 | if (IsHTTPCommand(Buffer->Data, "GET / ")) | ||
| 118 | { | ||
| 119 | PageBlock = 0; | ||
| 120 | |||
| 121 | /* Copy the HTTP 200 response header into the packet buffer */ | ||
| 122 | strcpy_P(BufferDataStr, HTTP200Header); | ||
| 123 | |||
| 124 | /* Send the buffer contents to the host */ | ||
| 125 | TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); | ||
| 126 | |||
| 127 | /* Lock the buffer to Device->Host transmissions only while we send the page contents */ | ||
| 128 | TCP_APP_CAPTURE_BUFFER(Buffer); | ||
| 129 | } | ||
| 130 | else | ||
| 131 | { | ||
| 132 | /* Copy the HTTP 404 response header into the packet buffer */ | ||
| 133 | strcpy_P(BufferDataStr, HTTP404Header); | ||
| 134 | |||
| 135 | /* Send the buffer contents to the host */ | ||
| 136 | TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); | ||
| 137 | |||
| 138 | /* All data sent, close the connection */ | ||
| 139 | TCP_APP_CLOSECONNECTION(ConnectionState); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | else if (IsHTTPCommand(Buffer->Data, "HEAD")) | ||
| 143 | { | ||
| 144 | if (IsHTTPCommand(Buffer->Data, "HEAD / ")) | ||
| 145 | { | ||
| 146 | /* Copy the HTTP response header into the packet buffer */ | ||
| 147 | strcpy_P(BufferDataStr, HTTP200Header); | ||
| 148 | |||
| 149 | /* Send the buffer contents to the host */ | ||
| 150 | TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); | ||
| 151 | } | ||
| 152 | else | ||
| 153 | { | ||
| 154 | /* Copy the HTTP response header into the packet buffer */ | ||
| 155 | strcpy_P(BufferDataStr, HTTP404Header); | ||
| 156 | |||
| 157 | /* Send the buffer contents to the host */ | ||
| 158 | TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); | ||
| 159 | } | ||
| 160 | |||
| 161 | /* All data sent, close the connection */ | ||
| 162 | TCP_APP_CLOSECONNECTION(ConnectionState); | ||
| 163 | } | ||
| 164 | else if (IsHTTPCommand(Buffer->Data, "TRACE")) | ||
| 165 | { | ||
| 166 | /* Echo the host's query back to the host */ | ||
| 167 | TCP_APP_SEND_BUFFER(Buffer, Buffer->Length); | ||
| 168 | |||
| 169 | /* All data sent, close the connection */ | ||
| 170 | TCP_APP_CLOSECONNECTION(ConnectionState); | ||
| 171 | } | ||
| 172 | else | ||
| 173 | { | ||
| 174 | /* Unknown request, just clear the buffer (drop the packet) */ | ||
| 175 | TCP_APP_CLEAR_BUFFER(Buffer); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | else if (TCP_APP_HAVE_CAPTURED_BUFFER(Buffer)) | ||
| 179 | { | ||
| 180 | uint16_t RemLength = strlen_P(&HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE]); | ||
| 181 | uint16_t Length; | ||
| 182 | |||
| 183 | /* Determine the length of the loaded block */ | ||
| 184 | Length = MIN(RemLength, HTTP_REPLY_BLOCK_SIZE); | ||
| 185 | |||
| 186 | /* Copy the next buffer sized block of the page to the packet buffer */ | ||
| 187 | strncpy_P(BufferDataStr, &HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE], Length); | ||
| 188 | |||
| 189 | /* Send the buffer contents to the host */ | ||
| 190 | TCP_APP_SEND_BUFFER(Buffer, Length); | ||
| 191 | |||
| 192 | /* Check to see if the entire page has been sent */ | ||
| 193 | if (PageBlock++ == (sizeof(HTTPPage) / HTTP_REPLY_BLOCK_SIZE)) | ||
| 194 | { | ||
| 195 | /* Unlock the buffer so that the host can fill it with future packets */ | ||
| 196 | TCP_APP_RELEASE_BUFFER(Buffer); | ||
| 197 | |||
| 198 | /* Close the connection to the host */ | ||
| 199 | TCP_APP_CLOSECONNECTION(ConnectionState); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
