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:
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?

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