GSwifiInterface library (interface for GainSpan Wi-Fi GS1011 modules) Please see https://mbed.org/users/gsfan/notebook/GSwifiInterface/

Dependents:   GSwifiInterface_HelloWorld GSwifiInterface_HelloServo GSwifiInterface_UDPEchoServer GSwifiInterface_UDPEchoClient ... more

Fork of WiflyInterface by mbed official

GainSpan Wi-Fi library

The GS1011/GS2100 is an ultra low power 802.11b wireless module from GainSpan.

mbed RTOS supported.

/media/uploads/gsfan/gs_im_002.jpg /media/uploads/gsfan/gs1011m_2.jpg

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

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

mbed RTOS に対応しています。(mbed2.0)

Revision:
12:057089026a20
Child:
15:086d1a33a197
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/GSwifi_httpd_ws.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -0,0 +1,300 @@
+/* Copyright (C) 2013 gsfan, 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.
+ */
+
+#include "GSwifi.h"
+
+#ifdef CFG_ENABLE_WEBSOCKET
+
+#include "sha1.h"
+
+int GSwifi::wsOpen (const char *host, int port, const char *uri, const char *user, const char *pwd) {
+    int cid;
+    char cmd[CFG_CMD_SIZE], tmp[CFG_CMD_SIZE];
+    char ip[17];
+
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
+
+    if (getHostByName(host, ip)) return -1;
+    if (! port) {
+        port = 80;
+    }
+
+    cid = open(PROTO_TCP, ip, port);
+    if (cid < 0) return -1;
+    DBG("ws cid %d\r\n", cid);
+
+    // request
+    snprintf(cmd, sizeof(cmd), "GET %d HTTP/1.1\r\n", uri);
+    send(cid, cmd, strlen(cmd));
+    if (host) {
+        snprintf(cmd, sizeof(cmd), "Host: %s\r\n", host);
+        send(cid, cmd, strlen(cmd));
+    }
+    if (user && pwd) {
+        snprintf(cmd, sizeof(cmd), "%s:%s", user, pwd);
+        base64encode(cmd, strlen(cmd), tmp, sizeof(tmp));
+        snprintf(cmd, sizeof(cmd), "Authorization: Basic %s\r\n", tmp);
+        send(cid, cmd, strlen(cmd));
+    }
+    strcpy(cmd, "Upgrade: websocket\r\n");
+    send(cid, cmd, strlen(cmd));
+    strcpy(cmd, "Connection: Upgrade\r\n");
+    send(cid, cmd, strlen(cmd));
+    getMacAddress(tmp);
+    memcpy(&tmp[6], host, 10);
+    base64encode(tmp, 16, cmd, sizeof(cmd));
+    snprintf(cmd, sizeof(cmd), "Sec-WebSocket-Key: %s\r\n", tmp);
+    send(cid, cmd, strlen(cmd));
+    strcpy(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
+    send(cid, cmd, strlen(cmd));
+
+    if (wsWait(cid, 101)) {
+        close(cid);
+        return -1;
+    }
+    wsWait(cid, 0);
+    return cid;
+}
+
+int GSwifi::wsWait (int cid, int code) {
+    Timer timeout;
+    int i, n, len;
+    char buf[CFG_DATA_SIZE], data[CFG_CMD_SIZE];
+
+    if (code == 0) {
+        // dummy read
+        timeout.start();
+        while (timeout.read_ms() < CFG_TIMEOUT) {
+            wait_ms(10);
+            if (!readable(cid)) break;
+            n = recv(cid, buf, sizeof(buf));
+            if (n <= 0) break;
+        }
+        timeout.stop();
+        return 0;
+    }
+
+    // wait responce
+    len = 0;
+    timeout.start();
+    while (timeout.read_ms() < CFG_TIMEOUT) {
+        wait_ms(10);
+        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;
+    timeout.stop();
+    DBG("ws: %s\r\n", data);
+ 
+    // check return code
+    if (strncmp(data, "HTTP/1.1 ", 9) != 0) return -1;
+    i = atoi(&data[9]);
+    DBG("ws status %d\r\n", i);
+    return i == code ? 0 : -1;
+}
+
+int GSwifi::wsSend (int cid, const char *buf, int len, const char *mask) {
+    int i = 0, r;
+    char tmp[10];
+ 
+    tmp[i++] = 0x81; // single, text frame
+    if (len < 126) {
+        tmp[i++] = (mask == NULL ? 0 : 0x80) | len;
+    } else {
+        tmp[i++] = (mask == NULL ? 0 : 0x80) | 126;
+        tmp[i++] = (len >> 8) & 0xff;
+        tmp[i++] = len & 0xff;
+    }
+    if (mask) {
+        memcpy(&tmp[i], mask, 4);
+        i += 4;
+    }
+    r = send(cid, tmp, strlen(tmp));
+ 
+    if (r == 0) {
+        if (mask) {
+            char tmp2[len];
+            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;
+}
+
+#ifdef CFG_ENABLE_HTTPD
+
+void GSwifi::wsRecvData (int cid, char c) {
+
+    switch (_httpd[cid].mode) {
+    case HTTPDMODE_WEBSOCKET:
+        if (_httpd[cid].n == 0) {
+            // flag
+            _httpd[cid].websocket_opcode = c & 0x0f;
+            _httpd[cid].websocket_flg = c << 8;
+            _httpd[cid].n ++;
+        } else
+        if (_httpd[cid].n == 1) {
+            // length 7bit
+            _httpd[cid].websocket_flg |= c;
+            _httpd[cid].length = c & 0x7f;
+            _httpd[cid].n ++;
+            if (_httpd[cid].length < 126) {
+                _httpd[cid].n = 0;
+                if (_httpd[cid].length) {
+                    if (_httpd[cid].websocket_flg & 0x0080) {
+                        _httpd[cid].mode = HTTPDMODE_WEBSOCKET_MASK;
+                    } else {
+                        _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BODY;
+                    }
+                } else {
+                    _httpd[cid].mode = HTTPDMODE_WEBSOCKET_ENTER;
+                }
+                DBG("ws length %d\r\n", _httpd[cid].length);
+            }
+        } else {
+            // length 16bit,64bit
+            if (_httpd[cid].n == 2) {
+                _httpd[cid].length = c;
+                _httpd[cid].n ++;
+            } else
+            if (_httpd[cid].n < 9 && (_httpd[cid].websocket_flg & 0x7f) == 127) {
+                // 64bit
+                _httpd[cid].length = (_httpd[cid].length << 8) | c;
+                _httpd[cid].n ++;
+            } else {
+                // end
+                _httpd[cid].length = (_httpd[cid].length << 8) | c;
+                _httpd[cid].n = 0;
+                if (_httpd[cid].websocket_flg & 0x0080) {
+                    _httpd[cid].mode = HTTPDMODE_WEBSOCKET_MASK;
+                } else {
+                    _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BODY;
+                }
+                DBG("ws length2 %d\r\n", _httpd[cid].length);
+            }
+        }
+        break;
+    case HTTPDMODE_WEBSOCKET_MASK:
+        // masking key
+        _httpd[cid].websocket_mask[_httpd[cid].n] = c;
+        _httpd[cid].n ++;
+        if (_httpd[cid].n >= 4) {
+            _httpd[cid].n = 0;
+            _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BODY;
+            DBG("ws mask\r\n");
+        }
+        break;
+    case HTTPDMODE_WEBSOCKET_BODY:
+        // payload
+        if (_httpd[cid].websocket_flg & 0x0080) {
+            // un-mask
+            _httpd[cid].buf->queue(c ^ _httpd[cid].websocket_mask[_httpd[cid].n & 0x03]); 
+        } else {
+            _httpd[cid].buf->queue(c); 
+        }
+        _httpd[cid].n ++;
+        if (_httpd[cid].n >= _httpd[cid].length) {
+            _httpd[cid].mode = HTTPDMODE_WEBSOCKET_ENTER;
+            _con[cid].received = true;
+        }
+        break;
+    }
+}
+
+int GSwifi::wsParseRequest (int cid) {
+    int i;
+
+    DBG("ws opcode %d\r\n", _httpd[cid].websocket_opcode);
+    switch (_httpd[cid].websocket_opcode) {
+    case 0x00: // continuation
+        break;
+    case 0x01: // text
+    case 0x02: // binary
+        i = httpdGetHandler(_httpd[cid].uri);
+        if (i >= 0) {
+            if (_httpd_handler[i].func) {
+                // cgi
+                _httpd_handler[i].func(cid);
+            }
+        }
+        break;
+    case 0x08: // close
+        close(cid);
+        break;
+    case 0x09: // ping
+        {
+        char pong[_httpd[cid].n + 2];
+        pong[0] = 0x8a;
+        pong[1] = 0x04;
+        for (i = 0; i < _httpd[cid].length; i ++) {
+            if (_httpd[cid].buf->dequeue(&pong[i + 2]) == false) break;
+        }
+        send(cid, pong, _httpd[cid].length + 2);
+        }
+        break;
+    case 0x0a: // pong
+        break;
+    default:
+        break;
+    }
+    _httpd[cid].n = 0;
+    _httpd[cid].length = 0;
+    return 0;
+}
+
+int GSwifi::wsAccept (int cid) {
+    char buf[CFG_CMD_SIZE], buf2[CFG_CMD_SIZE];
+    
+    DBG("websocket accept: %d\r\n", cid);
+
+    strcpy(buf, "HTTP/1.1 101 Switching Protocols\r\n");
+    send(cid, buf, strlen(buf));
+    strcpy(buf, "Upgrade: websocket\r\n");
+    send(cid, buf, strlen(buf));
+    strcpy(buf, "Connection: Upgrade\r\n");
+    send(cid, buf, strlen(buf));
+
+    strcpy(buf, "Sec-WebSocket-Accept: ");
+    send(cid, buf, strlen(buf));
+    strcpy(buf, _httpd[cid].websocket_key);
+    strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
+    sha1(buf, strlen(buf), buf2);
+    base64encode(buf2, 20, buf, sizeof(buf));
+    send(cid, buf, strlen(buf));
+    strcpy(buf, "\r\n\r\n");
+    send(cid, buf, strlen(buf));
+    return 0;
+}
+
+#endif
+#endif