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:
Fri Feb 22 01:05:10 2013 +0000
Revision:
26:b347ee3a1087
Parent:
25:f6e5622d2930
Child:
29:1c4419512941
Heavily modified

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 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 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 24:5c350ae2e703 193 _httpd[cid].host = _gs_sock[cid].host;
gsfan 24:5c350ae2e703 194 j = strlen(_handler[i].uri);
gsfan 24:5c350ae2e703 195 _httpd[cid].file = &_httpd[cid].uri[j];
gsfan 24:5c350ae2e703 196 _httpd[cid].query = NULL;
gsfan 24:5c350ae2e703 197
gsfan 23:a783c62c36d0 198 send_websocket_accept(cid);
gsfan 24:5c350ae2e703 199 break; // exit while
gsfan 23:a783c62c36d0 200
gsfan 23:a783c62c36d0 201 } else
gsfan 23:a783c62c36d0 202 #endif
gsfan 18:4b97804c37d1 203 if (flg) {
gsfan 18:4b97804c37d1 204 // http request
gsfan 18:4b97804c37d1 205 _httpd[cid].buf[_httpd[cid].len] = 0;
gsfan 19:cad912f5a6ba 206
gsfan 23:a783c62c36d0 207 i = get_handler(_httpd[cid].uri);
gsfan 23:a783c62c36d0 208 if (i >= 0) {
gsfan 23:a783c62c36d0 209 _httpd[cid].host = _gs_sock[cid].host;
gsfan 23:a783c62c36d0 210 j = strlen(_handler[i].uri);
gsfan 23:a783c62c36d0 211 _httpd[cid].file = &_httpd[cid].uri[j];
gsfan 23:a783c62c36d0 212 _httpd[cid].query = NULL;
gsfan 23:a783c62c36d0 213 for (; j < strlen(_httpd[cid].uri); j ++) {
gsfan 23:a783c62c36d0 214 if (_httpd[cid].uri[j] == '?') {
gsfan 23:a783c62c36d0 215 // query string
gsfan 23:a783c62c36d0 216 _httpd[cid].uri[j] = 0;
gsfan 23:a783c62c36d0 217 _httpd[cid].query = &_httpd[cid].uri[j + 1];
gsfan 23:a783c62c36d0 218 break;
gsfan 18:4b97804c37d1 219 }
gsfan 18:4b97804c37d1 220 }
gsfan 23:a783c62c36d0 221
gsfan 23:a783c62c36d0 222 if (_handler[i].dir) {
gsfan 23:a783c62c36d0 223 // file
gsfan 23:a783c62c36d0 224 httpd_request(cid, &_httpd[cid], _handler[i].dir);
gsfan 23:a783c62c36d0 225 flg = 1;
gsfan 23:a783c62c36d0 226 } else
gsfan 23:a783c62c36d0 227 if (_handler[i].onHttpCgi) {
gsfan 23:a783c62c36d0 228 // cgi
gsfan 23:a783c62c36d0 229 _handler[i].onHttpCgi(cid, &_httpd[cid]);
gsfan 23:a783c62c36d0 230 _httpd[cid].keepalive = 0;
gsfan 23:a783c62c36d0 231 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 232 LOG("%s %s %d 200 -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length);
gsfan 23:a783c62c36d0 233 flg = 1;
gsfan 23:a783c62c36d0 234 }
gsfan 23:a783c62c36d0 235 } else {
gsfan 19:cad912f5a6ba 236 // not found
gsfan 18:4b97804c37d1 237 send_httpd_error(cid, 403);
gsfan 18:4b97804c37d1 238 }
gsfan 18:4b97804c37d1 239
gsfan 18:4b97804c37d1 240 if (_httpd[cid].keepalive) {
gsfan 23:a783c62c36d0 241 _httpd[cid].mode = GSHTTPDMODE_REQUEST;
gsfan 18:4b97804c37d1 242 _httpd[cid].len = 0;
gsfan 18:4b97804c37d1 243 _httpd[cid].length = 0;
gsfan 18:4b97804c37d1 244 _httpd[cid].keepalive --;
gsfan 18:4b97804c37d1 245 } else {
gsfan 18:4b97804c37d1 246 close(cid);
gsfan 18:4b97804c37d1 247 }
gsfan 18:4b97804c37d1 248 }
gsfan 18:4b97804c37d1 249
gsfan 23:a783c62c36d0 250 if (_httpd[cid].mode == GSHTTPDMODE_ERROR) {
gsfan 18:4b97804c37d1 251 send_httpd_error(cid, 400);
gsfan 18:4b97804c37d1 252 }
gsfan 18:4b97804c37d1 253
gsfan 18:4b97804c37d1 254 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 255 } // while
gsfan 23:a783c62c36d0 256 }
gsfan 23:a783c62c36d0 257
gsfan 23:a783c62c36d0 258 int GSwifi::get_handler (char *uri) {
gsfan 23:a783c62c36d0 259 int i, j;
gsfan 23:a783c62c36d0 260
gsfan 23:a783c62c36d0 261 for (i = 0; i < _handler_count; i ++) {
gsfan 23:a783c62c36d0 262 j = strlen(_handler[i].uri);
gsfan 23:a783c62c36d0 263 if (strncmp(uri, _handler[i].uri, j) == NULL) {
gsfan 23:a783c62c36d0 264 // found
gsfan 23:a783c62c36d0 265 return i;
gsfan 23:a783c62c36d0 266 }
gsfan 23:a783c62c36d0 267 }
gsfan 23:a783c62c36d0 268 return -1;
gsfan 18:4b97804c37d1 269 }
gsfan 18:4b97804c37d1 270
gsfan 19:cad912f5a6ba 271 int GSwifi::httpd_request (int cid, GS_httpd *gshttpd, char *dir) {
gsfan 18:4b97804c37d1 272 FILE *fp;
gsfan 20:151b5a4fdd29 273 int i, len;
gsfan 20:151b5a4fdd29 274 char buf[HTTPD_BUF_SIZE];
gsfan 20:151b5a4fdd29 275 char file[HTTPD_URI_SIZE];
gsfan 18:4b97804c37d1 276
gsfan 20:151b5a4fdd29 277 strcpy(file, dir);
gsfan 20:151b5a4fdd29 278 strcat(file, gshttpd->file);
gsfan 20:151b5a4fdd29 279 if (file[strlen(file) - 1] == '/') {
gsfan 24:5c350ae2e703 280 strcat(file, "index.html");
gsfan 18:4b97804c37d1 281 }
gsfan 20:151b5a4fdd29 282 DBG("file: %s\r\n", file);
gsfan 18:4b97804c37d1 283
gsfan 20:151b5a4fdd29 284 fp = fopen(file, "r");
gsfan 18:4b97804c37d1 285 if (fp) {
gsfan 19:cad912f5a6ba 286 send(cid, "HTTP/1.1 200 OK\r\n", 17);
gsfan 18:4b97804c37d1 287 {
gsfan 19:cad912f5a6ba 288 // file size
gsfan 20:151b5a4fdd29 289 i = ftell(fp);
gsfan 18:4b97804c37d1 290 fseek(fp, 0, SEEK_END);
gsfan 20:151b5a4fdd29 291 len = ftell(fp);
gsfan 20:151b5a4fdd29 292 fseek(fp, i, SEEK_SET);
gsfan 18:4b97804c37d1 293 }
gsfan 20:151b5a4fdd29 294 sprintf(buf, "Content-Length: %d\r\n", len);
gsfan 18:4b97804c37d1 295 send(cid, buf, strlen(buf));
gsfan 20:151b5a4fdd29 296 sprintf(buf, "Content-Type: %s\r\n", mimetype(file));
gsfan 18:4b97804c37d1 297 send(cid, buf, strlen(buf));
gsfan 19:cad912f5a6ba 298 if (gshttpd->keepalive) {
gsfan 18:4b97804c37d1 299 strcpy(buf, "Connection: Keep-Alive\r\n");
gsfan 18:4b97804c37d1 300 } else {
gsfan 18:4b97804c37d1 301 strcpy(buf, "Connection: close\r\n");
gsfan 18:4b97804c37d1 302 }
gsfan 18:4b97804c37d1 303 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 304 strcpy(buf, "Server: GSwifi httpd\r\n");
gsfan 18:4b97804c37d1 305 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 306 send(cid, "\r\n", 2);
gsfan 18:4b97804c37d1 307
gsfan 18:4b97804c37d1 308 for (;;) {
gsfan 18:4b97804c37d1 309 i = fread(buf, sizeof(char), sizeof(buf), fp);
gsfan 20:151b5a4fdd29 310 if (i <= 0) break;
gsfan 22:9b077e2823ce 311 if (! _gs_sock[cid].connect) break;
gsfan 18:4b97804c37d1 312 send(cid, buf, i);
gsfan 20:151b5a4fdd29 313 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
gsfan 18:4b97804c37d1 314 if (feof(fp)) break;
gsfan 20:151b5a4fdd29 315 #endif
gsfan 18:4b97804c37d1 316 }
gsfan 18:4b97804c37d1 317 fclose(fp);
gsfan 20:151b5a4fdd29 318 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 319 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 320 return 0;
gsfan 18:4b97804c37d1 321 }
gsfan 18:4b97804c37d1 322
gsfan 18:4b97804c37d1 323 send_httpd_error(cid, 404);
gsfan 18:4b97804c37d1 324 return -1;
gsfan 18:4b97804c37d1 325 }
gsfan 18:4b97804c37d1 326
gsfan 19:cad912f5a6ba 327 char *GSwifi::mimetype (char *file) {
gsfan 19:cad912f5a6ba 328 int i, j;
gsfan 19:cad912f5a6ba 329
gsfan 20:151b5a4fdd29 330 DBG("<%s>\r\n", file);
gsfan 19:cad912f5a6ba 331 for (i = 0; i < MIMETABLE_NUM; i ++) {
gsfan 19:cad912f5a6ba 332 j = strlen(mimetable[i].ext);
gsfan 25:f6e5622d2930 333 if (file[strlen(file) - j - 1] == '.' &&
gsfan 25:f6e5622d2930 334 strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) {
gsfan 19:cad912f5a6ba 335 return mimetable[i].type;
gsfan 19:cad912f5a6ba 336 }
gsfan 19:cad912f5a6ba 337 }
gsfan 19:cad912f5a6ba 338 return mimetable[0].type;
gsfan 19:cad912f5a6ba 339 }
gsfan 19:cad912f5a6ba 340
gsfan 23:a783c62c36d0 341 int GSwifi::strnicmp (char *p1, char *p2, int n) {
gsfan 25:f6e5622d2930 342 int i, r = -1;
gsfan 23:a783c62c36d0 343 char c1, c2;
gsfan 23:a783c62c36d0 344
gsfan 23:a783c62c36d0 345 for (i = 0; i < n; i ++) {
gsfan 23:a783c62c36d0 346 c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i];
gsfan 23:a783c62c36d0 347 c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i];
gsfan 23:a783c62c36d0 348 r = c1 - c2;
gsfan 23:a783c62c36d0 349 if (r) break;
gsfan 23:a783c62c36d0 350 }
gsfan 23:a783c62c36d0 351 return r;
gsfan 23:a783c62c36d0 352 }
gsfan 23:a783c62c36d0 353
gsfan 18:4b97804c37d1 354 void GSwifi::send_httpd_error (int cid, int err) {
gsfan 18:4b97804c37d1 355 char buf[100], msg[30];
gsfan 18:4b97804c37d1 356
gsfan 18:4b97804c37d1 357 switch (err) {
gsfan 18:4b97804c37d1 358 case 400:
gsfan 18:4b97804c37d1 359 strcpy(msg, "Bad Request");
gsfan 18:4b97804c37d1 360 break;
gsfan 18:4b97804c37d1 361 case 403:
gsfan 18:4b97804c37d1 362 strcpy(msg, "Forbidden");
gsfan 18:4b97804c37d1 363 break;
gsfan 18:4b97804c37d1 364 case 404:
gsfan 18:4b97804c37d1 365 strcpy(msg, "Not Found");
gsfan 18:4b97804c37d1 366 break;
gsfan 18:4b97804c37d1 367 case 500:
gsfan 18:4b97804c37d1 368 default:
gsfan 18:4b97804c37d1 369 strcpy(msg, "Internal Server Error");
gsfan 18:4b97804c37d1 370 break;
gsfan 18:4b97804c37d1 371 }
gsfan 18:4b97804c37d1 372 DBG("httpd error: %d %d %s\r\n", cid, err, msg);
gsfan 18:4b97804c37d1 373
gsfan 18:4b97804c37d1 374 sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg);
gsfan 18:4b97804c37d1 375 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 376 strcpy(buf, "Content-Type: text/html\r\n");
gsfan 18:4b97804c37d1 377 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 378 send(cid, "\r\n", 2);
gsfan 18:4b97804c37d1 379
gsfan 18:4b97804c37d1 380 sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg);
gsfan 18:4b97804c37d1 381 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 382 sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg);
gsfan 18:4b97804c37d1 383 send(cid, buf, strlen(buf));
gsfan 18:4b97804c37d1 384 close(cid);
gsfan 20:151b5a4fdd29 385 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 386 LOG("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err);
gsfan 18:4b97804c37d1 387 }
gsfan 18:4b97804c37d1 388
gsfan 19:cad912f5a6ba 389 int GSwifi::attach_httpd (const char *uri, const char *dir) {
gsfan 18:4b97804c37d1 390 if (_handler_count < HTTPD_HANDLE) {
gsfan 18:4b97804c37d1 391 _handler[_handler_count].uri = new char[strlen(uri) + 1];
gsfan 18:4b97804c37d1 392 strcpy(_handler[_handler_count].uri, uri);
gsfan 18:4b97804c37d1 393 _handler[_handler_count].dir = new char[strlen(dir) + 1];
gsfan 18:4b97804c37d1 394 strcpy(_handler[_handler_count].dir, dir);
gsfan 18:4b97804c37d1 395 _handler[_handler_count].onHttpCgi = NULL;
gsfan 18:4b97804c37d1 396 _handler_count ++;
gsfan 18:4b97804c37d1 397 return 0;
gsfan 18:4b97804c37d1 398 } else {
gsfan 18:4b97804c37d1 399 return -1;
gsfan 18:4b97804c37d1 400 }
gsfan 18:4b97804c37d1 401 }
gsfan 18:4b97804c37d1 402
gsfan 19:cad912f5a6ba 403 int GSwifi::attach_httpd (const char *uri, onHttpdCgiFunc ponHttpCgi) {
gsfan 18:4b97804c37d1 404 if (_handler_count < HTTPD_HANDLE) {
gsfan 18:4b97804c37d1 405 _handler[_handler_count].uri = new char[strlen(uri) + 1];
gsfan 18:4b97804c37d1 406 strcpy(_handler[_handler_count].uri, uri);
gsfan 18:4b97804c37d1 407 _handler[_handler_count].dir = NULL;
gsfan 18:4b97804c37d1 408 _handler[_handler_count].onHttpCgi = ponHttpCgi;
gsfan 18:4b97804c37d1 409 _handler_count ++;
gsfan 18:4b97804c37d1 410 return 0;
gsfan 18:4b97804c37d1 411 } else {
gsfan 18:4b97804c37d1 412 return -1;
gsfan 18:4b97804c37d1 413 }
gsfan 18:4b97804c37d1 414 }
gsfan 20:151b5a4fdd29 415
gsfan 23:a783c62c36d0 416 #ifdef GS_USE_WEBSOCKET
gsfan 23:a783c62c36d0 417 void GSwifi::poll_websocket (int cid, int len) {
gsfan 23:a783c62c36d0 418 int i, j, flg;
gsfan 23:a783c62c36d0 419 unsigned char c;
gsfan 23:a783c62c36d0 420
gsfan 26:b347ee3a1087 421 while (_gs_sock[cid].connect && (! _gs_sock[cid].data->isEmpty())) {
gsfan 23:a783c62c36d0 422 flg = 0;
gsfan 23:a783c62c36d0 423 // get 1 line
gsfan 23:a783c62c36d0 424 for (j = 0; j < len; j ++) {
gsfan 25:f6e5622d2930 425 _gs_sock[cid].data->dequeue((char*)&c);
gsfan 23:a783c62c36d0 426 // DBG("_%c", c);
gsfan 23:a783c62c36d0 427
gsfan 23:a783c62c36d0 428 switch (_httpd[cid].mode) {
gsfan 23:a783c62c36d0 429 case GSHTTPDMODE_WEBSOCKET:
gsfan 23:a783c62c36d0 430 if (_httpd[cid].len == 0) {
gsfan 26:b347ee3a1087 431 // flag
gsfan 23:a783c62c36d0 432 _httpd[cid].type = c & 0x0f;
gsfan 23:a783c62c36d0 433 _httpd[cid].websocket_flg = c << 8;
gsfan 23:a783c62c36d0 434 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 435 } else
gsfan 23:a783c62c36d0 436 if (_httpd[cid].len == 1) {
gsfan 26:b347ee3a1087 437 // length 7bit
gsfan 23:a783c62c36d0 438 _httpd[cid].websocket_flg |= c;
gsfan 23:a783c62c36d0 439 _httpd[cid].length = c & 0x7f;
gsfan 23:a783c62c36d0 440 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 441 if (_httpd[cid].length < 126) {
gsfan 23:a783c62c36d0 442 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 443 if (_httpd[cid].websocket_flg & 0x0080) {
gsfan 23:a783c62c36d0 444 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK;
gsfan 23:a783c62c36d0 445 } else {
gsfan 23:a783c62c36d0 446 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY;
gsfan 23:a783c62c36d0 447 }
gsfan 23:a783c62c36d0 448 DBG("ws length %d\r\n", _httpd[cid].length);
gsfan 23:a783c62c36d0 449 }
gsfan 23:a783c62c36d0 450 } else {
gsfan 23:a783c62c36d0 451 // length 16bit,64bit
gsfan 23:a783c62c36d0 452 if (_httpd[cid].len == 2) {
gsfan 23:a783c62c36d0 453 _httpd[cid].length = c;
gsfan 23:a783c62c36d0 454 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 455 } else
gsfan 23:a783c62c36d0 456 if (_httpd[cid].len < 9 && (_httpd[cid].websocket_flg & 0x7f) == 127) {
gsfan 23:a783c62c36d0 457 // 64bit
gsfan 23:a783c62c36d0 458 _httpd[cid].length = (_httpd[cid].length << 8) | c;
gsfan 23:a783c62c36d0 459 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 460 } else {
gsfan 26:b347ee3a1087 461 // end
gsfan 23:a783c62c36d0 462 _httpd[cid].length = (_httpd[cid].length << 8) | c;
gsfan 23:a783c62c36d0 463 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 464 if (_httpd[cid].websocket_flg & 0x0080) {
gsfan 23:a783c62c36d0 465 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK;
gsfan 23:a783c62c36d0 466 } else {
gsfan 23:a783c62c36d0 467 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY;
gsfan 23:a783c62c36d0 468 }
gsfan 23:a783c62c36d0 469 DBG("ws length2 %d\r\n", _httpd[cid].length);
gsfan 23:a783c62c36d0 470 }
gsfan 23:a783c62c36d0 471 }
gsfan 23:a783c62c36d0 472 break;
gsfan 23:a783c62c36d0 473
gsfan 23:a783c62c36d0 474 case GSHTTPDMODE_WEBSOCKET_MASK:
gsfan 26:b347ee3a1087 475 // masking key
gsfan 23:a783c62c36d0 476 _httpd[cid].websocket_mask[_httpd[cid].len] = c;
gsfan 23:a783c62c36d0 477 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 478 if (_httpd[cid].len >= 4) {
gsfan 23:a783c62c36d0 479 _httpd[cid].len = 0;
gsfan 23:a783c62c36d0 480 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY;
gsfan 23:a783c62c36d0 481 DBG("ws mask\r\n");
gsfan 23:a783c62c36d0 482 }
gsfan 23:a783c62c36d0 483 break;
gsfan 23:a783c62c36d0 484
gsfan 23:a783c62c36d0 485 case GSHTTPDMODE_WEBSOCKET_BODY:
gsfan 26:b347ee3a1087 486 // payload
gsfan 23:a783c62c36d0 487 if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) {
gsfan 23:a783c62c36d0 488 if (_httpd[cid].websocket_flg & 0x0080) {
gsfan 26:b347ee3a1087 489 // un-mask
gsfan 23:a783c62c36d0 490 _httpd[cid].buf[_httpd[cid].len] = c ^ _httpd[cid].websocket_mask[_httpd[cid].len & 0x03];
gsfan 23:a783c62c36d0 491 } else {
gsfan 23:a783c62c36d0 492 _httpd[cid].buf[_httpd[cid].len] = c;
gsfan 23:a783c62c36d0 493 }
gsfan 23:a783c62c36d0 494 _httpd[cid].len ++;
gsfan 23:a783c62c36d0 495 }
gsfan 23:a783c62c36d0 496 break;
gsfan 23:a783c62c36d0 497 }
gsfan 23:a783c62c36d0 498
gsfan 23:a783c62c36d0 499 if (_httpd[cid].mode == GSHTTPDMODE_WEBSOCKET_BODY && _httpd[cid].len >= _httpd[cid].length) {
gsfan 23:a783c62c36d0 500 flg = 1;
gsfan 23:a783c62c36d0 501 break;
gsfan 23:a783c62c36d0 502 }
gsfan 23:a783c62c36d0 503 }
gsfan 23:a783c62c36d0 504 if (j >= len) return; // continue
gsfan 23:a783c62c36d0 505 if (_httpd[cid].len < HTTPD_BUF_SIZE) {
gsfan 23:a783c62c36d0 506 _httpd[cid].buf[_httpd[cid].len] = 0;
gsfan 23:a783c62c36d0 507 DBG("websocket %d: (%d)\r\n", cid, _httpd[cid].len);
gsfan 23:a783c62c36d0 508 }
gsfan 23:a783c62c36d0 509
gsfan 26:b347ee3a1087 510 if (flg) {
gsfan 26:b347ee3a1087 511 // websocket request
gsfan 26:b347ee3a1087 512 DBG("ws type %d\r\n", _httpd[cid].type);
gsfan 26:b347ee3a1087 513 switch (_httpd[cid].type) {
gsfan 26:b347ee3a1087 514 case 0x00: // continuation
gsfan 26:b347ee3a1087 515 case 0x01: // text
gsfan 26:b347ee3a1087 516 case 0x02: // binary
gsfan 26:b347ee3a1087 517 i = get_handler(_httpd[cid].uri);
gsfan 26:b347ee3a1087 518 if (i >= 0) {
gsfan 26:b347ee3a1087 519 if (_handler[i].onHttpCgi) {
gsfan 26:b347ee3a1087 520 // cgi
gsfan 26:b347ee3a1087 521 _handler[i].onHttpCgi(cid, &_httpd[cid]);
gsfan 26:b347ee3a1087 522 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 523 LOG("%s %s %d 200 -\r\n", "WEBSOCKET", _httpd[cid].uri, _httpd[cid].length);
gsfan 26:b347ee3a1087 524 flg = 1;
gsfan 26:b347ee3a1087 525 }
gsfan 23:a783c62c36d0 526 }
gsfan 26:b347ee3a1087 527 break;
gsfan 23:a783c62c36d0 528
gsfan 26:b347ee3a1087 529 case 0x08: // close
gsfan 26:b347ee3a1087 530 close(cid);
gsfan 26:b347ee3a1087 531 break;
gsfan 23:a783c62c36d0 532
gsfan 26:b347ee3a1087 533 case 0x09: // ping
gsfan 26:b347ee3a1087 534 {
gsfan 26:b347ee3a1087 535 char pong[_httpd[cid].len + 2];
gsfan 26:b347ee3a1087 536 pong[0] = 0x8a;
gsfan 26:b347ee3a1087 537 pong[1] = 0x04;
gsfan 26:b347ee3a1087 538 memcpy(&pong[2], _httpd[cid].buf, _httpd[cid].len);
gsfan 26:b347ee3a1087 539 send(cid, pong, _httpd[cid].len + 2);
gsfan 26:b347ee3a1087 540 }
gsfan 26:b347ee3a1087 541 break;
gsfan 26:b347ee3a1087 542
gsfan 26:b347ee3a1087 543 case 0x0a: // pong
gsfan 26:b347ee3a1087 544 break;
gsfan 26:b347ee3a1087 545 }
gsfan 26:b347ee3a1087 546 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET;
gsfan 26:b347ee3a1087 547 _httpd[cid].len = 0;
gsfan 26:b347ee3a1087 548 _httpd[cid].length = 0;
gsfan 23:a783c62c36d0 549 }
gsfan 23:a783c62c36d0 550 } // while
gsfan 23:a783c62c36d0 551 }
gsfan 23:a783c62c36d0 552
gsfan 23:a783c62c36d0 553 int GSwifi::send_websocket (int cid, const char *buf, int len) {
gsfan 23:a783c62c36d0 554 int r;
gsfan 23:a783c62c36d0 555 char tmp[10];
gsfan 23:a783c62c36d0 556
gsfan 23:a783c62c36d0 557 tmp[0] = 0x81; // single, text frame
gsfan 23:a783c62c36d0 558 if (len < 126) {
gsfan 23:a783c62c36d0 559 tmp[1] = len;
gsfan 23:a783c62c36d0 560 r = send(cid, tmp, 2);
gsfan 23:a783c62c36d0 561 } else {
gsfan 23:a783c62c36d0 562 tmp[1] = 126;
gsfan 23:a783c62c36d0 563 tmp[2] = (len >> 8) & 0xff;
gsfan 23:a783c62c36d0 564 tmp[3] = len & 0xff;
gsfan 23:a783c62c36d0 565 r = send(cid, tmp, 4);
gsfan 23:a783c62c36d0 566 }
gsfan 23:a783c62c36d0 567 if (r == 0) {
gsfan 23:a783c62c36d0 568 r = send(cid, buf, len);
gsfan 23:a783c62c36d0 569 }
gsfan 23:a783c62c36d0 570 return r;
gsfan 23:a783c62c36d0 571 }
gsfan 23:a783c62c36d0 572
gsfan 23:a783c62c36d0 573 void GSwifi::send_websocket_accept (int cid) {
gsfan 23:a783c62c36d0 574 char buf[100], buf2[20];
gsfan 23:a783c62c36d0 575
gsfan 23:a783c62c36d0 576 DBG("websocket accept: %d\r\n", cid);
gsfan 23:a783c62c36d0 577
gsfan 23:a783c62c36d0 578 send(cid, "HTTP/1.1 101 Switching Protocols\r\n", 34);
gsfan 23:a783c62c36d0 579 send(cid, "Upgrade: websocket\r\n", 20);
gsfan 23:a783c62c36d0 580 send(cid, "Connection: Upgrade\r\n", 21);
gsfan 23:a783c62c36d0 581
gsfan 23:a783c62c36d0 582 send(cid, "Sec-WebSocket-Accept: ", 22);
gsfan 23:a783c62c36d0 583 strcpy(buf, _httpd[cid].websocket_key);
gsfan 23:a783c62c36d0 584 strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
gsfan 23:a783c62c36d0 585 sha1(buf, strlen(buf), buf2);
gsfan 23:a783c62c36d0 586 base64encode(buf2, 20, buf, sizeof(buf));
gsfan 23:a783c62c36d0 587 send(cid, buf, strlen(buf));
gsfan 23:a783c62c36d0 588 send(cid, "\r\n", 2);
gsfan 23:a783c62c36d0 589 // send(cid, "Sec-WebSocket-Protocol: chat\r\n", 30);
gsfan 23:a783c62c36d0 590 send(cid, "\r\n", 2);
gsfan 23:a783c62c36d0 591 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 592 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 593 }
gsfan 20:151b5a4fdd29 594 #endif
gsfan 23:a783c62c36d0 595
gsfan 23:a783c62c36d0 596 #endif