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
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/
ゲインスパン Wi-Fi モジュール ライブラリ
ゲインスパン社の低電力 Wi-Fiモジュール(無線LAN) GS1011 シリーズ用のライブラリです。
解説: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
Revision 29:1c4419512941, committed 2013-02-26
- Comitter:
- gsfan
- Date:
- Tue Feb 26 02:48:31 2013 +0000
- Parent:
- 28:fbba4c58d14c
- Child:
- 30:f3e9053d9b46
- Commit message:
- add websocket client
Changed in this revision
--- a/CBuffer.h Fri Feb 22 03:07:43 2013 +0000 +++ b/CBuffer.h Tue Feb 26 02:48:31 2013 +0000 @@ -1,81 +1,77 @@ -/* Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef CIRCBUFFER_H_ -#define CIRCBUFFER_H_ - -template <class T> -class CircBuffer { -public: - CircBuffer(int length) { - write = 0; - read = 0; - size = length + 1; - buf = (T *)malloc(size * sizeof(T)); - }; - - bool isFull() { - return (((write + 1) % size) == read); - }; - - bool isEmpty() { - return (read == write); - }; - - bool queue(T k) { - if (isFull()) { -// read++; -// read %= size; - return false; - } - buf[write++] = k; - write %= size; - return true; - } - - void flush() { - read = 0; - write = 0; - } - - - uint32_t available() { - return (write >= read) ? write - read : size - read + write; - }; - - uint32_t use() { - return size - available() - 1; - }; - - bool dequeue(T * c) { - bool empty = isEmpty(); - if (!empty) { - *c = buf[read++]; - read %= size; - } - return(!empty); - }; - -private: - volatile uint32_t write; - volatile uint32_t read; - uint32_t size; - T * buf; -}; - -#endif +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef CIRCBUFFER_H_ +#define CIRCBUFFER_H_ + +template <class T> +class CircBuffer { +public: + CircBuffer(int length) { + write = 0; + read = 0; + size = length + 1; + buf = (T *)malloc(size * sizeof(T)); + }; + + bool isFull() { + return (((write + 1) % size) == read); + }; + + bool isEmpty() { + return (read == write); + }; + + bool queue(T k) { + if (isFull()) { +// read++; +// read %= size; + return false; + } + buf[write++] = k; + write %= size; + return true; + } + + void flush() { + read = 0; + write = 0; + } + + + uint32_t available() { + return (write >= read) ? write - read : size - read + write; + }; + + bool dequeue(T * c) { + bool empty = isEmpty(); + if (!empty) { + *c = buf[read++]; + read %= size; + } + return(!empty); + }; + +private: + volatile uint32_t write; + volatile uint32_t read; + uint32_t size; + T * buf; +}; + +#endif
--- a/GSFunctionPointer.h Fri Feb 22 03:07:43 2013 +0000 +++ b/GSFunctionPointer.h Tue Feb 26 02:48:31 2013 +0000 @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -/* Copyright (C) 2013 gsfan, MIT License - * modifyed for the GSwifi library +/* + * Modifyed for the GSwifi library, by 2013 gsfan */ #ifndef GS_FUNCTIONPOINTER_H #define GS_FUNCTIONPOINTER_H
--- a/GSwifi.cpp Fri Feb 22 03:07:43 2013 +0000 +++ b/GSwifi.cpp Tue Feb 26 02:48:31 2013 +0000 @@ -246,7 +246,7 @@ if (_gs_sock[_cid].protocol == GSPROT_HTTPGET) { // recv interrupt - if (_gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->use()) == 0) + if (_gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->available()) == 0) _gs_sock[_cid].received = false; } break; @@ -266,7 +266,7 @@ if (len < GS_DATA_SIZE && _gs_sock[_cid].data->isFull()) { // buffer full // recv interrupt - _gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->use()); + _gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->available()); } } } @@ -331,7 +331,7 @@ if (len && _gs_sock[_cid].data->isFull()) { // buffer full // recv interrupt - _gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->use()); + _gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->available()); } if (len == 0) { DBG("recv binary %d\r\n", _cid); @@ -341,7 +341,7 @@ if (_gs_sock[_cid].protocol == GSPROT_HTTPGET) { // recv interrupt - if (_gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->use()) == 0) + if (_gs_sock[_cid].onGsReceive.call(_cid, _gs_sock[_cid].data->available()) == 0) _gs_sock[_cid].received = false; } } @@ -695,7 +695,7 @@ return 0; } -int GSwifi::getMac (char *mac) { +int GSwifi::getMacAddress (char *mac) { memcpy(mac, _mac, 6); return 0; } @@ -1060,7 +1060,7 @@ _gs_sock[i].received = false; for (j = 0; j < 1500 / GS_DATA_SIZE + 1; j ++) { if (! _gs_sock[i].connect || _gs_sock[i].data->isEmpty()) break; - _gs_sock[i].onGsReceive.call(i, _gs_sock[i].data->use()); + _gs_sock[i].onGsReceive.call(i, _gs_sock[i].data->available()); } } } @@ -1164,7 +1164,7 @@ DBG("GS mode=%d, escape=%d, cid=%d\r\n", _gs_mode, _escape, _cid); for (i = 0; i < 16; i ++) { - DBG("%d: connect=%d, type=%d, protocol=%d, len=%d\r\n", i, _gs_sock[i].connect, _gs_sock[i].type, _gs_sock[i].protocol, _gs_sock[i].data->use()); + DBG("%d: connect=%d, type=%d, protocol=%d, len=%d\r\n", i, _gs_sock[i].connect, _gs_sock[i].type, _gs_sock[i].protocol, _gs_sock[i].data->available()); if (_gs_sock[i].protocol == GSPROT_HTTPD) { DBG(" mode=%d, type=%d, len=%d\r\n", i, _httpd[i].mode, _httpd[i].type, _httpd[i].len); }
--- a/GSwifi.h Fri Feb 22 03:07:43 2013 +0000 +++ b/GSwifi.h Tue Feb 26 02:48:31 2013 +0000 @@ -264,7 +264,7 @@ /** * get mac address */ - int getMac (char *mac); + int getMacAddress (char *mac); /** * resolv hostname * @param name hostname @@ -427,12 +427,27 @@ * http request (GET method) */ int httpGet (Host &host, const char *uri, const char *user, const char *pwd, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL); - int httpGet (Host &host, const char *uri, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL); + int httpGet (Host &host, const char *uri, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL) { + return httpGet (host, uri, NULL, NULL, ssl, ponGsReceive); + } /** * http request (POST method) */ int httpPost (Host &host, const char *uri, const char *body, const char *user, const char *pwd, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL); - int httpPost (Host &host, const char *uri, const char *body, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL); + int httpPost (Host &host, const char *uri, const char *body, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL) { + return httpPost (host, uri, body, NULL, NULL, ssl, ponGsReceive); + } + /** + * websocket request (Upgrade method) + */ + int wsOpen (Host &host, const char *uri, const char *user, const char *pwd, onGsReceiveFunc ponGsReceive = NULL); + int wsOpen (Host &host, const char *uri, onGsReceiveFunc ponGsReceive = NULL) { + return wsOpen (host, uri, NULL, NULL, ponGsReceive); + } + /** + * send data websocket + */ + int wsSend (int cid, const char *buf, int len, const char *mask = NULL); /** * base64 encode @@ -483,9 +498,6 @@ * attach uri to cgi handler */ int attach_httpd (const char *uri, onHttpdCgiFunc ponHttpCgi); -#ifdef GS_USE_WEBSOCKET - int send_websocket (int cid, const char *buf, int len); -#endif #endif #ifdef DEBUG @@ -518,6 +530,8 @@ _gs_sock[cid].onGsReceive.attach(object, member); } + int wait_ws (int cid, int code); + #ifdef GS_USE_SMTP int wait_smtp (int cid, int code); #endif
--- a/GSwifi_conf.h Fri Feb 22 03:07:43 2013 +0000 +++ b/GSwifi_conf.h Tue Feb 26 02:48:31 2013 +0000 @@ -10,7 +10,7 @@ #define GS_WREGDOMAIN 2 // 0:FCC, 1:ETSI, 2:TELEC #define GS_TIMEOUT 10000 // ms -#define GS_TIMEOUT2 30000 // ms +#define GS_TIMEOUT2 130000 // ms #define GS_CMD_SIZE 100 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) @@ -31,7 +31,7 @@ // ----- GSwifi_http.cpp ----- #define GS_USE_HTTPD // use http server -//#define GS_USE_WEBSOCKET // use websocket (need httpd) +//#define GS_USE_WEBSOCKET // use websocket server (need httpd) #define HTTPD_TIMEOUT 15000 #define HTTPD_HANDLE 10
--- a/GSwifi_http.cpp Fri Feb 22 03:07:43 2013 +0000 +++ b/GSwifi_http.cpp Tue Feb 26 02:48:31 2013 +0000 @@ -23,6 +23,7 @@ #include "dbg.h" #include "mbed.h" #include "GSwifi.h" +#include <string.h> int GSwifi::httpGet (Host &host, const char *uri, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) { @@ -71,10 +72,6 @@ return _cid; } -int GSwifi::httpGet (Host &host, const char *uri, int ssl, onGsReceiveFunc ponGsReceive) { - return httpGet (host, uri, NULL, NULL, ssl, ponGsReceive); -} - int GSwifi::httpPost (Host &host, const char *uri, const char *body, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) { char cmd[GS_CMD_SIZE]; int i, len; @@ -130,8 +127,144 @@ return _cid; } -int GSwifi::httpPost (Host &host, const char *uri, const char *body, int ssl, onGsReceiveFunc ponGsReceive) { - return httpPost (host, uri, body, NULL, NULL, ssl, ponGsReceive); +int GSwifi::wsOpen (Host &host, const char *uri, const char *user, const char *pwd, onGsReceiveFunc ponGsReceive) { + int cid; + char cmd[GS_CMD_SIZE], tmp[GS_CMD_SIZE]; + + if (! _connect || _status != GSSTAT_READY) return -1; + + if (host.getIp().isNull()) { + if (getHostByName(host)) { + if (getHostByName(host)) return -1; + } + } + if (host.getPort() == 0) { + host.setPort(80); + } + + cid = open(host, GSPROT_TCP); + if (cid < 0) return -1; + DBG("cid %d\r\n", cid); + + // send request + send(cid, "GET ", 4); + send(cid, uri, strlen(uri)); + send(cid, " HTTP/1.1\r\n", 11); + if (host.getName() && host.getName()[0] != 0) { + send(cid, "Host: ", 5); + send(cid, host.getName(), strlen(host.getName())); + send(cid, "\r\n", 2); + } + if (user && pwd) { + snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd); + base64encode(tmp, strlen(tmp), cmd, sizeof(cmd)); + send(cid, "Authorization: Basic ", 21); + send(cid, cmd, strlen(cmd)); + send(cid, "\r\n", 2); + } + send(cid, "Upgrade: websocket\r\n", 20); + send(cid, "Connection: Upgrade\r\n", 21); + send(cid, "Sec-WebSocket-Key: ", 19); + getMacAddress(tmp); + memcpy(&tmp[6], host.getName(), 10); + base64encode(tmp, 16, cmd, sizeof(cmd)); + send(cid, cmd, strlen(cmd)); + send(cid, "\r\n", 2); + send(cid, "Sec-WebSocket-Version: 13\r\n", 27); + send(cid, "\r\n", 2); + + if (wait_ws(cid, 101)) { + close(cid); + return -1; + } + wait_ws(cid, 0); + + _gs_sock[cid].onGsReceive.attach(ponGsReceive); + return cid; +} + +int GSwifi::wait_ws (int cid, int code) { + Timer timeout; + int i, n, len; + char buf[200], data[100]; + + if (code == 0) { + timeout.start(); + while (timeout.read_ms() < GS_TIMEOUT) { + wait_ms(10); + if (_gs_sock[cid].data->isEmpty()) break; + poll(); + n = recv(cid, buf, sizeof(buf)); + if (n <= 0) break; + } + timeout.stop(); + return 0; + } + + // wait responce + len = 0; + timeout.start(); + while (timeout.read_ms() < GS_TIMEOUT) { + wait_ms(10); + poll(); + n = recv(cid, buf, sizeof(buf)); + for (i = 0; i < n; i ++) { + if (buf[i] == '\r') continue; + if (buf[i] == '\n') { + if (len == 0) continue; + goto next; + } else + if (len < sizeof(data) - 1) { + data[len] = buf[i]; + len ++; + } + } + } +next: + data[len] = 0; + DBG("ws: %s\r\n", data); + timeout.stop(); + + // check return code + if (strncmp(data, "HTTP/1.1 ", 9) != 0) return -1; + i = atoi(&data[9]); + DBG("ws status %d\r\n", i); + if (i == code) return 0; + + return -1; +} + +int GSwifi::wsSend (int cid, const char *buf, int len, const char *mask) { + int r; + char tmp[10]; + + tmp[0] = 0x82; // single, binary frame + tmp[1] = (mask == NULL) ? 0 : 0x80; + + if (len < 126) { + tmp[1] |= len; + r = send(cid, tmp, 2); + } else { + tmp[1] |= 126; + tmp[2] = (len >> 8) & 0xff; + tmp[3] = len & 0xff; + r = send(cid, tmp, 4); + } + + if (r == 0) { + if (mask) { + int i; + char tmp2[len]; + send(cid, mask, 4); + for (i = 0; i < len; i ++) { + tmp2[i] = buf[i] ^ mask[i & 0x03]; + } + r = send(cid, tmp2, len); + } else { + r = send(cid, buf, len); + } + } + return r; }
--- a/GSwifi_httpd.cpp Fri Feb 22 03:07:43 2013 +0000 +++ b/GSwifi_httpd.cpp Tue Feb 26 02:48:31 2013 +0000 @@ -30,8 +30,8 @@ #define MIMETABLE_NUM 9 struct { - char ext[5]; - char type[24]; + const char ext[5]; + const char type[24]; } mimetable[MIMETABLE_NUM] = { {"txt", "text/plain"}, // default {"html", "text/html"}, @@ -190,12 +190,17 @@ #ifdef GS_USE_WEBSOCKET if (flg && _httpd[cid].mode == GSHTTPDMODE_WEBSOCKET) { // websocket - _httpd[cid].host = _gs_sock[cid].host; - j = strlen(_handler[i].uri); - _httpd[cid].file = &_httpd[cid].uri[j]; - _httpd[cid].query = NULL; + i = get_handler(_httpd[cid].uri); + if (i >= 0 && _handler[i].onHttpCgi) { + _httpd[cid].host = _gs_sock[cid].host; + _httpd[cid].file = NULL; + _httpd[cid].query = NULL; - send_websocket_accept(cid); + send_websocket_accept(cid); + } else { + // not found + send_httpd_error(cid, 403); + } break; // exit while } else @@ -331,11 +336,11 @@ for (i = 0; i < MIMETABLE_NUM; i ++) { j = strlen(mimetable[i].ext); if (file[strlen(file) - j - 1] == '.' && - strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) { - return mimetable[i].type; + strnicmp(&file[strlen(file) - j], (char*)mimetable[i].ext, j) == NULL) { + return (char*)mimetable[i].type; } } - return mimetable[0].type; + return (char*)mimetable[0].type; } int GSwifi::strnicmp (char *p1, char *p2, int n) { @@ -550,26 +555,6 @@ } // while } -int GSwifi::send_websocket (int cid, const char *buf, int len) { - int r; - char tmp[10]; - - tmp[0] = 0x81; // single, text frame - if (len < 126) { - tmp[1] = len; - r = send(cid, tmp, 2); - } else { - tmp[1] = 126; - tmp[2] = (len >> 8) & 0xff; - tmp[3] = len & 0xff; - r = send(cid, tmp, 4); - } - if (r == 0) { - r = send(cid, buf, len); - } - return r; -} - void GSwifi::send_websocket_accept (int cid) { char buf[100], buf2[20];
--- a/GSwifi_smtp.cpp Fri Feb 22 03:07:43 2013 +0000 +++ b/GSwifi_smtp.cpp Tue Feb 26 02:48:31 2013 +0000 @@ -103,7 +103,7 @@ // wait responce timeout.start(); while (timeout.read_ms() < SMTP_TIMEOUT) { - wait_ms(100); + wait_ms(10); poll(); n = recv(cid, buf, sizeof(buf)); for (i = 0; i < n; i ++) { @@ -120,7 +120,6 @@ } next: data[len] = 0; - len = 0; DBG("smtp: %s\r\n", data); timeout.stop();