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:
Wed Dec 18 01:29:43 2013 +0000
Revision:
43:0b5e2727e020
Parent:
35:515ec79792d3
fix reconnect

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