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 gs fan

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/

/media/uploads/gsfan/gs_im_002.jpg /media/uploads/gsfan/gs1011m_2.jpg

ゲインスパン Wi-Fi モジュール ライブラリ

ゲインスパン社の低電力 Wi-Fiモジュール(無線LAN) GS1011 シリーズ用のライブラリです。

解説: http://mbed.org/users/gsfan/notebook/gainspan_wifi/

Committer:
gsfan
Date:
Tue Feb 26 06:05:11 2013 +0000
Revision:
31:0abdc584823d
Parent:
29:1c4419512941
Child:
35:515ec79792d3
bug fix

Who changed what in which revision?

UserRevisionLine numberNew 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 31:0abdc584823d 32 static const struct {
gsfan 31:0abdc584823d 33 char ext[5];
gsfan 31:0abdc584823d 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 26:b347ee3a1087 62 newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, this, &GSwifi::poll_httpd);
gsfan 18:4b97804c37d1 63 return _cid;
gsfan 18:4b97804c37d1 64 }
gsfan 18:4b97804c37d1 65
gsfan 18:4b97804c37d1 66 void GSwifi::poll_httpd (int cid, int len) {
gsfan 18:4b97804c37d1 67 int i, j, flg = 0;
gsfan 18:4b97804c37d1 68 char c;
gsfan 18:4b97804c37d1 69
gsfan 18:4b97804c37d1 70 if (len == 0) {
gsfan 23:a783c62c36d0 71 // start request
gsfan 23:a783c62c36d0 72 _httpd[cid].mode = GSHTTPDMODE_REQUEST;
gsfan 18:4b97804c37d1 73 _httpd[cid].len = 0;
gsfan 18:4b97804c37d1 74 _httpd[cid].keepalive = 0;
gsfan 23:a783c62c36d0 75 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 76 _httpd[cid].websocket = 0;
gsfan 23:a783c62c36d0 77 #endif
gsfan 18:4b97804c37d1 78 return;
gsfan 18:4b97804c37d1 79 }
gsfan 18:4b97804c37d1 80
gsfan 23:a783c62c36d0 81 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 82 if (_httpd[cid].mode >= GSHTTPDMODE_WEBSOCKET) {
gsfan 23:a783c62c36d0 83 poll_websocket(cid, len);
gsfan 23:a783c62c36d0 84 return;
gsfan 23:a783c62c36d0 85 }
gsfan 23:a783c62c36d0 86 #endif
gsfan 23:a783c62c36d0 87
gsfan 26:b347ee3a1087 88 while (_gs_sock[cid].connect && (! _gs_sock[cid].data->isEmpty())) {
gsfan 18:4b97804c37d1 89 flg = 0;
gsfan 18:4b97804c37d1 90 if (_httpd[cid].buf == NULL) {
gsfan 18:4b97804c37d1 91 _httpd[cid].buf = new char[HTTPD_BUF_SIZE];
gsfan 18:4b97804c37d1 92 }
gsfan 23:a783c62c36d0 93 // get 1 line
gsfan 18:4b97804c37d1 94 for (j = 0; j < len; j ++) {
gsfan 25:f6e5622d2930 95 _gs_sock[cid].data->dequeue(&c);
gsfan 18:4b97804c37d1 96 if (c == '\r') continue;
gsfan 23:a783c62c36d0 97 if (c == '\n' && _httpd[cid].mode != GSHTTPDMODE_BODY) break;
gsfan 18:4b97804c37d1 98
gsfan 18:4b97804c37d1 99 if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) {
gsfan 18:4b97804c37d1 100 _httpd[cid].buf[_httpd[cid].len] = c;
gsfan 18:4b97804c37d1 101 }
gsfan 18:4b97804c37d1 102 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 103 if (_httpd[cid].mode == GSHTTPDMODE_BODY && _httpd[cid].len >= _httpd[cid].length) break; // end of body
gsfan 18:4b97804c37d1 104 }
gsfan 23:a783c62c36d0 105 if (j >= len) return; // continue
gsfan 18:4b97804c37d1 106 if (_httpd[cid].len < HTTPD_BUF_SIZE) {
gsfan 18:4b97804c37d1 107 _httpd[cid].buf[_httpd[cid].len] = 0;
gsfan 20:151b5a4fdd29 108 DBG("httpd %d: %d %s (%d)\r\n", cid, _httpd[cid].mode, _httpd[cid].buf, _httpd[cid].len);
gsfan 18:4b97804c37d1 109 }
gsfan 18:4b97804c37d1 110
gsfan 23:a783c62c36d0 111 // parse
gsfan 18:4b97804c37d1 112 switch (_httpd[cid].mode) {
gsfan 23:a783c62c36d0 113 case GSHTTPDMODE_REQUEST:
gsfan 23:a783c62c36d0 114 if (strnicmp(_httpd[cid].buf, "GET ", 4) == 0) {
gsfan 19:cad912f5a6ba 115 _httpd[cid].type = GSPROT_HTTPGET;
gsfan 18:4b97804c37d1 116 j = 4;
gsfan 18:4b97804c37d1 117 } else
gsfan 23:a783c62c36d0 118 if (strnicmp(_httpd[cid].buf, "POST ", 5) == 0) {
gsfan 19:cad912f5a6ba 119 _httpd[cid].type = GSPROT_HTTPPOST;
gsfan 18:4b97804c37d1 120 j = 5;
gsfan 18:4b97804c37d1 121 } else {
gsfan 23:a783c62c36d0 122 _httpd[cid].mode = GSHTTPDMODE_ERROR;
gsfan 18:4b97804c37d1 123 break;
gsfan 18:4b97804c37d1 124 }
gsfan 18:4b97804c37d1 125
gsfan 23:a783c62c36d0 126 // get uri
gsfan 18:4b97804c37d1 127 for (i = j; i < _httpd[cid].len; i ++) {
gsfan 18:4b97804c37d1 128 if (_httpd[cid].buf[i] == ' ') break;
gsfan 18:4b97804c37d1 129 }
gsfan 18:4b97804c37d1 130 i = i - j;
gsfan 18:4b97804c37d1 131 if (i) {
gsfan 18:4b97804c37d1 132 if (_httpd[cid].uri == NULL) {
gsfan 18:4b97804c37d1 133 _httpd[cid].uri = new char[HTTPD_URI_SIZE];
gsfan 18:4b97804c37d1 134 }
gsfan 18:4b97804c37d1 135 strncpy(_httpd[cid].uri, &_httpd[cid].buf[j], i);
gsfan 18:4b97804c37d1 136 _httpd[cid].uri[i] = 0;
gsfan 18:4b97804c37d1 137 }
gsfan 23:a783c62c36d0 138 _httpd[cid].mode = GSHTTPDMODE_HEAD;
gsfan 18:4b97804c37d1 139 _httpd[cid].length = 0;
gsfan 18:4b97804c37d1 140 DBG("uri: %s\r\n", _httpd[cid].uri);
gsfan 18:4b97804c37d1 141 break;
gsfan 18:4b97804c37d1 142
gsfan 23:a783c62c36d0 143 case GSHTTPDMODE_HEAD:
gsfan 18:4b97804c37d1 144 if (_httpd[cid].len == 0) {
gsfan 23:a783c62c36d0 145 // blank line (end of header)
gsfan 23:a783c62c36d0 146 _httpd[cid].mode = GSHTTPDMODE_BODY;
gsfan 19:cad912f5a6ba 147 if (_httpd[cid].length == 0) flg = 1; // no body
gsfan 23:a783c62c36d0 148 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 149 if (_httpd[cid].websocket && _httpd[cid].websocket_key) {
gsfan 23:a783c62c36d0 150 // enter websocket
gsfan 23:a783c62c36d0 151 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET;
gsfan 23:a783c62c36d0 152 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 153 flg = 1;
gsfan 23:a783c62c36d0 154 }
gsfan 23:a783c62c36d0 155 #endif
gsfan 18:4b97804c37d1 156 } else
gsfan 23:a783c62c36d0 157 if (strnicmp(_httpd[cid].buf, "Content-Length: ", 16) == 0) {
gsfan 18:4b97804c37d1 158 _httpd[cid].length = atoi(&_httpd[cid].buf[16]);
gsfan 18:4b97804c37d1 159 } else
gsfan 23:a783c62c36d0 160 if (strnicmp(_httpd[cid].buf, "Connection: Keep-Alive", 22) == 0) {
gsfan 18:4b97804c37d1 161 if (! _httpd[cid].keepalive) {
gsfan 18:4b97804c37d1 162 _httpd[cid].keepalive = HTTPD_KEEPALIVE;
gsfan 18:4b97804c37d1 163 }
gsfan 23:a783c62c36d0 164 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 165 } else
gsfan 23:a783c62c36d0 166 if (strnicmp(_httpd[cid].buf, "Upgrade: websocket", 18) == 0) {
gsfan 23:a783c62c36d0 167 if (! _httpd[cid].websocket) _httpd[cid].websocket = 1;
gsfan 23:a783c62c36d0 168 } else
gsfan 23:a783c62c36d0 169 if (strnicmp(_httpd[cid].buf, "Sec-WebSocket-Version: ", 23) == 0) {
gsfan 23:a783c62c36d0 170 _httpd[cid].websocket = atoi(&_httpd[cid].buf[23]);
gsfan 23:a783c62c36d0 171 } else
gsfan 23:a783c62c36d0 172 if (strnicmp(_httpd[cid].buf, "Sec-WebSocket-Key: ", 19) == 0) {
gsfan 23:a783c62c36d0 173 if (_httpd[cid].websocket_key == NULL) {
gsfan 23:a783c62c36d0 174 _httpd[cid].websocket_key = new char[30];
gsfan 23:a783c62c36d0 175 }
gsfan 23:a783c62c36d0 176 strncpy(_httpd[cid].websocket_key, &_httpd[cid].buf[19], 30);
gsfan 23:a783c62c36d0 177 #endif
gsfan 18:4b97804c37d1 178 }
gsfan 18:4b97804c37d1 179 break;
gsfan 18:4b97804c37d1 180
gsfan 23:a783c62c36d0 181 case GSHTTPDMODE_BODY:
gsfan 18:4b97804c37d1 182 if (_httpd[cid].len >= _httpd[cid].length) {
gsfan 18:4b97804c37d1 183 DBG("body: %s\r\n", _httpd[cid].buf);
gsfan 18:4b97804c37d1 184 flg = 1;
gsfan 18:4b97804c37d1 185 }
gsfan 18:4b97804c37d1 186 break;
gsfan 23:a783c62c36d0 187
gsfan 18:4b97804c37d1 188 }
gsfan 18:4b97804c37d1 189
gsfan 23:a783c62c36d0 190 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 191 if (flg && _httpd[cid].mode == GSHTTPDMODE_WEBSOCKET) {
gsfan 23:a783c62c36d0 192 // websocket
gsfan 29:1c4419512941 193 i = get_handler(_httpd[cid].uri);
gsfan 29:1c4419512941 194 if (i >= 0 && _handler[i].onHttpCgi) {
gsfan 29:1c4419512941 195 _httpd[cid].host = _gs_sock[cid].host;
gsfan 29:1c4419512941 196 _httpd[cid].file = NULL;
gsfan 29:1c4419512941 197 _httpd[cid].query = NULL;
gsfan 24:5c350ae2e703 198
gsfan 29:1c4419512941 199 send_websocket_accept(cid);
gsfan 29:1c4419512941 200 } else {
gsfan 29:1c4419512941 201 // not found
gsfan 29:1c4419512941 202 send_httpd_error(cid, 403);
gsfan 29:1c4419512941 203 }
gsfan 24:5c350ae2e703 204 break; // exit while
gsfan 23:a783c62c36d0 205
gsfan 23:a783c62c36d0 206 } else
gsfan 23:a783c62c36d0 207 #endif
gsfan 18:4b97804c37d1 208 if (flg) {
gsfan 18:4b97804c37d1 209 // http request
gsfan 18:4b97804c37d1 210 _httpd[cid].buf[_httpd[cid].len] = 0;
gsfan 19:cad912f5a6ba 211
gsfan 23:a783c62c36d0 212 i = get_handler(_httpd[cid].uri);
gsfan 23:a783c62c36d0 213 if (i >= 0) {
gsfan 23:a783c62c36d0 214 _httpd[cid].host = _gs_sock[cid].host;
gsfan 23:a783c62c36d0 215 j = strlen(_handler[i].uri);
gsfan 23:a783c62c36d0 216 _httpd[cid].file = &_httpd[cid].uri[j];
gsfan 23:a783c62c36d0 217 _httpd[cid].query = NULL;
gsfan 23:a783c62c36d0 218 for (; j < strlen(_httpd[cid].uri); j ++) {
gsfan 23:a783c62c36d0 219 if (_httpd[cid].uri[j] == '?') {
gsfan 23:a783c62c36d0 220 // query string
gsfan 23:a783c62c36d0 221 _httpd[cid].uri[j] = 0;
gsfan 23:a783c62c36d0 222 _httpd[cid].query = &_httpd[cid].uri[j + 1];
gsfan 23:a783c62c36d0 223 break;
gsfan 18:4b97804c37d1 224 }
gsfan 18:4b97804c37d1 225 }
gsfan 23:a783c62c36d0 226
gsfan 23:a783c62c36d0 227 if (_handler[i].dir) {
gsfan 23:a783c62c36d0 228 // file
gsfan 23:a783c62c36d0 229 httpd_request(cid, &_httpd[cid], _handler[i].dir);
gsfan 23:a783c62c36d0 230 flg = 1;
gsfan 23:a783c62c36d0 231 } else
gsfan 23:a783c62c36d0 232 if (_handler[i].onHttpCgi) {
gsfan 23:a783c62c36d0 233 // cgi
gsfan 23:a783c62c36d0 234 _handler[i].onHttpCgi(cid, &_httpd[cid]);
gsfan 23:a783c62c36d0 235 _httpd[cid].keepalive = 0;
gsfan 23:a783c62c36d0 236 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 237 LOG("%s %s %d 200 -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length);
gsfan 23:a783c62c36d0 238 flg = 1;
gsfan 23:a783c62c36d0 239 }
gsfan 23:a783c62c36d0 240 } else {
gsfan 19:cad912f5a6ba 241 // not found
gsfan 18:4b97804c37d1 242 send_httpd_error(cid, 403);
gsfan 18:4b97804c37d1 243 }
gsfan 18:4b97804c37d1 244
gsfan 18:4b97804c37d1 245 if (_httpd[cid].keepalive) {
gsfan 23:a783c62c36d0 246 _httpd[cid].mode = GSHTTPDMODE_REQUEST;
gsfan 18:4b97804c37d1 247 _httpd[cid].len = 0;
gsfan 18:4b97804c37d1 248 _httpd[cid].length = 0;
gsfan 18:4b97804c37d1 249 _httpd[cid].keepalive --;
gsfan 18:4b97804c37d1 250 } else {
gsfan 18:4b97804c37d1 251 close(cid);
gsfan 18:4b97804c37d1 252 }
gsfan 18:4b97804c37d1 253 }
gsfan 18:4b97804c37d1 254
gsfan 23:a783c62c36d0 255 if (_httpd[cid].mode == GSHTTPDMODE_ERROR) {
gsfan 18:4b97804c37d1 256 send_httpd_error(cid, 400);
gsfan 18:4b97804c37d1 257 }
gsfan 18:4b97804c37d1 258
gsfan 18:4b97804c37d1 259 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 260 } // while
gsfan 23:a783c62c36d0 261 }
gsfan 23:a783c62c36d0 262
gsfan 23:a783c62c36d0 263 int GSwifi::get_handler (char *uri) {
gsfan 23:a783c62c36d0 264 int i, j;
gsfan 23:a783c62c36d0 265
gsfan 23:a783c62c36d0 266 for (i = 0; i < _handler_count; i ++) {
gsfan 23:a783c62c36d0 267 j = strlen(_handler[i].uri);
gsfan 23:a783c62c36d0 268 if (strncmp(uri, _handler[i].uri, j) == NULL) {
gsfan 23:a783c62c36d0 269 // found
gsfan 23:a783c62c36d0 270 return i;
gsfan 23:a783c62c36d0 271 }
gsfan 23:a783c62c36d0 272 }
gsfan 23:a783c62c36d0 273 return -1;
gsfan 18:4b97804c37d1 274 }
gsfan 18:4b97804c37d1 275
gsfan 19:cad912f5a6ba 276 int GSwifi::httpd_request (int cid, GS_httpd *gshttpd, char *dir) {
gsfan 18:4b97804c37d1 277 FILE *fp;
gsfan 20:151b5a4fdd29 278 int i, len;
gsfan 20:151b5a4fdd29 279 char buf[HTTPD_BUF_SIZE];
gsfan 20:151b5a4fdd29 280 char file[HTTPD_URI_SIZE];
gsfan 18:4b97804c37d1 281
gsfan 20:151b5a4fdd29 282 strcpy(file, dir);
gsfan 20:151b5a4fdd29 283 strcat(file, gshttpd->file);
gsfan 20:151b5a4fdd29 284 if (file[strlen(file) - 1] == '/') {
gsfan 24:5c350ae2e703 285 strcat(file, "index.html");
gsfan 18:4b97804c37d1 286 }
gsfan 20:151b5a4fdd29 287 DBG("file: %s\r\n", file);
gsfan 18:4b97804c37d1 288
gsfan 20:151b5a4fdd29 289 fp = fopen(file, "r");
gsfan 18:4b97804c37d1 290 if (fp) {
gsfan 19:cad912f5a6ba 291 send(cid, "HTTP/1.1 200 OK\r\n", 17);
gsfan 18:4b97804c37d1 292 {
gsfan 19:cad912f5a6ba 293 // file size
gsfan 20:151b5a4fdd29 294 i = ftell(fp);
gsfan 18:4b97804c37d1 295 fseek(fp, 0, SEEK_END);
gsfan 20:151b5a4fdd29 296 len = ftell(fp);
gsfan 20:151b5a4fdd29 297 fseek(fp, i, SEEK_SET);
gsfan 18:4b97804c37d1 298 }
gsfan 20:151b5a4fdd29 299 sprintf(buf, "Content-Length: %d\r\n", len);
gsfan 18:4b97804c37d1 300 send(cid, buf, strlen(buf));
gsfan 20:151b5a4fdd29 301 sprintf(buf, "Content-Type: %s\r\n", mimetype(file));
gsfan 18:4b97804c37d1 302 send(cid, buf, strlen(buf));
gsfan 19:cad912f5a6ba 303 if (gshttpd->keepalive) {
gsfan 18:4b97804c37d1 304 strcpy(buf, "Connection: Keep-Alive\r\n");
gsfan 18:4b97804c37d1 305 } else {
gsfan 18:4b97804c37d1 306 strcpy(buf, "Connection: close\r\n");
gsfan 18:4b97804c37d1 307 }
gsfan 18:4b97804c37d1 308 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 309 strcpy(buf, "Server: GSwifi httpd\r\n");
gsfan 18:4b97804c37d1 310 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 311 send(cid, "\r\n", 2);
gsfan 18:4b97804c37d1 312
gsfan 18:4b97804c37d1 313 for (;;) {
gsfan 18:4b97804c37d1 314 i = fread(buf, sizeof(char), sizeof(buf), fp);
gsfan 20:151b5a4fdd29 315 if (i <= 0) break;
gsfan 22:9b077e2823ce 316 if (! _gs_sock[cid].connect) break;
gsfan 18:4b97804c37d1 317 send(cid, buf, i);
gsfan 20:151b5a4fdd29 318 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
gsfan 18:4b97804c37d1 319 if (feof(fp)) break;
gsfan 20:151b5a4fdd29 320 #endif
gsfan 18:4b97804c37d1 321 }
gsfan 18:4b97804c37d1 322 fclose(fp);
gsfan 20:151b5a4fdd29 323 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 324 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 325 return 0;
gsfan 18:4b97804c37d1 326 }
gsfan 18:4b97804c37d1 327
gsfan 18:4b97804c37d1 328 send_httpd_error(cid, 404);
gsfan 18:4b97804c37d1 329 return -1;
gsfan 18:4b97804c37d1 330 }
gsfan 18:4b97804c37d1 331
gsfan 19:cad912f5a6ba 332 char *GSwifi::mimetype (char *file) {
gsfan 19:cad912f5a6ba 333 int i, j;
gsfan 19:cad912f5a6ba 334
gsfan 20:151b5a4fdd29 335 DBG("<%s>\r\n", file);
gsfan 19:cad912f5a6ba 336 for (i = 0; i < MIMETABLE_NUM; i ++) {
gsfan 19:cad912f5a6ba 337 j = strlen(mimetable[i].ext);
gsfan 25:f6e5622d2930 338 if (file[strlen(file) - j - 1] == '.' &&
gsfan 31:0abdc584823d 339 strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) {
gsfan 29:1c4419512941 340 return (char*)mimetable[i].type;
gsfan 19:cad912f5a6ba 341 }
gsfan 19:cad912f5a6ba 342 }
gsfan 29:1c4419512941 343 return (char*)mimetable[0].type;
gsfan 19:cad912f5a6ba 344 }
gsfan 19:cad912f5a6ba 345
gsfan 31:0abdc584823d 346 int GSwifi::strnicmp (const char *p1, const char *p2, int n) {
gsfan 25:f6e5622d2930 347 int i, r = -1;
gsfan 23:a783c62c36d0 348 char c1, c2;
gsfan 23:a783c62c36d0 349
gsfan 23:a783c62c36d0 350 for (i = 0; i < n; i ++) {
gsfan 23:a783c62c36d0 351 c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i];
gsfan 23:a783c62c36d0 352 c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i];
gsfan 23:a783c62c36d0 353 r = c1 - c2;
gsfan 23:a783c62c36d0 354 if (r) break;
gsfan 23:a783c62c36d0 355 }
gsfan 23:a783c62c36d0 356 return r;
gsfan 23:a783c62c36d0 357 }
gsfan 23:a783c62c36d0 358
gsfan 18:4b97804c37d1 359 void GSwifi::send_httpd_error (int cid, int err) {
gsfan 18:4b97804c37d1 360 char buf[100], msg[30];
gsfan 18:4b97804c37d1 361
gsfan 18:4b97804c37d1 362 switch (err) {
gsfan 18:4b97804c37d1 363 case 400:
gsfan 18:4b97804c37d1 364 strcpy(msg, "Bad Request");
gsfan 18:4b97804c37d1 365 break;
gsfan 18:4b97804c37d1 366 case 403:
gsfan 18:4b97804c37d1 367 strcpy(msg, "Forbidden");
gsfan 18:4b97804c37d1 368 break;
gsfan 18:4b97804c37d1 369 case 404:
gsfan 18:4b97804c37d1 370 strcpy(msg, "Not Found");
gsfan 18:4b97804c37d1 371 break;
gsfan 18:4b97804c37d1 372 case 500:
gsfan 18:4b97804c37d1 373 default:
gsfan 18:4b97804c37d1 374 strcpy(msg, "Internal Server Error");
gsfan 18:4b97804c37d1 375 break;
gsfan 18:4b97804c37d1 376 }
gsfan 18:4b97804c37d1 377 DBG("httpd error: %d %d %s\r\n", cid, err, msg);
gsfan 18:4b97804c37d1 378
gsfan 18:4b97804c37d1 379 sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg);
gsfan 18:4b97804c37d1 380 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 381 strcpy(buf, "Content-Type: text/html\r\n");
gsfan 18:4b97804c37d1 382 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 383 send(cid, "\r\n", 2);
gsfan 18:4b97804c37d1 384
gsfan 18:4b97804c37d1 385 sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg);
gsfan 18:4b97804c37d1 386 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 387 sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg);
gsfan 18:4b97804c37d1 388 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 389 close(cid);
gsfan 20:151b5a4fdd29 390 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 391 LOG("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err);
gsfan 18:4b97804c37d1 392 }
gsfan 18:4b97804c37d1 393
gsfan 19:cad912f5a6ba 394 int GSwifi::attach_httpd (const char *uri, const char *dir) {
gsfan 18:4b97804c37d1 395 if (_handler_count < HTTPD_HANDLE) {
gsfan 18:4b97804c37d1 396 _handler[_handler_count].uri = new char[strlen(uri) + 1];
gsfan 18:4b97804c37d1 397 strcpy(_handler[_handler_count].uri, uri);
gsfan 18:4b97804c37d1 398 _handler[_handler_count].dir = new char[strlen(dir) + 1];
gsfan 18:4b97804c37d1 399 strcpy(_handler[_handler_count].dir, dir);
gsfan 18:4b97804c37d1 400 _handler[_handler_count].onHttpCgi = NULL;
gsfan 18:4b97804c37d1 401 _handler_count ++;
gsfan 18:4b97804c37d1 402 return 0;
gsfan 18:4b97804c37d1 403 } else {
gsfan 18:4b97804c37d1 404 return -1;
gsfan 18:4b97804c37d1 405 }
gsfan 18:4b97804c37d1 406 }
gsfan 18:4b97804c37d1 407
gsfan 19:cad912f5a6ba 408 int GSwifi::attach_httpd (const char *uri, onHttpdCgiFunc ponHttpCgi) {
gsfan 18:4b97804c37d1 409 if (_handler_count < HTTPD_HANDLE) {
gsfan 18:4b97804c37d1 410 _handler[_handler_count].uri = new char[strlen(uri) + 1];
gsfan 18:4b97804c37d1 411 strcpy(_handler[_handler_count].uri, uri);
gsfan 18:4b97804c37d1 412 _handler[_handler_count].dir = NULL;
gsfan 18:4b97804c37d1 413 _handler[_handler_count].onHttpCgi = ponHttpCgi;
gsfan 18:4b97804c37d1 414 _handler_count ++;
gsfan 18:4b97804c37d1 415 return 0;
gsfan 18:4b97804c37d1 416 } else {
gsfan 18:4b97804c37d1 417 return -1;
gsfan 18:4b97804c37d1 418 }
gsfan 18:4b97804c37d1 419 }
gsfan 20:151b5a4fdd29 420
gsfan 23:a783c62c36d0 421 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 422 void GSwifi::poll_websocket (int cid, int len) {
gsfan 23:a783c62c36d0 423 int i, j, flg;
gsfan 23:a783c62c36d0 424 unsigned char c;
gsfan 23:a783c62c36d0 425
gsfan 26:b347ee3a1087 426 while (_gs_sock[cid].connect && (! _gs_sock[cid].data->isEmpty())) {
gsfan 23:a783c62c36d0 427 flg = 0;
gsfan 23:a783c62c36d0 428 // get 1 line
gsfan 23:a783c62c36d0 429 for (j = 0; j < len; j ++) {
gsfan 25:f6e5622d2930 430 _gs_sock[cid].data->dequeue((char*)&c);
gsfan 23:a783c62c36d0 431 // DBG("_%c", c);
gsfan 23:a783c62c36d0 432
gsfan 23:a783c62c36d0 433 switch (_httpd[cid].mode) {
gsfan 23:a783c62c36d0 434 case GSHTTPDMODE_WEBSOCKET:
gsfan 23:a783c62c36d0 435 if (_httpd[cid].len == 0) {
gsfan 26:b347ee3a1087 436 // flag
gsfan 23:a783c62c36d0 437 _httpd[cid].type = c & 0x0f;
gsfan 23:a783c62c36d0 438 _httpd[cid].websocket_flg = c << 8;
gsfan 23:a783c62c36d0 439 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 440 } else
gsfan 23:a783c62c36d0 441 if (_httpd[cid].len == 1) {
gsfan 26:b347ee3a1087 442 // length 7bit
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 26:b347ee3a1087 466 // end
gsfan 23:a783c62c36d0 467 _httpd[cid].length = (_httpd[cid].length << 8) | c;
gsfan 23:a783c62c36d0 468 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 469 if (_httpd[cid].websocket_flg & 0x0080) {
gsfan 23:a783c62c36d0 470 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK;
gsfan 23:a783c62c36d0 471 } else {
gsfan 23:a783c62c36d0 472 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY;
gsfan 23:a783c62c36d0 473 }
gsfan 23:a783c62c36d0 474 DBG("ws length2 %d\r\n", _httpd[cid].length);
gsfan 23:a783c62c36d0 475 }
gsfan 23:a783c62c36d0 476 }
gsfan 23:a783c62c36d0 477 break;
gsfan 23:a783c62c36d0 478
gsfan 23:a783c62c36d0 479 case GSHTTPDMODE_WEBSOCKET_MASK:
gsfan 26:b347ee3a1087 480 // masking key
gsfan 23:a783c62c36d0 481 _httpd[cid].websocket_mask[_httpd[cid].len] = c;
gsfan 23:a783c62c36d0 482 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 483 if (_httpd[cid].len >= 4) {
gsfan 23:a783c62c36d0 484 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 485 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY;
gsfan 23:a783c62c36d0 486 DBG("ws mask\r\n");
gsfan 23:a783c62c36d0 487 }
gsfan 23:a783c62c36d0 488 break;
gsfan 23:a783c62c36d0 489
gsfan 23:a783c62c36d0 490 case GSHTTPDMODE_WEBSOCKET_BODY:
gsfan 26:b347ee3a1087 491 // payload
gsfan 23:a783c62c36d0 492 if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) {
gsfan 23:a783c62c36d0 493 if (_httpd[cid].websocket_flg & 0x0080) {
gsfan 26:b347ee3a1087 494 // un-mask
gsfan 23:a783c62c36d0 495 _httpd[cid].buf[_httpd[cid].len] = c ^ _httpd[cid].websocket_mask[_httpd[cid].len & 0x03];
gsfan 23:a783c62c36d0 496 } else {
gsfan 23:a783c62c36d0 497 _httpd[cid].buf[_httpd[cid].len] = c;
gsfan 23:a783c62c36d0 498 }
gsfan 23:a783c62c36d0 499 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 500 }
gsfan 23:a783c62c36d0 501 break;
gsfan 23:a783c62c36d0 502 }
gsfan 23:a783c62c36d0 503
gsfan 23:a783c62c36d0 504 if (_httpd[cid].mode == GSHTTPDMODE_WEBSOCKET_BODY && _httpd[cid].len >= _httpd[cid].length) {
gsfan 23:a783c62c36d0 505 flg = 1;
gsfan 23:a783c62c36d0 506 break;
gsfan 23:a783c62c36d0 507 }
gsfan 23:a783c62c36d0 508 }
gsfan 23:a783c62c36d0 509 if (j >= len) return; // continue
gsfan 23:a783c62c36d0 510 if (_httpd[cid].len < HTTPD_BUF_SIZE) {
gsfan 23:a783c62c36d0 511 _httpd[cid].buf[_httpd[cid].len] = 0;
gsfan 23:a783c62c36d0 512 DBG("websocket %d: (%d)\r\n", cid, _httpd[cid].len);
gsfan 23:a783c62c36d0 513 }
gsfan 23:a783c62c36d0 514
gsfan 26:b347ee3a1087 515 if (flg) {
gsfan 26:b347ee3a1087 516 // websocket request
gsfan 26:b347ee3a1087 517 DBG("ws type %d\r\n", _httpd[cid].type);
gsfan 26:b347ee3a1087 518 switch (_httpd[cid].type) {
gsfan 26:b347ee3a1087 519 case 0x00: // continuation
gsfan 26:b347ee3a1087 520 case 0x01: // text
gsfan 26:b347ee3a1087 521 case 0x02: // binary
gsfan 26:b347ee3a1087 522 i = get_handler(_httpd[cid].uri);
gsfan 26:b347ee3a1087 523 if (i >= 0) {
gsfan 26:b347ee3a1087 524 if (_handler[i].onHttpCgi) {
gsfan 26:b347ee3a1087 525 // cgi
gsfan 26:b347ee3a1087 526 _handler[i].onHttpCgi(cid, &_httpd[cid]);
gsfan 26:b347ee3a1087 527 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 26:b347ee3a1087 528 LOG("%s %s %d 200 -\r\n", "WEBSOCKET", _httpd[cid].uri, _httpd[cid].length);
gsfan 26:b347ee3a1087 529 flg = 1;
gsfan 26:b347ee3a1087 530 }
gsfan 23:a783c62c36d0 531 }
gsfan 26:b347ee3a1087 532 break;
gsfan 23:a783c62c36d0 533
gsfan 26:b347ee3a1087 534 case 0x08: // close
gsfan 26:b347ee3a1087 535 close(cid);
gsfan 26:b347ee3a1087 536 break;
gsfan 23:a783c62c36d0 537
gsfan 26:b347ee3a1087 538 case 0x09: // ping
gsfan 26:b347ee3a1087 539 {
gsfan 26:b347ee3a1087 540 char pong[_httpd[cid].len + 2];
gsfan 26:b347ee3a1087 541 pong[0] = 0x8a;
gsfan 26:b347ee3a1087 542 pong[1] = 0x04;
gsfan 26:b347ee3a1087 543 memcpy(&pong[2], _httpd[cid].buf, _httpd[cid].len);
gsfan 26:b347ee3a1087 544 send(cid, pong, _httpd[cid].len + 2);
gsfan 26:b347ee3a1087 545 }
gsfan 26:b347ee3a1087 546 break;
gsfan 26:b347ee3a1087 547
gsfan 26:b347ee3a1087 548 case 0x0a: // pong
gsfan 26:b347ee3a1087 549 break;
gsfan 26:b347ee3a1087 550 }
gsfan 26:b347ee3a1087 551 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET;
gsfan 26:b347ee3a1087 552 _httpd[cid].len = 0;
gsfan 26:b347ee3a1087 553 _httpd[cid].length = 0;
gsfan 23:a783c62c36d0 554 }
gsfan 23:a783c62c36d0 555 } // while
gsfan 23:a783c62c36d0 556 }
gsfan 23:a783c62c36d0 557
gsfan 23:a783c62c36d0 558 void GSwifi::send_websocket_accept (int cid) {
gsfan 23:a783c62c36d0 559 char buf[100], buf2[20];
gsfan 23:a783c62c36d0 560
gsfan 23:a783c62c36d0 561 DBG("websocket accept: %d\r\n", cid);
gsfan 23:a783c62c36d0 562
gsfan 23:a783c62c36d0 563 send(cid, "HTTP/1.1 101 Switching Protocols\r\n", 34);
gsfan 23:a783c62c36d0 564 send(cid, "Upgrade: websocket\r\n", 20);
gsfan 23:a783c62c36d0 565 send(cid, "Connection: Upgrade\r\n", 21);
gsfan 23:a783c62c36d0 566
gsfan 23:a783c62c36d0 567 send(cid, "Sec-WebSocket-Accept: ", 22);
gsfan 23:a783c62c36d0 568 strcpy(buf, _httpd[cid].websocket_key);
gsfan 23:a783c62c36d0 569 strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
gsfan 23:a783c62c36d0 570 sha1(buf, strlen(buf), buf2);
gsfan 23:a783c62c36d0 571 base64encode(buf2, 20, buf, sizeof(buf));
gsfan 23:a783c62c36d0 572 send(cid, buf, strlen(buf));
gsfan 23:a783c62c36d0 573 send(cid, "\r\n", 2);
gsfan 23:a783c62c36d0 574 // send(cid, "Sec-WebSocket-Protocol: chat\r\n", 30);
gsfan 23:a783c62c36d0 575 send(cid, "\r\n", 2);
gsfan 23:a783c62c36d0 576 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 577 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 578 }
gsfan 20:151b5a4fdd29 579 #endif
gsfan 23:a783c62c36d0 580
gsfan 23:a783c62c36d0 581 #endif