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/

Files at this revision

API Documentation at this revision

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

CBuffer.h Show annotated file Show diff for this revision Revisions of this file
GSFunctionPointer.h Show annotated file Show diff for this revision Revisions of this file
GSwifi.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi.h Show annotated file Show diff for this revision Revisions of this file
GSwifi_conf.h Show annotated file Show diff for this revision Revisions of this file
GSwifi_http.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi_httpd.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi_smtp.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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();