GainSpan Wi-Fi library see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/

Fork of GSwifi_old 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/

Information

Please change the baud rate in advance.

  • ATB=115200
  • AT&W0

It may be better and sometimes faster.
GSwifi gs(p13, p14, baud);

Heavily modified new library: http://mbed.org/users/gsfan/code/GSwifi

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

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

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

Information

モジュールはあらかじめ次のコマンドでボーレートを変更しておく。

  • ATB=115200
  • AT&W0

場合によってはもっと高速の方がいいかもしれない。クラス宣言時にレート設定をする。
GSwifi gs(p13, p14, baud);

大幅に更新された新しいライブラリ: http://mbed.org/users/gsfan/code/GSwifi

Committer:
gsfan
Date:
Wed Jan 23 07:41:23 2013 +0000
Revision:
24:5c350ae2e703
Parent:
23:a783c62c36d0
auto re-connect

Who changed what in which revision?

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