GainSpan Wi-Fi library see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
Dependents: GSwifi_httpd GSwifi_websocket GSwifi_tcpclient GSwifi_tcpserver ... more
Fork of GSwifi by
GainSpan Wi-Fi library
The GS1011 is an ultra low power 802.11b wireless module from GainSpan.
see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
ゲインスパン Wi-Fi モジュール ライブラリ
ゲインスパン社の低電力 Wi-Fiモジュール(無線LAN) GS1011 シリーズ用のライブラリです。
解説: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
GSwifi_httpd.cpp@25:f6e5622d2930, 2013-02-11 (annotated)
- Committer:
- gsfan
- Date:
- Mon Feb 11 06:01:46 2013 +0000
- Revision:
- 25:f6e5622d2930
- Parent:
- 24:5c350ae2e703
- Child:
- 26:b347ee3a1087
split the file
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gsfan | 25:f6e5622d2930 | 1 | /* Copyright (C) 2013 gsfan, MIT License |
gsfan | 25:f6e5622d2930 | 2 | * |
gsfan | 25:f6e5622d2930 | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
gsfan | 25:f6e5622d2930 | 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
gsfan | 25:f6e5622d2930 | 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
gsfan | 25:f6e5622d2930 | 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
gsfan | 25:f6e5622d2930 | 7 | * furnished to do so, subject to the following conditions: |
gsfan | 25:f6e5622d2930 | 8 | * |
gsfan | 25:f6e5622d2930 | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
gsfan | 25:f6e5622d2930 | 10 | * substantial portions of the Software. |
gsfan | 25:f6e5622d2930 | 11 | * |
gsfan | 25:f6e5622d2930 | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
gsfan | 25:f6e5622d2930 | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
gsfan | 25:f6e5622d2930 | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
gsfan | 25:f6e5622d2930 | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
gsfan | 25:f6e5622d2930 | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
gsfan | 25:f6e5622d2930 | 17 | */ |
gsfan | 25:f6e5622d2930 | 18 | /** @file |
gsfan | 25:f6e5622d2930 | 19 | * @brief Gainspan wi-fi module library for mbed |
gsfan | 25:f6e5622d2930 | 20 | * GS1011MIC, GS1011MIP, GainSpan WiFi Breakout, etc. |
gsfan | 25:f6e5622d2930 | 21 | */ |
gsfan | 25:f6e5622d2930 | 22 | |
gsfan | 18:4b97804c37d1 | 23 | #include "dbg.h" |
gsfan | 18:4b97804c37d1 | 24 | #include "mbed.h" |
gsfan | 18:4b97804c37d1 | 25 | #include "GSwifi.h" |
gsfan | 23:a783c62c36d0 | 26 | #include "sha1.h" |
gsfan | 23:a783c62c36d0 | 27 | #include <string.h> |
gsfan | 18:4b97804c37d1 | 28 | |
gsfan | 20:151b5a4fdd29 | 29 | #ifdef GS_USE_HTTPD |
gsfan | 20:151b5a4fdd29 | 30 | |
gsfan | 25:f6e5622d2930 | 31 | #define MIMETABLE_NUM 9 |
gsfan | 19:cad912f5a6ba | 32 | struct { |
gsfan | 25:f6e5622d2930 | 33 | char ext[5]; |
gsfan | 22:9b077e2823ce | 34 | char type[24]; |
gsfan | 19:cad912f5a6ba | 35 | } mimetable[MIMETABLE_NUM] = { |
gsfan | 25:f6e5622d2930 | 36 | {"txt", "text/plain"}, // default |
gsfan | 25:f6e5622d2930 | 37 | {"html", "text/html"}, |
gsfan | 25:f6e5622d2930 | 38 | {"htm", "text/html"}, |
gsfan | 25:f6e5622d2930 | 39 | {"css", "text/css"}, |
gsfan | 25:f6e5622d2930 | 40 | {"js", "application/javascript"}, |
gsfan | 25:f6e5622d2930 | 41 | {"jpg", "image/jpeg"}, |
gsfan | 25:f6e5622d2930 | 42 | {"png", "image/png"}, |
gsfan | 25:f6e5622d2930 | 43 | {"gif", "image/gif"}, |
gsfan | 25:f6e5622d2930 | 44 | {"ico", "image/x-icon"}, |
gsfan | 19:cad912f5a6ba | 45 | }; |
gsfan | 19:cad912f5a6ba | 46 | |
gsfan | 18:4b97804c37d1 | 47 | int GSwifi::httpd (int port) { |
gsfan | 18:4b97804c37d1 | 48 | int i; |
gsfan | 18:4b97804c37d1 | 49 | char cmd[GS_CMD_SIZE]; |
gsfan | 18:4b97804c37d1 | 50 | |
gsfan | 18:4b97804c37d1 | 51 | if (! _connect || _status != GSSTAT_READY) return -1; |
gsfan | 18:4b97804c37d1 | 52 | |
gsfan | 23:a783c62c36d0 | 53 | memset(&_httpd, 0, sizeof(_httpd)); |
gsfan | 18:4b97804c37d1 | 54 | for (i = 0; i < 16; i ++) { |
gsfan | 23:a783c62c36d0 | 55 | _httpd[i].mode = GSHTTPDMODE_REQUEST; |
gsfan | 18:4b97804c37d1 | 56 | } |
gsfan | 18:4b97804c37d1 | 57 | _handler_count = 0; |
gsfan | 18:4b97804c37d1 | 58 | |
gsfan | 18:4b97804c37d1 | 59 | sprintf(cmd, "AT+NSTCP=%d", port); |
gsfan | 18:4b97804c37d1 | 60 | if (command(cmd, GSRES_CONNECT)) return -1; |
gsfan | 18:4b97804c37d1 | 61 | |
gsfan | 18:4b97804c37d1 | 62 | newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, NULL); |
gsfan | 19:cad912f5a6ba | 63 | /* |
gsfan | 19:cad912f5a6ba | 64 | // newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, &GSwifi::poll_httpd); |
gsfan | 19:cad912f5a6ba | 65 | // newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, reinterpret_cast<onGsReceiveFunc>(&GSwifi::poll_httpd)); |
gsfan | 19:cad912f5a6ba | 66 | void (GSwifi::*f1)(int,int) = &GSwifi::poll_httpd; |
gsfan | 19:cad912f5a6ba | 67 | onGsReceiveFunc f2 = reinterpret_cast<onGsReceiveFunc>(f1); |
gsfan | 19:cad912f5a6ba | 68 | newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, f2); |
gsfan | 19:cad912f5a6ba | 69 | */ |
gsfan | 18:4b97804c37d1 | 70 | return _cid; |
gsfan | 18:4b97804c37d1 | 71 | } |
gsfan | 18:4b97804c37d1 | 72 | |
gsfan | 18:4b97804c37d1 | 73 | void GSwifi::poll_httpd (int cid, int len) { |
gsfan | 18:4b97804c37d1 | 74 | int i, j, flg = 0; |
gsfan | 18:4b97804c37d1 | 75 | char c; |
gsfan | 18:4b97804c37d1 | 76 | |
gsfan | 18:4b97804c37d1 | 77 | if (len == 0) { |
gsfan | 23:a783c62c36d0 | 78 | // start request |
gsfan | 23:a783c62c36d0 | 79 | _httpd[cid].mode = GSHTTPDMODE_REQUEST; |
gsfan | 18:4b97804c37d1 | 80 | _httpd[cid].len = 0; |
gsfan | 18:4b97804c37d1 | 81 | _httpd[cid].keepalive = 0; |
gsfan | 23:a783c62c36d0 | 82 | #ifdef GS_USE_WEBSOCKET |
gsfan | 23:a783c62c36d0 | 83 | _httpd[cid].websocket = 0; |
gsfan | 23:a783c62c36d0 | 84 | #endif |
gsfan | 18:4b97804c37d1 | 85 | return; |
gsfan | 18:4b97804c37d1 | 86 | } |
gsfan | 18:4b97804c37d1 | 87 | |
gsfan | 23:a783c62c36d0 | 88 | #ifdef GS_USE_WEBSOCKET |
gsfan | 23:a783c62c36d0 | 89 | if (_httpd[cid].mode >= GSHTTPDMODE_WEBSOCKET) { |
gsfan | 23:a783c62c36d0 | 90 | poll_websocket(cid, len); |
gsfan | 23:a783c62c36d0 | 91 | return; |
gsfan | 23:a783c62c36d0 | 92 | } |
gsfan | 23:a783c62c36d0 | 93 | #endif |
gsfan | 23:a783c62c36d0 | 94 | |
gsfan | 18:4b97804c37d1 | 95 | while (_gs_sock[cid].connect && _gs_sock[cid].data->use()) { |
gsfan | 18:4b97804c37d1 | 96 | flg = 0; |
gsfan | 18:4b97804c37d1 | 97 | if (_httpd[cid].buf == NULL) { |
gsfan | 18:4b97804c37d1 | 98 | _httpd[cid].buf = new char[HTTPD_BUF_SIZE]; |
gsfan | 18:4b97804c37d1 | 99 | } |
gsfan | 23:a783c62c36d0 | 100 | // get 1 line |
gsfan | 18:4b97804c37d1 | 101 | for (j = 0; j < len; j ++) { |
gsfan | 25:f6e5622d2930 | 102 | _gs_sock[cid].data->dequeue(&c); |
gsfan | 18:4b97804c37d1 | 103 | if (c == '\r') continue; |
gsfan | 23:a783c62c36d0 | 104 | if (c == '\n' && _httpd[cid].mode != GSHTTPDMODE_BODY) break; |
gsfan | 18:4b97804c37d1 | 105 | |
gsfan | 18:4b97804c37d1 | 106 | if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) { |
gsfan | 18:4b97804c37d1 | 107 | _httpd[cid].buf[_httpd[cid].len] = c; |
gsfan | 18:4b97804c37d1 | 108 | } |
gsfan | 18:4b97804c37d1 | 109 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 110 | if (_httpd[cid].mode == GSHTTPDMODE_BODY && _httpd[cid].len >= _httpd[cid].length) break; // end of body |
gsfan | 18:4b97804c37d1 | 111 | } |
gsfan | 23:a783c62c36d0 | 112 | if (j >= len) return; // continue |
gsfan | 18:4b97804c37d1 | 113 | if (_httpd[cid].len < HTTPD_BUF_SIZE) { |
gsfan | 18:4b97804c37d1 | 114 | _httpd[cid].buf[_httpd[cid].len] = 0; |
gsfan | 20:151b5a4fdd29 | 115 | DBG("httpd %d: %d %s (%d)\r\n", cid, _httpd[cid].mode, _httpd[cid].buf, _httpd[cid].len); |
gsfan | 18:4b97804c37d1 | 116 | } |
gsfan | 18:4b97804c37d1 | 117 | |
gsfan | 23:a783c62c36d0 | 118 | // parse |
gsfan | 18:4b97804c37d1 | 119 | switch (_httpd[cid].mode) { |
gsfan | 23:a783c62c36d0 | 120 | case GSHTTPDMODE_REQUEST: |
gsfan | 23:a783c62c36d0 | 121 | if (strnicmp(_httpd[cid].buf, "GET ", 4) == 0) { |
gsfan | 19:cad912f5a6ba | 122 | _httpd[cid].type = GSPROT_HTTPGET; |
gsfan | 18:4b97804c37d1 | 123 | j = 4; |
gsfan | 18:4b97804c37d1 | 124 | } else |
gsfan | 23:a783c62c36d0 | 125 | if (strnicmp(_httpd[cid].buf, "POST ", 5) == 0) { |
gsfan | 19:cad912f5a6ba | 126 | _httpd[cid].type = GSPROT_HTTPPOST; |
gsfan | 18:4b97804c37d1 | 127 | j = 5; |
gsfan | 18:4b97804c37d1 | 128 | } else { |
gsfan | 23:a783c62c36d0 | 129 | _httpd[cid].mode = GSHTTPDMODE_ERROR; |
gsfan | 18:4b97804c37d1 | 130 | break; |
gsfan | 18:4b97804c37d1 | 131 | } |
gsfan | 18:4b97804c37d1 | 132 | |
gsfan | 23:a783c62c36d0 | 133 | // get uri |
gsfan | 18:4b97804c37d1 | 134 | for (i = j; i < _httpd[cid].len; i ++) { |
gsfan | 18:4b97804c37d1 | 135 | if (_httpd[cid].buf[i] == ' ') break; |
gsfan | 18:4b97804c37d1 | 136 | } |
gsfan | 18:4b97804c37d1 | 137 | i = i - j; |
gsfan | 18:4b97804c37d1 | 138 | if (i) { |
gsfan | 18:4b97804c37d1 | 139 | if (_httpd[cid].uri == NULL) { |
gsfan | 18:4b97804c37d1 | 140 | _httpd[cid].uri = new char[HTTPD_URI_SIZE]; |
gsfan | 18:4b97804c37d1 | 141 | } |
gsfan | 18:4b97804c37d1 | 142 | strncpy(_httpd[cid].uri, &_httpd[cid].buf[j], i); |
gsfan | 18:4b97804c37d1 | 143 | _httpd[cid].uri[i] = 0; |
gsfan | 18:4b97804c37d1 | 144 | } |
gsfan | 23:a783c62c36d0 | 145 | _httpd[cid].mode = GSHTTPDMODE_HEAD; |
gsfan | 18:4b97804c37d1 | 146 | _httpd[cid].length = 0; |
gsfan | 18:4b97804c37d1 | 147 | DBG("uri: %s\r\n", _httpd[cid].uri); |
gsfan | 18:4b97804c37d1 | 148 | break; |
gsfan | 18:4b97804c37d1 | 149 | |
gsfan | 23:a783c62c36d0 | 150 | case GSHTTPDMODE_HEAD: |
gsfan | 18:4b97804c37d1 | 151 | if (_httpd[cid].len == 0) { |
gsfan | 23:a783c62c36d0 | 152 | // blank line (end of header) |
gsfan | 23:a783c62c36d0 | 153 | _httpd[cid].mode = GSHTTPDMODE_BODY; |
gsfan | 19:cad912f5a6ba | 154 | if (_httpd[cid].length == 0) flg = 1; // no body |
gsfan | 23:a783c62c36d0 | 155 | #ifdef GS_USE_WEBSOCKET |
gsfan | 23:a783c62c36d0 | 156 | if (_httpd[cid].websocket && _httpd[cid].websocket_key) { |
gsfan | 23:a783c62c36d0 | 157 | // enter websocket |
gsfan | 23:a783c62c36d0 | 158 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET; |
gsfan | 23:a783c62c36d0 | 159 | _httpd[cid].len = 0; |
gsfan | 23:a783c62c36d0 | 160 | flg = 1; |
gsfan | 23:a783c62c36d0 | 161 | } |
gsfan | 23:a783c62c36d0 | 162 | #endif |
gsfan | 18:4b97804c37d1 | 163 | } else |
gsfan | 23:a783c62c36d0 | 164 | if (strnicmp(_httpd[cid].buf, "Content-Length: ", 16) == 0) { |
gsfan | 18:4b97804c37d1 | 165 | _httpd[cid].length = atoi(&_httpd[cid].buf[16]); |
gsfan | 18:4b97804c37d1 | 166 | } else |
gsfan | 23:a783c62c36d0 | 167 | if (strnicmp(_httpd[cid].buf, "Connection: Keep-Alive", 22) == 0) { |
gsfan | 18:4b97804c37d1 | 168 | if (! _httpd[cid].keepalive) { |
gsfan | 18:4b97804c37d1 | 169 | _httpd[cid].keepalive = HTTPD_KEEPALIVE; |
gsfan | 18:4b97804c37d1 | 170 | } |
gsfan | 23:a783c62c36d0 | 171 | #ifdef GS_USE_WEBSOCKET |
gsfan | 23:a783c62c36d0 | 172 | } else |
gsfan | 23:a783c62c36d0 | 173 | if (strnicmp(_httpd[cid].buf, "Upgrade: websocket", 18) == 0) { |
gsfan | 23:a783c62c36d0 | 174 | if (! _httpd[cid].websocket) _httpd[cid].websocket = 1; |
gsfan | 23:a783c62c36d0 | 175 | } else |
gsfan | 23:a783c62c36d0 | 176 | if (strnicmp(_httpd[cid].buf, "Sec-WebSocket-Version: ", 23) == 0) { |
gsfan | 23:a783c62c36d0 | 177 | _httpd[cid].websocket = atoi(&_httpd[cid].buf[23]); |
gsfan | 23:a783c62c36d0 | 178 | } else |
gsfan | 23:a783c62c36d0 | 179 | if (strnicmp(_httpd[cid].buf, "Sec-WebSocket-Key: ", 19) == 0) { |
gsfan | 23:a783c62c36d0 | 180 | if (_httpd[cid].websocket_key == NULL) { |
gsfan | 23:a783c62c36d0 | 181 | _httpd[cid].websocket_key = new char[30]; |
gsfan | 23:a783c62c36d0 | 182 | } |
gsfan | 23:a783c62c36d0 | 183 | strncpy(_httpd[cid].websocket_key, &_httpd[cid].buf[19], 30); |
gsfan | 23:a783c62c36d0 | 184 | #endif |
gsfan | 18:4b97804c37d1 | 185 | } |
gsfan | 18:4b97804c37d1 | 186 | break; |
gsfan | 18:4b97804c37d1 | 187 | |
gsfan | 23:a783c62c36d0 | 188 | case GSHTTPDMODE_BODY: |
gsfan | 18:4b97804c37d1 | 189 | if (_httpd[cid].len >= _httpd[cid].length) { |
gsfan | 18:4b97804c37d1 | 190 | DBG("body: %s\r\n", _httpd[cid].buf); |
gsfan | 18:4b97804c37d1 | 191 | flg = 1; |
gsfan | 18:4b97804c37d1 | 192 | } |
gsfan | 18:4b97804c37d1 | 193 | break; |
gsfan | 23:a783c62c36d0 | 194 | |
gsfan | 18:4b97804c37d1 | 195 | } |
gsfan | 18:4b97804c37d1 | 196 | |
gsfan | 23:a783c62c36d0 | 197 | #ifdef GS_USE_WEBSOCKET |
gsfan | 23:a783c62c36d0 | 198 | if (flg && _httpd[cid].mode == GSHTTPDMODE_WEBSOCKET) { |
gsfan | 23:a783c62c36d0 | 199 | // websocket |
gsfan | 24:5c350ae2e703 | 200 | _httpd[cid].host = _gs_sock[cid].host; |
gsfan | 24:5c350ae2e703 | 201 | j = strlen(_handler[i].uri); |
gsfan | 24:5c350ae2e703 | 202 | _httpd[cid].file = &_httpd[cid].uri[j]; |
gsfan | 24:5c350ae2e703 | 203 | _httpd[cid].query = NULL; |
gsfan | 24:5c350ae2e703 | 204 | |
gsfan | 23:a783c62c36d0 | 205 | send_websocket_accept(cid); |
gsfan | 24:5c350ae2e703 | 206 | break; // exit while |
gsfan | 23:a783c62c36d0 | 207 | |
gsfan | 23:a783c62c36d0 | 208 | } else |
gsfan | 23:a783c62c36d0 | 209 | #endif |
gsfan | 18:4b97804c37d1 | 210 | if (flg) { |
gsfan | 18:4b97804c37d1 | 211 | // http request |
gsfan | 18:4b97804c37d1 | 212 | _httpd[cid].buf[_httpd[cid].len] = 0; |
gsfan | 19:cad912f5a6ba | 213 | |
gsfan | 23:a783c62c36d0 | 214 | i = get_handler(_httpd[cid].uri); |
gsfan | 23:a783c62c36d0 | 215 | if (i >= 0) { |
gsfan | 23:a783c62c36d0 | 216 | _httpd[cid].host = _gs_sock[cid].host; |
gsfan | 23:a783c62c36d0 | 217 | j = strlen(_handler[i].uri); |
gsfan | 23:a783c62c36d0 | 218 | _httpd[cid].file = &_httpd[cid].uri[j]; |
gsfan | 23:a783c62c36d0 | 219 | _httpd[cid].query = NULL; |
gsfan | 23:a783c62c36d0 | 220 | for (; j < strlen(_httpd[cid].uri); j ++) { |
gsfan | 23:a783c62c36d0 | 221 | if (_httpd[cid].uri[j] == '?') { |
gsfan | 23:a783c62c36d0 | 222 | // query string |
gsfan | 23:a783c62c36d0 | 223 | _httpd[cid].uri[j] = 0; |
gsfan | 23:a783c62c36d0 | 224 | _httpd[cid].query = &_httpd[cid].uri[j + 1]; |
gsfan | 23:a783c62c36d0 | 225 | break; |
gsfan | 18:4b97804c37d1 | 226 | } |
gsfan | 18:4b97804c37d1 | 227 | } |
gsfan | 23:a783c62c36d0 | 228 | |
gsfan | 23:a783c62c36d0 | 229 | if (_handler[i].dir) { |
gsfan | 23:a783c62c36d0 | 230 | // file |
gsfan | 23:a783c62c36d0 | 231 | httpd_request(cid, &_httpd[cid], _handler[i].dir); |
gsfan | 23:a783c62c36d0 | 232 | flg = 1; |
gsfan | 23:a783c62c36d0 | 233 | } else |
gsfan | 23:a783c62c36d0 | 234 | if (_handler[i].onHttpCgi) { |
gsfan | 23:a783c62c36d0 | 235 | // cgi |
gsfan | 23:a783c62c36d0 | 236 | _handler[i].onHttpCgi(cid, &_httpd[cid]); |
gsfan | 23:a783c62c36d0 | 237 | _httpd[cid].keepalive = 0; |
gsfan | 23:a783c62c36d0 | 238 | LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); |
gsfan | 23:a783c62c36d0 | 239 | LOG("%s %s %d 200 -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length); |
gsfan | 23:a783c62c36d0 | 240 | flg = 1; |
gsfan | 23:a783c62c36d0 | 241 | } |
gsfan | 23:a783c62c36d0 | 242 | } else { |
gsfan | 19:cad912f5a6ba | 243 | // not found |
gsfan | 18:4b97804c37d1 | 244 | send_httpd_error(cid, 403); |
gsfan | 18:4b97804c37d1 | 245 | } |
gsfan | 18:4b97804c37d1 | 246 | |
gsfan | 18:4b97804c37d1 | 247 | if (_httpd[cid].keepalive) { |
gsfan | 23:a783c62c36d0 | 248 | _httpd[cid].mode = GSHTTPDMODE_REQUEST; |
gsfan | 18:4b97804c37d1 | 249 | _httpd[cid].len = 0; |
gsfan | 18:4b97804c37d1 | 250 | _httpd[cid].length = 0; |
gsfan | 18:4b97804c37d1 | 251 | _httpd[cid].keepalive --; |
gsfan | 18:4b97804c37d1 | 252 | } else { |
gsfan | 18:4b97804c37d1 | 253 | close(cid); |
gsfan | 18:4b97804c37d1 | 254 | } |
gsfan | 18:4b97804c37d1 | 255 | } |
gsfan | 18:4b97804c37d1 | 256 | |
gsfan | 23:a783c62c36d0 | 257 | if (_httpd[cid].mode == GSHTTPDMODE_ERROR) { |
gsfan | 18:4b97804c37d1 | 258 | send_httpd_error(cid, 400); |
gsfan | 18:4b97804c37d1 | 259 | } |
gsfan | 18:4b97804c37d1 | 260 | |
gsfan | 18:4b97804c37d1 | 261 | _httpd[cid].len = 0; |
gsfan | 23:a783c62c36d0 | 262 | } // while |
gsfan | 23:a783c62c36d0 | 263 | } |
gsfan | 23:a783c62c36d0 | 264 | |
gsfan | 23:a783c62c36d0 | 265 | int GSwifi::get_handler (char *uri) { |
gsfan | 23:a783c62c36d0 | 266 | int i, j; |
gsfan | 23:a783c62c36d0 | 267 | |
gsfan | 23:a783c62c36d0 | 268 | for (i = 0; i < _handler_count; i ++) { |
gsfan | 23:a783c62c36d0 | 269 | j = strlen(_handler[i].uri); |
gsfan | 23:a783c62c36d0 | 270 | if (strncmp(uri, _handler[i].uri, j) == NULL) { |
gsfan | 23:a783c62c36d0 | 271 | // found |
gsfan | 23:a783c62c36d0 | 272 | return i; |
gsfan | 23:a783c62c36d0 | 273 | } |
gsfan | 23:a783c62c36d0 | 274 | } |
gsfan | 23:a783c62c36d0 | 275 | return -1; |
gsfan | 18:4b97804c37d1 | 276 | } |
gsfan | 18:4b97804c37d1 | 277 | |
gsfan | 19:cad912f5a6ba | 278 | int GSwifi::httpd_request (int cid, GS_httpd *gshttpd, char *dir) { |
gsfan | 18:4b97804c37d1 | 279 | FILE *fp; |
gsfan | 20:151b5a4fdd29 | 280 | int i, len; |
gsfan | 20:151b5a4fdd29 | 281 | char buf[HTTPD_BUF_SIZE]; |
gsfan | 20:151b5a4fdd29 | 282 | char file[HTTPD_URI_SIZE]; |
gsfan | 18:4b97804c37d1 | 283 | |
gsfan | 20:151b5a4fdd29 | 284 | strcpy(file, dir); |
gsfan | 20:151b5a4fdd29 | 285 | strcat(file, gshttpd->file); |
gsfan | 20:151b5a4fdd29 | 286 | if (file[strlen(file) - 1] == '/') { |
gsfan | 24:5c350ae2e703 | 287 | strcat(file, "index.html"); |
gsfan | 18:4b97804c37d1 | 288 | } |
gsfan | 20:151b5a4fdd29 | 289 | DBG("file: %s\r\n", file); |
gsfan | 18:4b97804c37d1 | 290 | |
gsfan | 20:151b5a4fdd29 | 291 | fp = fopen(file, "r"); |
gsfan | 18:4b97804c37d1 | 292 | if (fp) { |
gsfan | 19:cad912f5a6ba | 293 | send(cid, "HTTP/1.1 200 OK\r\n", 17); |
gsfan | 18:4b97804c37d1 | 294 | { |
gsfan | 19:cad912f5a6ba | 295 | // file size |
gsfan | 20:151b5a4fdd29 | 296 | i = ftell(fp); |
gsfan | 18:4b97804c37d1 | 297 | fseek(fp, 0, SEEK_END); |
gsfan | 20:151b5a4fdd29 | 298 | len = ftell(fp); |
gsfan | 20:151b5a4fdd29 | 299 | fseek(fp, i, SEEK_SET); |
gsfan | 18:4b97804c37d1 | 300 | } |
gsfan | 20:151b5a4fdd29 | 301 | sprintf(buf, "Content-Length: %d\r\n", len); |
gsfan | 18:4b97804c37d1 | 302 | send(cid, buf, strlen(buf)); |
gsfan | 20:151b5a4fdd29 | 303 | sprintf(buf, "Content-Type: %s\r\n", mimetype(file)); |
gsfan | 18:4b97804c37d1 | 304 | send(cid, buf, strlen(buf)); |
gsfan | 19:cad912f5a6ba | 305 | if (gshttpd->keepalive) { |
gsfan | 18:4b97804c37d1 | 306 | strcpy(buf, "Connection: Keep-Alive\r\n"); |
gsfan | 18:4b97804c37d1 | 307 | } else { |
gsfan | 18:4b97804c37d1 | 308 | strcpy(buf, "Connection: close\r\n"); |
gsfan | 18:4b97804c37d1 | 309 | } |
gsfan | 18:4b97804c37d1 | 310 | send(cid, buf, strlen(buf)); |
gsfan | 18:4b97804c37d1 | 311 | strcpy(buf, "Server: GSwifi httpd\r\n"); |
gsfan | 18:4b97804c37d1 | 312 | send(cid, buf, strlen(buf)); |
gsfan | 18:4b97804c37d1 | 313 | send(cid, "\r\n", 2); |
gsfan | 18:4b97804c37d1 | 314 | |
gsfan | 18:4b97804c37d1 | 315 | for (;;) { |
gsfan | 18:4b97804c37d1 | 316 | i = fread(buf, sizeof(char), sizeof(buf), fp); |
gsfan | 20:151b5a4fdd29 | 317 | if (i <= 0) break; |
gsfan | 22:9b077e2823ce | 318 | if (! _gs_sock[cid].connect) break; |
gsfan | 18:4b97804c37d1 | 319 | send(cid, buf, i); |
gsfan | 20:151b5a4fdd29 | 320 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
gsfan | 18:4b97804c37d1 | 321 | if (feof(fp)) break; |
gsfan | 20:151b5a4fdd29 | 322 | #endif |
gsfan | 18:4b97804c37d1 | 323 | } |
gsfan | 18:4b97804c37d1 | 324 | fclose(fp); |
gsfan | 20:151b5a4fdd29 | 325 | LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); |
gsfan | 20:151b5a4fdd29 | 326 | LOG("%s %s %d 200 %d\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, len); |
gsfan | 18:4b97804c37d1 | 327 | return 0; |
gsfan | 18:4b97804c37d1 | 328 | } |
gsfan | 18:4b97804c37d1 | 329 | |
gsfan | 18:4b97804c37d1 | 330 | send_httpd_error(cid, 404); |
gsfan | 18:4b97804c37d1 | 331 | return -1; |
gsfan | 18:4b97804c37d1 | 332 | } |
gsfan | 18:4b97804c37d1 | 333 | |
gsfan | 19:cad912f5a6ba | 334 | char *GSwifi::mimetype (char *file) { |
gsfan | 19:cad912f5a6ba | 335 | int i, j; |
gsfan | 19:cad912f5a6ba | 336 | |
gsfan | 20:151b5a4fdd29 | 337 | DBG("<%s>\r\n", file); |
gsfan | 19:cad912f5a6ba | 338 | for (i = 0; i < MIMETABLE_NUM; i ++) { |
gsfan | 19:cad912f5a6ba | 339 | j = strlen(mimetable[i].ext); |
gsfan | 25:f6e5622d2930 | 340 | if (file[strlen(file) - j - 1] == '.' && |
gsfan | 25:f6e5622d2930 | 341 | strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) { |
gsfan | 19:cad912f5a6ba | 342 | return mimetable[i].type; |
gsfan | 19:cad912f5a6ba | 343 | } |
gsfan | 19:cad912f5a6ba | 344 | } |
gsfan | 19:cad912f5a6ba | 345 | return mimetable[0].type; |
gsfan | 19:cad912f5a6ba | 346 | } |
gsfan | 19:cad912f5a6ba | 347 | |
gsfan | 23:a783c62c36d0 | 348 | int GSwifi::strnicmp (char *p1, char *p2, int n) { |
gsfan | 25:f6e5622d2930 | 349 | int i, r = -1; |
gsfan | 23:a783c62c36d0 | 350 | char c1, c2; |
gsfan | 23:a783c62c36d0 | 351 | |
gsfan | 23:a783c62c36d0 | 352 | for (i = 0; i < n; i ++) { |
gsfan | 23:a783c62c36d0 | 353 | c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i]; |
gsfan | 23:a783c62c36d0 | 354 | c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i]; |
gsfan | 23:a783c62c36d0 | 355 | r = c1 - c2; |
gsfan | 23:a783c62c36d0 | 356 | if (r) break; |
gsfan | 23:a783c62c36d0 | 357 | } |
gsfan | 23:a783c62c36d0 | 358 | return r; |
gsfan | 23:a783c62c36d0 | 359 | } |
gsfan | 23:a783c62c36d0 | 360 | |
gsfan | 18:4b97804c37d1 | 361 | void GSwifi::send_httpd_error (int cid, int err) { |
gsfan | 18:4b97804c37d1 | 362 | char buf[100], msg[30]; |
gsfan | 18:4b97804c37d1 | 363 | |
gsfan | 18:4b97804c37d1 | 364 | switch (err) { |
gsfan | 18:4b97804c37d1 | 365 | case 400: |
gsfan | 18:4b97804c37d1 | 366 | strcpy(msg, "Bad Request"); |
gsfan | 18:4b97804c37d1 | 367 | break; |
gsfan | 18:4b97804c37d1 | 368 | case 403: |
gsfan | 18:4b97804c37d1 | 369 | strcpy(msg, "Forbidden"); |
gsfan | 18:4b97804c37d1 | 370 | break; |
gsfan | 18:4b97804c37d1 | 371 | case 404: |
gsfan | 18:4b97804c37d1 | 372 | strcpy(msg, "Not Found"); |
gsfan | 18:4b97804c37d1 | 373 | break; |
gsfan | 18:4b97804c37d1 | 374 | case 500: |
gsfan | 18:4b97804c37d1 | 375 | default: |
gsfan | 18:4b97804c37d1 | 376 | strcpy(msg, "Internal Server Error"); |
gsfan | 18:4b97804c37d1 | 377 | break; |
gsfan | 18:4b97804c37d1 | 378 | } |
gsfan | 18:4b97804c37d1 | 379 | DBG("httpd error: %d %d %s\r\n", cid, err, msg); |
gsfan | 18:4b97804c37d1 | 380 | |
gsfan | 18:4b97804c37d1 | 381 | sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg); |
gsfan | 18:4b97804c37d1 | 382 | send(cid, buf, strlen(buf)); |
gsfan | 18:4b97804c37d1 | 383 | strcpy(buf, "Content-Type: text/html\r\n"); |
gsfan | 18:4b97804c37d1 | 384 | send(cid, buf, strlen(buf)); |
gsfan | 18:4b97804c37d1 | 385 | send(cid, "\r\n", 2); |
gsfan | 18:4b97804c37d1 | 386 | |
gsfan | 18:4b97804c37d1 | 387 | sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg); |
gsfan | 18:4b97804c37d1 | 388 | send(cid, buf, strlen(buf)); |
gsfan | 18:4b97804c37d1 | 389 | sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg); |
gsfan | 18:4b97804c37d1 | 390 | send(cid, buf, strlen(buf)); |
gsfan | 18:4b97804c37d1 | 391 | close(cid); |
gsfan | 20:151b5a4fdd29 | 392 | LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); |
gsfan | 20:151b5a4fdd29 | 393 | LOG("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err); |
gsfan | 18:4b97804c37d1 | 394 | } |
gsfan | 18:4b97804c37d1 | 395 | |
gsfan | 19:cad912f5a6ba | 396 | int GSwifi::attach_httpd (const char *uri, const char *dir) { |
gsfan | 18:4b97804c37d1 | 397 | if (_handler_count < HTTPD_HANDLE) { |
gsfan | 18:4b97804c37d1 | 398 | _handler[_handler_count].uri = new char[strlen(uri) + 1]; |
gsfan | 18:4b97804c37d1 | 399 | strcpy(_handler[_handler_count].uri, uri); |
gsfan | 18:4b97804c37d1 | 400 | _handler[_handler_count].dir = new char[strlen(dir) + 1]; |
gsfan | 18:4b97804c37d1 | 401 | strcpy(_handler[_handler_count].dir, dir); |
gsfan | 18:4b97804c37d1 | 402 | _handler[_handler_count].onHttpCgi = NULL; |
gsfan | 18:4b97804c37d1 | 403 | _handler_count ++; |
gsfan | 18:4b97804c37d1 | 404 | return 0; |
gsfan | 18:4b97804c37d1 | 405 | } else { |
gsfan | 18:4b97804c37d1 | 406 | return -1; |
gsfan | 18:4b97804c37d1 | 407 | } |
gsfan | 18:4b97804c37d1 | 408 | } |
gsfan | 18:4b97804c37d1 | 409 | |
gsfan | 19:cad912f5a6ba | 410 | int GSwifi::attach_httpd (const char *uri, onHttpdCgiFunc ponHttpCgi) { |
gsfan | 18:4b97804c37d1 | 411 | if (_handler_count < HTTPD_HANDLE) { |
gsfan | 18:4b97804c37d1 | 412 | _handler[_handler_count].uri = new char[strlen(uri) + 1]; |
gsfan | 18:4b97804c37d1 | 413 | strcpy(_handler[_handler_count].uri, uri); |
gsfan | 18:4b97804c37d1 | 414 | _handler[_handler_count].dir = NULL; |
gsfan | 18:4b97804c37d1 | 415 | _handler[_handler_count].onHttpCgi = ponHttpCgi; |
gsfan | 18:4b97804c37d1 | 416 | _handler_count ++; |
gsfan | 18:4b97804c37d1 | 417 | return 0; |
gsfan | 18:4b97804c37d1 | 418 | } else { |
gsfan | 18:4b97804c37d1 | 419 | return -1; |
gsfan | 18:4b97804c37d1 | 420 | } |
gsfan | 18:4b97804c37d1 | 421 | } |
gsfan | 20:151b5a4fdd29 | 422 | |
gsfan | 23:a783c62c36d0 | 423 | #ifdef GS_USE_WEBSOCKET |
gsfan | 23:a783c62c36d0 | 424 | void GSwifi::poll_websocket (int cid, int len) { |
gsfan | 23:a783c62c36d0 | 425 | int i, j, flg; |
gsfan | 23:a783c62c36d0 | 426 | unsigned char c; |
gsfan | 23:a783c62c36d0 | 427 | |
gsfan | 23:a783c62c36d0 | 428 | while (_gs_sock[cid].connect && _gs_sock[cid].data->use()) { |
gsfan | 23:a783c62c36d0 | 429 | flg = 0; |
gsfan | 23:a783c62c36d0 | 430 | // get 1 line |
gsfan | 23:a783c62c36d0 | 431 | for (j = 0; j < len; j ++) { |
gsfan | 25:f6e5622d2930 | 432 | _gs_sock[cid].data->dequeue((char*)&c); |
gsfan | 23:a783c62c36d0 | 433 | // DBG("_%c", c); |
gsfan | 23:a783c62c36d0 | 434 | |
gsfan | 23:a783c62c36d0 | 435 | switch (_httpd[cid].mode) { |
gsfan | 23:a783c62c36d0 | 436 | case GSHTTPDMODE_WEBSOCKET: |
gsfan | 23:a783c62c36d0 | 437 | if (_httpd[cid].len == 0) { |
gsfan | 23:a783c62c36d0 | 438 | _httpd[cid].type = c & 0x0f; |
gsfan | 23:a783c62c36d0 | 439 | _httpd[cid].websocket_flg = c << 8; |
gsfan | 23:a783c62c36d0 | 440 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 441 | } else |
gsfan | 23:a783c62c36d0 | 442 | if (_httpd[cid].len == 1) { |
gsfan | 23:a783c62c36d0 | 443 | _httpd[cid].websocket_flg |= c; |
gsfan | 23:a783c62c36d0 | 444 | _httpd[cid].length = c & 0x7f; |
gsfan | 23:a783c62c36d0 | 445 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 446 | if (_httpd[cid].length < 126) { |
gsfan | 23:a783c62c36d0 | 447 | _httpd[cid].len = 0; |
gsfan | 23:a783c62c36d0 | 448 | if (_httpd[cid].websocket_flg & 0x0080) { |
gsfan | 23:a783c62c36d0 | 449 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK; |
gsfan | 23:a783c62c36d0 | 450 | } else { |
gsfan | 23:a783c62c36d0 | 451 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY; |
gsfan | 23:a783c62c36d0 | 452 | } |
gsfan | 23:a783c62c36d0 | 453 | DBG("ws length %d\r\n", _httpd[cid].length); |
gsfan | 23:a783c62c36d0 | 454 | } |
gsfan | 23:a783c62c36d0 | 455 | } else { |
gsfan | 23:a783c62c36d0 | 456 | // length 16bit,64bit |
gsfan | 23:a783c62c36d0 | 457 | if (_httpd[cid].len == 2) { |
gsfan | 23:a783c62c36d0 | 458 | _httpd[cid].length = c; |
gsfan | 23:a783c62c36d0 | 459 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 460 | } else |
gsfan | 23:a783c62c36d0 | 461 | if (_httpd[cid].len < 9 && (_httpd[cid].websocket_flg & 0x7f) == 127) { |
gsfan | 23:a783c62c36d0 | 462 | // 64bit |
gsfan | 23:a783c62c36d0 | 463 | _httpd[cid].length = (_httpd[cid].length << 8) | c; |
gsfan | 23:a783c62c36d0 | 464 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 465 | } else { |
gsfan | 23:a783c62c36d0 | 466 | _httpd[cid].length = (_httpd[cid].length << 8) | c; |
gsfan | 23:a783c62c36d0 | 467 | _httpd[cid].len = 0; |
gsfan | 23:a783c62c36d0 | 468 | if (_httpd[cid].websocket_flg & 0x0080) { |
gsfan | 23:a783c62c36d0 | 469 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK; |
gsfan | 23:a783c62c36d0 | 470 | } else { |
gsfan | 23:a783c62c36d0 | 471 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY; |
gsfan | 23:a783c62c36d0 | 472 | } |
gsfan | 23:a783c62c36d0 | 473 | DBG("ws length2 %d\r\n", _httpd[cid].length); |
gsfan | 23:a783c62c36d0 | 474 | } |
gsfan | 23:a783c62c36d0 | 475 | } |
gsfan | 23:a783c62c36d0 | 476 | break; |
gsfan | 23:a783c62c36d0 | 477 | |
gsfan | 23:a783c62c36d0 | 478 | case GSHTTPDMODE_WEBSOCKET_MASK: |
gsfan | 23:a783c62c36d0 | 479 | _httpd[cid].websocket_mask[_httpd[cid].len] = c; |
gsfan | 23:a783c62c36d0 | 480 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 481 | if (_httpd[cid].len >= 4) { |
gsfan | 23:a783c62c36d0 | 482 | _httpd[cid].len = 0; |
gsfan | 23:a783c62c36d0 | 483 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY; |
gsfan | 23:a783c62c36d0 | 484 | DBG("ws mask\r\n"); |
gsfan | 23:a783c62c36d0 | 485 | } |
gsfan | 23:a783c62c36d0 | 486 | break; |
gsfan | 23:a783c62c36d0 | 487 | |
gsfan | 23:a783c62c36d0 | 488 | case GSHTTPDMODE_WEBSOCKET_BODY: |
gsfan | 23:a783c62c36d0 | 489 | if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) { |
gsfan | 23:a783c62c36d0 | 490 | if (_httpd[cid].websocket_flg & 0x0080) { |
gsfan | 23:a783c62c36d0 | 491 | _httpd[cid].buf[_httpd[cid].len] = c ^ _httpd[cid].websocket_mask[_httpd[cid].len & 0x03]; |
gsfan | 23:a783c62c36d0 | 492 | } else { |
gsfan | 23:a783c62c36d0 | 493 | _httpd[cid].buf[_httpd[cid].len] = c; |
gsfan | 23:a783c62c36d0 | 494 | } |
gsfan | 23:a783c62c36d0 | 495 | _httpd[cid].len ++; |
gsfan | 23:a783c62c36d0 | 496 | } |
gsfan | 23:a783c62c36d0 | 497 | break; |
gsfan | 23:a783c62c36d0 | 498 | } |
gsfan | 23:a783c62c36d0 | 499 | |
gsfan | 23:a783c62c36d0 | 500 | if (_httpd[cid].mode == GSHTTPDMODE_WEBSOCKET_BODY && _httpd[cid].len >= _httpd[cid].length) { |
gsfan | 23:a783c62c36d0 | 501 | flg = 1; |
gsfan | 23:a783c62c36d0 | 502 | break; |
gsfan | 23:a783c62c36d0 | 503 | } |
gsfan | 23:a783c62c36d0 | 504 | } |
gsfan | 23:a783c62c36d0 | 505 | if (j >= len) return; // continue |
gsfan | 23:a783c62c36d0 | 506 | if (_httpd[cid].len < HTTPD_BUF_SIZE) { |
gsfan | 23:a783c62c36d0 | 507 | _httpd[cid].buf[_httpd[cid].len] = 0; |
gsfan | 23:a783c62c36d0 | 508 | DBG("websocket %d: (%d)\r\n", cid, _httpd[cid].len); |
gsfan | 23:a783c62c36d0 | 509 | } |
gsfan | 23:a783c62c36d0 | 510 | |
gsfan | 23:a783c62c36d0 | 511 | if (flg) { |
gsfan | 23:a783c62c36d0 | 512 | // websocket request |
gsfan | 23:a783c62c36d0 | 513 | DBG("ws type %d\r\n", _httpd[cid].type); |
gsfan | 23:a783c62c36d0 | 514 | switch (_httpd[cid].type) { |
gsfan | 23:a783c62c36d0 | 515 | case 0x00: // continuation |
gsfan | 23:a783c62c36d0 | 516 | case 0x01: // text |
gsfan | 23:a783c62c36d0 | 517 | case 0x02: // binary |
gsfan | 23:a783c62c36d0 | 518 | i = get_handler(_httpd[cid].uri); |
gsfan | 23:a783c62c36d0 | 519 | if (i >= 0) { |
gsfan | 23:a783c62c36d0 | 520 | if (_handler[i].onHttpCgi) { |
gsfan | 23:a783c62c36d0 | 521 | // cgi |
gsfan | 23:a783c62c36d0 | 522 | _handler[i].onHttpCgi(cid, &_httpd[cid]); |
gsfan | 23:a783c62c36d0 | 523 | LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); |
gsfan | 24:5c350ae2e703 | 524 | LOG("%s %s %d 200 -\r\n", "WEBSOCKET", _httpd[cid].uri, _httpd[cid].length); |
gsfan | 23:a783c62c36d0 | 525 | flg = 1; |
gsfan | 23:a783c62c36d0 | 526 | } |
gsfan | 23:a783c62c36d0 | 527 | } |
gsfan | 23:a783c62c36d0 | 528 | break; |
gsfan | 23:a783c62c36d0 | 529 | |
gsfan | 23:a783c62c36d0 | 530 | case 0x08: // close |
gsfan | 23:a783c62c36d0 | 531 | close(cid); |
gsfan | 23:a783c62c36d0 | 532 | break; |
gsfan | 23:a783c62c36d0 | 533 | |
gsfan | 23:a783c62c36d0 | 534 | case 0x09: // ping |
gsfan | 23:a783c62c36d0 | 535 | _gs_putc(0x8a); // pong |
gsfan | 23:a783c62c36d0 | 536 | _gs_putc(0x04); |
gsfan | 23:a783c62c36d0 | 537 | for (i = 0; i < _httpd[cid].len; i ++) { |
gsfan | 23:a783c62c36d0 | 538 | _gs_putc(_httpd[cid].buf[i]); |
gsfan | 23:a783c62c36d0 | 539 | } |
gsfan | 23:a783c62c36d0 | 540 | break; |
gsfan | 23:a783c62c36d0 | 541 | |
gsfan | 23:a783c62c36d0 | 542 | case 0x0a: // pong |
gsfan | 23:a783c62c36d0 | 543 | break; |
gsfan | 23:a783c62c36d0 | 544 | } |
gsfan | 23:a783c62c36d0 | 545 | _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET; |
gsfan | 23:a783c62c36d0 | 546 | _httpd[cid].len = 0; |
gsfan | 23:a783c62c36d0 | 547 | _httpd[cid].length = 0; |
gsfan | 23:a783c62c36d0 | 548 | } |
gsfan | 23:a783c62c36d0 | 549 | } // while |
gsfan | 23:a783c62c36d0 | 550 | } |
gsfan | 23:a783c62c36d0 | 551 | |
gsfan | 23:a783c62c36d0 | 552 | int GSwifi::send_websocket (int cid, const char *buf, int len) { |
gsfan | 23:a783c62c36d0 | 553 | int r; |
gsfan | 23:a783c62c36d0 | 554 | char tmp[10]; |
gsfan | 23:a783c62c36d0 | 555 | |
gsfan | 23:a783c62c36d0 | 556 | tmp[0] = 0x81; // single, text frame |
gsfan | 23:a783c62c36d0 | 557 | if (len < 126) { |
gsfan | 23:a783c62c36d0 | 558 | tmp[1] = len; |
gsfan | 23:a783c62c36d0 | 559 | r = send(cid, tmp, 2); |
gsfan | 23:a783c62c36d0 | 560 | } else { |
gsfan | 23:a783c62c36d0 | 561 | tmp[1] = 126; |
gsfan | 23:a783c62c36d0 | 562 | tmp[2] = (len >> 8) & 0xff; |
gsfan | 23:a783c62c36d0 | 563 | tmp[3] = len & 0xff; |
gsfan | 23:a783c62c36d0 | 564 | r = send(cid, tmp, 4); |
gsfan | 23:a783c62c36d0 | 565 | } |
gsfan | 23:a783c62c36d0 | 566 | if (r == 0) { |
gsfan | 23:a783c62c36d0 | 567 | r = send(cid, buf, len); |
gsfan | 23:a783c62c36d0 | 568 | } |
gsfan | 23:a783c62c36d0 | 569 | return r; |
gsfan | 23:a783c62c36d0 | 570 | } |
gsfan | 23:a783c62c36d0 | 571 | |
gsfan | 23:a783c62c36d0 | 572 | void GSwifi::send_websocket_accept (int cid) { |
gsfan | 23:a783c62c36d0 | 573 | char buf[100], buf2[20]; |
gsfan | 23:a783c62c36d0 | 574 | |
gsfan | 23:a783c62c36d0 | 575 | DBG("websocket accept: %d\r\n", cid); |
gsfan | 23:a783c62c36d0 | 576 | |
gsfan | 23:a783c62c36d0 | 577 | send(cid, "HTTP/1.1 101 Switching Protocols\r\n", 34); |
gsfan | 23:a783c62c36d0 | 578 | send(cid, "Upgrade: websocket\r\n", 20); |
gsfan | 23:a783c62c36d0 | 579 | send(cid, "Connection: Upgrade\r\n", 21); |
gsfan | 23:a783c62c36d0 | 580 | |
gsfan | 23:a783c62c36d0 | 581 | send(cid, "Sec-WebSocket-Accept: ", 22); |
gsfan | 23:a783c62c36d0 | 582 | strcpy(buf, _httpd[cid].websocket_key); |
gsfan | 23:a783c62c36d0 | 583 | strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); |
gsfan | 23:a783c62c36d0 | 584 | sha1(buf, strlen(buf), buf2); |
gsfan | 23:a783c62c36d0 | 585 | base64encode(buf2, 20, buf, sizeof(buf)); |
gsfan | 23:a783c62c36d0 | 586 | send(cid, buf, strlen(buf)); |
gsfan | 23:a783c62c36d0 | 587 | send(cid, "\r\n", 2); |
gsfan | 23:a783c62c36d0 | 588 | // send(cid, "Sec-WebSocket-Protocol: chat\r\n", 30); |
gsfan | 23:a783c62c36d0 | 589 | send(cid, "\r\n", 2); |
gsfan | 23:a783c62c36d0 | 590 | LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); |
gsfan | 23:a783c62c36d0 | 591 | LOG("%s %s %d 101 - %s\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, buf); |
gsfan | 23:a783c62c36d0 | 592 | } |
gsfan | 20:151b5a4fdd29 | 593 | #endif |
gsfan | 23:a783c62c36d0 | 594 | |
gsfan | 23:a783c62c36d0 | 595 | #endif |