Network Services
Fork of W5500Interface_K22F by
HTTPD/HTTPD_req.cpp@15:14382459c8b7, 2017-06-15 (annotated)
- Committer:
- dgriffin65
- Date:
- Thu Jun 15 20:29:03 2017 +0000
- Revision:
- 15:14382459c8b7
Converted to a single library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dgriffin65 | 15:14382459c8b7 | 1 | /* Copyright (C) 2013 Hiroshi Suga, MIT License |
dgriffin65 | 15:14382459c8b7 | 2 | * |
dgriffin65 | 15:14382459c8b7 | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
dgriffin65 | 15:14382459c8b7 | 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
dgriffin65 | 15:14382459c8b7 | 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
dgriffin65 | 15:14382459c8b7 | 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
dgriffin65 | 15:14382459c8b7 | 7 | * furnished to do so, subject to the following conditions: |
dgriffin65 | 15:14382459c8b7 | 8 | * |
dgriffin65 | 15:14382459c8b7 | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
dgriffin65 | 15:14382459c8b7 | 10 | * substantial portions of the Software. |
dgriffin65 | 15:14382459c8b7 | 11 | * |
dgriffin65 | 15:14382459c8b7 | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
dgriffin65 | 15:14382459c8b7 | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
dgriffin65 | 15:14382459c8b7 | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
dgriffin65 | 15:14382459c8b7 | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
dgriffin65 | 15:14382459c8b7 | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
dgriffin65 | 15:14382459c8b7 | 17 | */ |
dgriffin65 | 15:14382459c8b7 | 18 | |
dgriffin65 | 15:14382459c8b7 | 19 | #include "HTTPD.h" |
dgriffin65 | 15:14382459c8b7 | 20 | |
dgriffin65 | 15:14382459c8b7 | 21 | |
dgriffin65 | 15:14382459c8b7 | 22 | int HTTPD::httpdFile (int id, char *dir) { |
dgriffin65 | 15:14382459c8b7 | 23 | FILE *fp; |
dgriffin65 | 15:14382459c8b7 | 24 | int i, len; |
dgriffin65 | 15:14382459c8b7 | 25 | char buf[HTTPD_BUF_SIZE]; |
dgriffin65 | 15:14382459c8b7 | 26 | char file[HTTPD_CMD_SIZE]; |
dgriffin65 | 15:14382459c8b7 | 27 | |
dgriffin65 | 15:14382459c8b7 | 28 | INFO("httpdFile %d %s", id, dir); |
dgriffin65 | 15:14382459c8b7 | 29 | |
dgriffin65 | 15:14382459c8b7 | 30 | strcpy(file, dir); |
dgriffin65 | 15:14382459c8b7 | 31 | strcat(file, _state[id].filename); |
dgriffin65 | 15:14382459c8b7 | 32 | if (file[strlen(file) - 1] == '/') { |
dgriffin65 | 15:14382459c8b7 | 33 | strcat(file, "index.html"); |
dgriffin65 | 15:14382459c8b7 | 34 | } |
dgriffin65 | 15:14382459c8b7 | 35 | DBG("file: %s\r\n", file); |
dgriffin65 | 15:14382459c8b7 | 36 | |
dgriffin65 | 15:14382459c8b7 | 37 | fp = fopen(file, "r"); |
dgriffin65 | 15:14382459c8b7 | 38 | if (fp) { |
dgriffin65 | 15:14382459c8b7 | 39 | strcpy(buf, "HTTP/1.1 200 OK\r\n"); |
dgriffin65 | 15:14382459c8b7 | 40 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 41 | { |
dgriffin65 | 15:14382459c8b7 | 42 | // file size |
dgriffin65 | 15:14382459c8b7 | 43 | i = ftell(fp); |
dgriffin65 | 15:14382459c8b7 | 44 | fseek(fp, 0, SEEK_END); |
dgriffin65 | 15:14382459c8b7 | 45 | len = ftell(fp); |
dgriffin65 | 15:14382459c8b7 | 46 | fseek(fp, i, SEEK_SET); |
dgriffin65 | 15:14382459c8b7 | 47 | } |
dgriffin65 | 15:14382459c8b7 | 48 | |
dgriffin65 | 15:14382459c8b7 | 49 | strcpy(buf, "Server: GSwifi httpd\r\n"); |
dgriffin65 | 15:14382459c8b7 | 50 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 51 | if (_state[id].keepalive) { |
dgriffin65 | 15:14382459c8b7 | 52 | strcpy(buf, "Connection: Keep-Alive\r\n"); |
dgriffin65 | 15:14382459c8b7 | 53 | } else { |
dgriffin65 | 15:14382459c8b7 | 54 | strcpy(buf, "Connection: close\r\n"); |
dgriffin65 | 15:14382459c8b7 | 55 | } |
dgriffin65 | 15:14382459c8b7 | 56 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 57 | sprintf(buf, "Content-Type: %s\r\n", mimetype(file)); |
dgriffin65 | 15:14382459c8b7 | 58 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 59 | sprintf(buf, "Content-Length: %d\r\n\r\n", len); |
dgriffin65 | 15:14382459c8b7 | 60 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 61 | |
dgriffin65 | 15:14382459c8b7 | 62 | for (;;) { |
dgriffin65 | 15:14382459c8b7 | 63 | i = fread(buf, sizeof(char), sizeof(buf), fp); |
dgriffin65 | 15:14382459c8b7 | 64 | if (i <= 0) break; |
dgriffin65 | 15:14382459c8b7 | 65 | _state[id].client->send(buf, i); |
dgriffin65 | 15:14382459c8b7 | 66 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
dgriffin65 | 15:14382459c8b7 | 67 | if (feof(fp)) break; |
dgriffin65 | 15:14382459c8b7 | 68 | #endif |
dgriffin65 | 15:14382459c8b7 | 69 | } |
dgriffin65 | 15:14382459c8b7 | 70 | fclose(fp); |
dgriffin65 | 15:14382459c8b7 | 71 | return 0; |
dgriffin65 | 15:14382459c8b7 | 72 | } |
dgriffin65 | 15:14382459c8b7 | 73 | |
dgriffin65 | 15:14382459c8b7 | 74 | httpdError(id, 404); |
dgriffin65 | 15:14382459c8b7 | 75 | return -1; |
dgriffin65 | 15:14382459c8b7 | 76 | } |
dgriffin65 | 15:14382459c8b7 | 77 | |
dgriffin65 | 15:14382459c8b7 | 78 | void HTTPD::httpdError (int id, int err) { |
dgriffin65 | 15:14382459c8b7 | 79 | char buf[HTTPD_CMD_SIZE], msg[30]; |
dgriffin65 | 15:14382459c8b7 | 80 | |
dgriffin65 | 15:14382459c8b7 | 81 | switch (err) { |
dgriffin65 | 15:14382459c8b7 | 82 | case 400: |
dgriffin65 | 15:14382459c8b7 | 83 | strcpy(msg, "Bad Request"); |
dgriffin65 | 15:14382459c8b7 | 84 | break; |
dgriffin65 | 15:14382459c8b7 | 85 | case 403: |
dgriffin65 | 15:14382459c8b7 | 86 | strcpy(msg, "Forbidden"); |
dgriffin65 | 15:14382459c8b7 | 87 | break; |
dgriffin65 | 15:14382459c8b7 | 88 | case 404: |
dgriffin65 | 15:14382459c8b7 | 89 | strcpy(msg, "Not Found"); |
dgriffin65 | 15:14382459c8b7 | 90 | break; |
dgriffin65 | 15:14382459c8b7 | 91 | case 500: |
dgriffin65 | 15:14382459c8b7 | 92 | default: |
dgriffin65 | 15:14382459c8b7 | 93 | strcpy(msg, "Internal Server Error"); |
dgriffin65 | 15:14382459c8b7 | 94 | break; |
dgriffin65 | 15:14382459c8b7 | 95 | } |
dgriffin65 | 15:14382459c8b7 | 96 | DBG("httpd error: %d %d %s\r\n", id, err, msg); |
dgriffin65 | 15:14382459c8b7 | 97 | |
dgriffin65 | 15:14382459c8b7 | 98 | sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg); |
dgriffin65 | 15:14382459c8b7 | 99 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 100 | strcpy(buf, "Content-Type: text/html\r\n\r\n"); |
dgriffin65 | 15:14382459c8b7 | 101 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 102 | |
dgriffin65 | 15:14382459c8b7 | 103 | sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg); |
dgriffin65 | 15:14382459c8b7 | 104 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 105 | sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg); |
dgriffin65 | 15:14382459c8b7 | 106 | _state[id].client->send(buf, strlen(buf)); |
dgriffin65 | 15:14382459c8b7 | 107 | wait_ms(100); |
dgriffin65 | 15:14382459c8b7 | 108 | _state[id].client->close(); |
dgriffin65 | 15:14382459c8b7 | 109 | //WARN("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); |
dgriffin65 | 15:14382459c8b7 | 110 | //WARN("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err); |
dgriffin65 | 15:14382459c8b7 | 111 | } |
dgriffin65 | 15:14382459c8b7 | 112 | |
dgriffin65 | 15:14382459c8b7 | 113 | void HTTPD::recvData (int id, char c) { |
dgriffin65 | 15:14382459c8b7 | 114 | |
dgriffin65 | 15:14382459c8b7 | 115 | switch (_state[id].mode) { |
dgriffin65 | 15:14382459c8b7 | 116 | case MODE_REQUEST: |
dgriffin65 | 15:14382459c8b7 | 117 | if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { |
dgriffin65 | 15:14382459c8b7 | 118 | _state[id].buf->flush(); |
dgriffin65 | 15:14382459c8b7 | 119 | _state[id].buf->queue(c); |
dgriffin65 | 15:14382459c8b7 | 120 | _state[id].mode = MODE_REQSTR; |
dgriffin65 | 15:14382459c8b7 | 121 | } else { |
dgriffin65 | 15:14382459c8b7 | 122 | _state[id].buf->flush(); |
dgriffin65 | 15:14382459c8b7 | 123 | } |
dgriffin65 | 15:14382459c8b7 | 124 | break; |
dgriffin65 | 15:14382459c8b7 | 125 | case MODE_REQSTR: |
dgriffin65 | 15:14382459c8b7 | 126 | switch (c) { |
dgriffin65 | 15:14382459c8b7 | 127 | case 0: |
dgriffin65 | 15:14382459c8b7 | 128 | break; |
dgriffin65 | 15:14382459c8b7 | 129 | case 0x0a: // LF |
dgriffin65 | 15:14382459c8b7 | 130 | case 0x0d: // CR |
dgriffin65 | 15:14382459c8b7 | 131 | if (parseRequest(id)) { |
dgriffin65 | 15:14382459c8b7 | 132 | _state[id].mode = MODE_REQSTR; |
dgriffin65 | 15:14382459c8b7 | 133 | } else { |
dgriffin65 | 15:14382459c8b7 | 134 | _state[id].mode = MODE_HEADER; |
dgriffin65 | 15:14382459c8b7 | 135 | } |
dgriffin65 | 15:14382459c8b7 | 136 | _state[id].enter = 0; |
dgriffin65 | 15:14382459c8b7 | 137 | break; |
dgriffin65 | 15:14382459c8b7 | 138 | default: |
dgriffin65 | 15:14382459c8b7 | 139 | _state[id].buf->queue(c); |
dgriffin65 | 15:14382459c8b7 | 140 | break; |
dgriffin65 | 15:14382459c8b7 | 141 | } |
dgriffin65 | 15:14382459c8b7 | 142 | break; |
dgriffin65 | 15:14382459c8b7 | 143 | case MODE_HEADER: |
dgriffin65 | 15:14382459c8b7 | 144 | switch (c) { |
dgriffin65 | 15:14382459c8b7 | 145 | case 0: |
dgriffin65 | 15:14382459c8b7 | 146 | break; |
dgriffin65 | 15:14382459c8b7 | 147 | case 0x0a: // LF |
dgriffin65 | 15:14382459c8b7 | 148 | case 0x0d: // CR |
dgriffin65 | 15:14382459c8b7 | 149 | if (_state[id].buf->available() == 0) { |
dgriffin65 | 15:14382459c8b7 | 150 | if ((_state[id].enter == 0x0d && c == 0x0a) || (_state[id].enter == 0x0a && c == 0x0a)) { |
dgriffin65 | 15:14382459c8b7 | 151 | _state[id].buf->flush(); |
dgriffin65 | 15:14382459c8b7 | 152 | if (_state[id].websocket) { |
dgriffin65 | 15:14382459c8b7 | 153 | INFO("MODE_WEBSOCKET"); |
dgriffin65 | 15:14382459c8b7 | 154 | acceptWebsocket(id); |
dgriffin65 | 15:14382459c8b7 | 155 | _state[id].mode = MODE_WEBSOCKET; |
dgriffin65 | 15:14382459c8b7 | 156 | } else |
dgriffin65 | 15:14382459c8b7 | 157 | if (_state[id].length) { |
dgriffin65 | 15:14382459c8b7 | 158 | INFO("MODE_BODY"); |
dgriffin65 | 15:14382459c8b7 | 159 | _state[id].mode = MODE_BODY; |
dgriffin65 | 15:14382459c8b7 | 160 | } else { |
dgriffin65 | 15:14382459c8b7 | 161 | INFO("MODE_ENTER"); |
dgriffin65 | 15:14382459c8b7 | 162 | _state[id].mode = MODE_ENTER; |
dgriffin65 | 15:14382459c8b7 | 163 | } |
dgriffin65 | 15:14382459c8b7 | 164 | } |
dgriffin65 | 15:14382459c8b7 | 165 | _state[id].enter = c; |
dgriffin65 | 15:14382459c8b7 | 166 | _state[id].buf->flush(); |
dgriffin65 | 15:14382459c8b7 | 167 | break; |
dgriffin65 | 15:14382459c8b7 | 168 | } |
dgriffin65 | 15:14382459c8b7 | 169 | |
dgriffin65 | 15:14382459c8b7 | 170 | parseHeader(id); |
dgriffin65 | 15:14382459c8b7 | 171 | _state[id].enter = 0; |
dgriffin65 | 15:14382459c8b7 | 172 | break; |
dgriffin65 | 15:14382459c8b7 | 173 | default: |
dgriffin65 | 15:14382459c8b7 | 174 | _state[id].buf->queue(c); |
dgriffin65 | 15:14382459c8b7 | 175 | _state[id].enter = 0; |
dgriffin65 | 15:14382459c8b7 | 176 | break; |
dgriffin65 | 15:14382459c8b7 | 177 | } |
dgriffin65 | 15:14382459c8b7 | 178 | break; |
dgriffin65 | 15:14382459c8b7 | 179 | case MODE_BODY: |
dgriffin65 | 15:14382459c8b7 | 180 | _state[id].buf->queue(c); |
dgriffin65 | 15:14382459c8b7 | 181 | if (_state[id].buf->available() >= _state[id].length) { |
dgriffin65 | 15:14382459c8b7 | 182 | _state[id].mode = MODE_ENTER; |
dgriffin65 | 15:14382459c8b7 | 183 | } |
dgriffin65 | 15:14382459c8b7 | 184 | break; |
dgriffin65 | 15:14382459c8b7 | 185 | case MODE_WEBSOCKET: |
dgriffin65 | 15:14382459c8b7 | 186 | case MODE_WEBSOCKET_MASK: |
dgriffin65 | 15:14382459c8b7 | 187 | case MODE_WEBSOCKET_BODY: |
dgriffin65 | 15:14382459c8b7 | 188 | recvWS(id, c); |
dgriffin65 | 15:14382459c8b7 | 189 | break; |
dgriffin65 | 15:14382459c8b7 | 190 | } |
dgriffin65 | 15:14382459c8b7 | 191 | |
dgriffin65 | 15:14382459c8b7 | 192 | if (_state[id].mode == MODE_ENTER) { |
dgriffin65 | 15:14382459c8b7 | 193 | int i = getHandler(_state[id].uri); |
dgriffin65 | 15:14382459c8b7 | 194 | printf("handler = %d, uri = %s\r\n", i, _state[id].uri); |
dgriffin65 | 15:14382459c8b7 | 195 | if (i >= 0) { |
dgriffin65 | 15:14382459c8b7 | 196 | if (_handler[i].dir) { |
dgriffin65 | 15:14382459c8b7 | 197 | // file |
dgriffin65 | 15:14382459c8b7 | 198 | httpdFile(id, _handler[i].dir); |
dgriffin65 | 15:14382459c8b7 | 199 | } else if (_handler[i].funcCgi) { |
dgriffin65 | 15:14382459c8b7 | 200 | // cgi |
dgriffin65 | 15:14382459c8b7 | 201 | _handler[i].funcCgi(id); |
dgriffin65 | 15:14382459c8b7 | 202 | _state[id].keepalive = 0; |
dgriffin65 | 15:14382459c8b7 | 203 | } else { |
dgriffin65 | 15:14382459c8b7 | 204 | httpdError(id, 403); |
dgriffin65 | 15:14382459c8b7 | 205 | } |
dgriffin65 | 15:14382459c8b7 | 206 | } else { |
dgriffin65 | 15:14382459c8b7 | 207 | httpdError(id, 404); |
dgriffin65 | 15:14382459c8b7 | 208 | } |
dgriffin65 | 15:14382459c8b7 | 209 | |
dgriffin65 | 15:14382459c8b7 | 210 | if (_state[id].keepalive) { |
dgriffin65 | 15:14382459c8b7 | 211 | DBG("keepalive %d", _state[id].keepalive); |
dgriffin65 | 15:14382459c8b7 | 212 | _state[id].keepalive--; |
dgriffin65 | 15:14382459c8b7 | 213 | } else { |
dgriffin65 | 15:14382459c8b7 | 214 | _state[id].client->close(); |
dgriffin65 | 15:14382459c8b7 | 215 | } |
dgriffin65 | 15:14382459c8b7 | 216 | _state[id].mode = MODE_REQUEST; |
dgriffin65 | 15:14382459c8b7 | 217 | } else |
dgriffin65 | 15:14382459c8b7 | 218 | if (_state[id].mode == MODE_WEBSOCKET_ENTER) { |
dgriffin65 | 15:14382459c8b7 | 219 | parseWebsocket(id); |
dgriffin65 | 15:14382459c8b7 | 220 | _state[id].mode = MODE_WEBSOCKET; |
dgriffin65 | 15:14382459c8b7 | 221 | } |
dgriffin65 | 15:14382459c8b7 | 222 | } |
dgriffin65 | 15:14382459c8b7 | 223 | |
dgriffin65 | 15:14382459c8b7 | 224 | int HTTPD::parseRequest (int id) { |
dgriffin65 | 15:14382459c8b7 | 225 | int i, j, len; |
dgriffin65 | 15:14382459c8b7 | 226 | char buf[HTTPD_CMD_SIZE]; |
dgriffin65 | 15:14382459c8b7 | 227 | |
dgriffin65 | 15:14382459c8b7 | 228 | for (len = 0; len < sizeof(buf); len++) { |
dgriffin65 | 15:14382459c8b7 | 229 | if (_state[id].buf->dequeue(&buf[len]) == false) break; |
dgriffin65 | 15:14382459c8b7 | 230 | } |
dgriffin65 | 15:14382459c8b7 | 231 | buf[len] = 0; |
dgriffin65 | 15:14382459c8b7 | 232 | |
dgriffin65 | 15:14382459c8b7 | 233 | if (strnicmp(buf, "GET ", 4) == 0) { |
dgriffin65 | 15:14382459c8b7 | 234 | _state[id].req = REQ_HTTPGET; |
dgriffin65 | 15:14382459c8b7 | 235 | j = 4; |
dgriffin65 | 15:14382459c8b7 | 236 | } else |
dgriffin65 | 15:14382459c8b7 | 237 | if (strnicmp(buf, "POST ", 5) == 0) { |
dgriffin65 | 15:14382459c8b7 | 238 | _state[id].req = REQ_HTTPPOST; |
dgriffin65 | 15:14382459c8b7 | 239 | j = 5; |
dgriffin65 | 15:14382459c8b7 | 240 | } else { |
dgriffin65 | 15:14382459c8b7 | 241 | return -1; |
dgriffin65 | 15:14382459c8b7 | 242 | } |
dgriffin65 | 15:14382459c8b7 | 243 | |
dgriffin65 | 15:14382459c8b7 | 244 | for (i = 0; i < len - j; i ++) { |
dgriffin65 | 15:14382459c8b7 | 245 | _state[id].uri[i] = buf[i + j]; |
dgriffin65 | 15:14382459c8b7 | 246 | if (buf[i + j] == ' ' || i >= sizeof(buf) - 1) { |
dgriffin65 | 15:14382459c8b7 | 247 | _state[id].uri[i] = 0; |
dgriffin65 | 15:14382459c8b7 | 248 | INFO("URI %d '%s'", _state[id].req, _state[id].uri); |
dgriffin65 | 15:14382459c8b7 | 249 | _state[id].mode = MODE_HEADER; |
dgriffin65 | 15:14382459c8b7 | 250 | _state[id].buf->flush(); |
dgriffin65 | 15:14382459c8b7 | 251 | _state[id].length = 0; |
dgriffin65 | 15:14382459c8b7 | 252 | _state[id].n = 0; |
dgriffin65 | 15:14382459c8b7 | 253 | _state[id].websocket = 0; |
dgriffin65 | 15:14382459c8b7 | 254 | _state[id].filename = NULL; |
dgriffin65 | 15:14382459c8b7 | 255 | _state[id].querystring = NULL; |
dgriffin65 | 15:14382459c8b7 | 256 | break; |
dgriffin65 | 15:14382459c8b7 | 257 | } |
dgriffin65 | 15:14382459c8b7 | 258 | } |
dgriffin65 | 15:14382459c8b7 | 259 | |
dgriffin65 | 15:14382459c8b7 | 260 | i = getHandler(_state[id].uri); |
dgriffin65 | 15:14382459c8b7 | 261 | if (i >= 0) { |
dgriffin65 | 15:14382459c8b7 | 262 | _state[id].filename = &_state[id].uri[strlen(_handler[i].uri)]; |
dgriffin65 | 15:14382459c8b7 | 263 | for (i = 0; i < strlen(_state[id].filename); i ++) { |
dgriffin65 | 15:14382459c8b7 | 264 | if (_state[id].filename[i] == '?') { |
dgriffin65 | 15:14382459c8b7 | 265 | _state[id].filename[i] = 0; |
dgriffin65 | 15:14382459c8b7 | 266 | _state[id].querystring = _state[id].filename + i + 1; |
dgriffin65 | 15:14382459c8b7 | 267 | break; |
dgriffin65 | 15:14382459c8b7 | 268 | } |
dgriffin65 | 15:14382459c8b7 | 269 | } |
dgriffin65 | 15:14382459c8b7 | 270 | INFO("FILE '%s' QUERY '%s'", _state[id].filename, _state[id].querystring); |
dgriffin65 | 15:14382459c8b7 | 271 | } |
dgriffin65 | 15:14382459c8b7 | 272 | return 0; |
dgriffin65 | 15:14382459c8b7 | 273 | } |
dgriffin65 | 15:14382459c8b7 | 274 | |
dgriffin65 | 15:14382459c8b7 | 275 | #define HEADER_TABLE_NUM 5 |
dgriffin65 | 15:14382459c8b7 | 276 | int HTTPD::parseHeader (int id) { |
dgriffin65 | 15:14382459c8b7 | 277 | int i; |
dgriffin65 | 15:14382459c8b7 | 278 | char buf[HTTPD_CMD_SIZE]; |
dgriffin65 | 15:14382459c8b7 | 279 | static const struct HEADER_TABLE { |
dgriffin65 | 15:14382459c8b7 | 280 | const char header[24]; |
dgriffin65 | 15:14382459c8b7 | 281 | void (HTTPD::*func)(int id, const char*); |
dgriffin65 | 15:14382459c8b7 | 282 | } header_table[HEADER_TABLE_NUM] = { |
dgriffin65 | 15:14382459c8b7 | 283 | {"Content-Length:", &HTTPD::reqContentLength}, |
dgriffin65 | 15:14382459c8b7 | 284 | {"Connection:", &HTTPD::reqConnection}, |
dgriffin65 | 15:14382459c8b7 | 285 | {"Upgrade: websocket", &HTTPD::reqUpgrade}, |
dgriffin65 | 15:14382459c8b7 | 286 | {"Sec-WebSocket-Version:", &HTTPD::reqWebSocketVersion}, |
dgriffin65 | 15:14382459c8b7 | 287 | {"Sec-WebSocket-Key:", &HTTPD::reqWebSocketKey}, |
dgriffin65 | 15:14382459c8b7 | 288 | }; |
dgriffin65 | 15:14382459c8b7 | 289 | for (i = 0; i < sizeof(buf); i++) { |
dgriffin65 | 15:14382459c8b7 | 290 | if (_state[id].buf->dequeue(&buf[i]) == false) break; |
dgriffin65 | 15:14382459c8b7 | 291 | } |
dgriffin65 | 15:14382459c8b7 | 292 | buf[i] = 0; |
dgriffin65 | 15:14382459c8b7 | 293 | |
dgriffin65 | 15:14382459c8b7 | 294 | for (i = 0; i < HEADER_TABLE_NUM; i ++) { |
dgriffin65 | 15:14382459c8b7 | 295 | if (strnicmp(buf, header_table[i].header, strlen(header_table[i].header)) == 0) { |
dgriffin65 | 15:14382459c8b7 | 296 | DBG("parse header %d '%s'\r\n", i, buf); |
dgriffin65 | 15:14382459c8b7 | 297 | if (header_table[i].func != NULL) { |
dgriffin65 | 15:14382459c8b7 | 298 | (this->*(header_table[i].func))(id, buf); |
dgriffin65 | 15:14382459c8b7 | 299 | } |
dgriffin65 | 15:14382459c8b7 | 300 | return 0; |
dgriffin65 | 15:14382459c8b7 | 301 | } |
dgriffin65 | 15:14382459c8b7 | 302 | } |
dgriffin65 | 15:14382459c8b7 | 303 | |
dgriffin65 | 15:14382459c8b7 | 304 | return -1; |
dgriffin65 | 15:14382459c8b7 | 305 | } |
dgriffin65 | 15:14382459c8b7 | 306 | |
dgriffin65 | 15:14382459c8b7 | 307 | void HTTPD::reqContentLength (int id, const char *buf) { |
dgriffin65 | 15:14382459c8b7 | 308 | _state[id].length = atoi(&buf[16]); |
dgriffin65 | 15:14382459c8b7 | 309 | } |
dgriffin65 | 15:14382459c8b7 | 310 | |
dgriffin65 | 15:14382459c8b7 | 311 | void HTTPD::reqConnection (int id, const char *buf) { |
dgriffin65 | 15:14382459c8b7 | 312 | if (strnicmp(&buf[12], "Keep-Alive", 10) == 0 && _state[id].keepalive == 0) { |
dgriffin65 | 15:14382459c8b7 | 313 | _state[id].keepalive = HTTPD_KEEPALIVE; |
dgriffin65 | 15:14382459c8b7 | 314 | } else { |
dgriffin65 | 15:14382459c8b7 | 315 | _state[id].keepalive = 0; |
dgriffin65 | 15:14382459c8b7 | 316 | } |
dgriffin65 | 15:14382459c8b7 | 317 | } |
dgriffin65 | 15:14382459c8b7 | 318 | |
dgriffin65 | 15:14382459c8b7 | 319 | void HTTPD::reqUpgrade (int id, const char *buf) { |
dgriffin65 | 15:14382459c8b7 | 320 | if (! _state[id].websocket) _state[id].websocket = 1; |
dgriffin65 | 15:14382459c8b7 | 321 | } |
dgriffin65 | 15:14382459c8b7 | 322 | |
dgriffin65 | 15:14382459c8b7 | 323 | void HTTPD::reqWebSocketVersion (int id, const char *buf) { |
dgriffin65 | 15:14382459c8b7 | 324 | _state[id].websocket = atoi(&buf[23]); |
dgriffin65 | 15:14382459c8b7 | 325 | } |
dgriffin65 | 15:14382459c8b7 | 326 | |
dgriffin65 | 15:14382459c8b7 | 327 | void HTTPD::reqWebSocketKey (int id, const char *buf) { |
dgriffin65 | 15:14382459c8b7 | 328 | if (_state[id].websocket_key == NULL) { |
dgriffin65 | 15:14382459c8b7 | 329 | _state[id].websocket_key = (char*)malloc(30); |
dgriffin65 | 15:14382459c8b7 | 330 | } |
dgriffin65 | 15:14382459c8b7 | 331 | strncpy(_state[id].websocket_key, &buf[19], 30); |
dgriffin65 | 15:14382459c8b7 | 332 | } |