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)

Files at this revision

API Documentation at this revision

Comitter:
gsfan
Date:
Fri Nov 22 14:03:07 2013 +0000
Parent:
11:71d67fea5ace
Child:
13:189e04ac70bd
Commit message:
add more function (smtp, http, httpd, websocket); fix some function;

Changed in this revision

GSwifi/CBuffer.h Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi.h Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_at.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_conf.h Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_hal.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_http.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_httpd.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_httpd_util.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_httpd_ws.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_msg.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_smtp.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_sock.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/GSwifi_util.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/sha1.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi/sha1.h Show annotated file Show diff for this revision Revisions of this file
GSwifiInterface.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/GSwifi/CBuffer.h	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/CBuffer.h	Fri Nov 22 14:03:07 2013 +0000
@@ -41,8 +41,9 @@
 
     void queue(T k) {
         if (isFull()) {
-            read++;
-            read %= size;
+//            read++;
+//            read %= size;
+            return;
         }
         buf[write++] = k;
         write %= size;
--- a/GSwifi/GSwifi.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -63,6 +63,7 @@
         strncpy(_state.name, CFG_DHCPNAME, sizeof(_state.name));
     }
     clearFlags();
+    _state.mode = MODE_COMMAND;
     sendCommand(NULL, RES_NULL, 0);
     if (cmdE(false)) return -1;
     if (_flow) {
@@ -156,6 +157,7 @@
     _state.wm = WM_ADHOCK;
     _state.initialized = true;
     clearFlags();
+    _state.mode = MODE_COMMAND;
     sendCommand(NULL, RES_NULL, 0);
     if (cmdE(false)) return -1;
     if (_flow) {
@@ -204,6 +206,7 @@
         strncpy(_state.name, CFG_DNSNAME, sizeof(_state.name));
     }
     clearFlags();
+    _state.mode = MODE_COMMAND;
     sendCommand(NULL, RES_NULL, 0);
     if (cmdE(false)) return -1;
     if (_flow) {
@@ -245,7 +248,7 @@
     return r;
 }
 
-int GSwifi::disconnect()
+int GSwifi::dissociate()
 {
     int i;
 
@@ -274,7 +277,7 @@
 
 }
 
-bool GSwifi::isConnected()
+bool GSwifi::isAssociated()
 {
     return _state.associated;
 }
@@ -283,7 +286,7 @@
 #ifndef CFG_ENABLE_RTOS
     static int t = 0;
 
-    if (_state.wm == WM_INFRASTRUCTURE && (! isConnected()) && _state.ssid) {
+    if (_state.wm == WM_INFRASTRUCTURE && (! isAssociated()) && _state.ssid) {
       if (t && time(NULL) > t) {
         // Wi-Fi re-associate
         if (_state.initialized) {
@@ -306,7 +309,7 @@
             t = time(NULL) + CFG_RECONNECT;
     }
 #else
-    if (_state.wm == WM_INFRASTRUCTURE && (! isConnected()) && _state.ssid) {
+    if (_state.wm == WM_INFRASTRUCTURE && (! isAssociated()) && _state.ssid) {
         // Wi-Fi re-associate
         if (_state.initialized) {
             if (!cmdWA(_state.ssid)) {
@@ -317,6 +320,20 @@
         }
     }
 #endif
+
+    for (int i = 0; i < 16; i ++) {
+        if (isConnected(i) && _con[i].received && _con[i].buf)
+          if (_con[i].func != NULL && !_con[i].buf->isEmpty()) {
+            _con[i].func(i);
+            if (_con[i].buf->isEmpty()) {
+                _con[i].received = false;
+            }
+        }
+    }
+
+#ifdef CFG_ENABLE_HTTPD
+    httpdPoll();
+#endif
 }
 
 #ifdef CFG_ENABLE_RTOS
@@ -330,7 +347,7 @@
         Thread::signal_wait(1);
         Thread::wait(1000);
         INFO("disassociated");
-        while (!_wifi->isConnected()){
+        while (!_wifi->isAssociated()){
             _wifi->poll();
             Thread::wait(CFG_TIMEOUT);
         }
@@ -338,6 +355,22 @@
 }
 #endif
 
+GSwifi::Status GSwifi::getStatus () {
+    return _state.status;
+}
+
+int GSwifi::setMacAddress (const char *mac) {
+    if (cmdNMAC(mac)) return -1;
+    strncpy(_state.mac, mac, sizeof(_state.mac));
+    return 0;
+}
+
+int GSwifi::getMacAddress (char *mac) {
+    if (cmdNMAC()) return -1;
+    strcpy(mac, _state.mac);
+    return 0;
+}
+
 int GSwifi::setAddress (const char *name) {
     _state.dhcp = true;
     strncpy(_state.name, name, sizeof(_state.name));
--- a/GSwifi/GSwifi.h	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi.h	Fri Nov 22 14:03:07 2013 +0000
@@ -42,9 +42,6 @@
 #include "rtos.h"
 #endif
 
-#define MSG_TABLE_NUM 15
-#define RES_TABLE_NUM 10
-
 //Debug is disabled by default
 #if defined(DEBUG) and (!defined(TARGET_LPC11U24))
 #define DBG(x, ...) std::printf("[DBG]" x "\r\n", ##__VA_ARGS__);
@@ -146,10 +143,10 @@
      * \param cts mbed pin to use for cts line of Serial interface
      * \param rts mbed pin to use for rts line of Serial interface
      * \param reset reset pin of the wifi module
-     * \param alarm alarm pin of the wifi module
-     * \param baud baud rate of Serial interface
+     * \param alarm alarm pin of the wifi module (default NULL)
+     * \param baud baud rate of Serial interface (default 9600)
      */
-    GSwifi (PinName tx, PinName rx, PinName cts, PinName rts, PinName reset, PinName alarm, int baud);
+    GSwifi (PinName tx, PinName rx, PinName cts, PinName rts, PinName reset, PinName alarm = NC, int baud = 9600);
 
     /** Connect the wifi module to the ssid contained in the constructor.
      * @param sec Security type (NONE, WEP_128 or WPA)
@@ -178,18 +175,51 @@
     /** Disconnect the wifi module from the access point
      * @returns 0 if successful
      */
-    int disconnect ();
+    int dissociate ();
+    int disconnect () {
+        return dissociate();
+    }
     
-    /** Check if a tcp link is active
+    /** Check if a Wi-Fi link is active
      * @returns true if successful
      */
-    bool isConnected();
+    bool isAssociated();
 
+    /** polling if not use rtos
+     */
     void poll ();
 
+    /** get Wi-Fi modue status
+     * @return Status
+     */
+    Status getStatus ();
+
+    /** set MAC address
+     */
+    int setMacAddress (const char *mac);
+    /** get MAC address
+     */
+    int getMacAddress (char *mac);
+
+    /** use DHCP
+     */
     int setAddress (const char *name = NULL);
+    /** use static IP address
+     * @param ip my ip address (dhcp start address)
+     * @param netmask subnet mask
+     * @param gateway default gateway
+     * @param dns my host name (default NULL)
+     */
     int setAddress (const char *ip, const char *netmask, const char *gateway, const char *name = NULL);
+    /** get IP address
+     */
     int getAddress (char *ip, char *netmask, char *gateway);
+
+    /** set Wi-Fi security parameter
+     * @param sec Security
+     * @param ssid SSID
+     * @param pass pass phrase
+     */
     int setSsid (Security sec, const char *ssid, const char *phrase);
 
     static GSwifi * getInstance() {
@@ -199,7 +229,7 @@
     // ----- GSwifi_util.cpp -----
     int setRegion (int reg);
 
-    /** RSSI
+    /** get RSSI
      * @return RSSI (dBm)
      */
     int getRssi ();
@@ -266,12 +296,12 @@
     /** TCP/UDP client
      * @return CID, -1:failure
      */
-    int open (Protocol proto, const char *ip, int port, int src = 0);
+    int open (Protocol proto, const char *ip, int port, int src = 0, void(*func)(int) = NULL);
 
     /** TCP/UDP server
      * @return CID, -1:failure
      */
-    int listen (Protocol proto, int port);
+    int listen (Protocol proto, int port, void(*func)(int) = NULL);
 
     /** close client/server
      */
@@ -281,8 +311,7 @@
      */
     int send (int cid, const char *buf, int len);
 
-    /*
-     * send data udp(s)
+    /** send data udp(s)
      */
     int sendto (int cid, const char *buf, int len, const char *ip, int port);
 
@@ -308,12 +337,70 @@
     int getRemote(int cid, char **ip, int *port);
 
     // ----- GSwifi_http.cpp -----
-    int httpGet (const char *host, int port, const char *uri, bool ssl = false, const char *user = NULL, const char *pwd = NULL);
-    int httpPost (const char *host, int port, const char *uri, const char *body, bool ssl = false, const char *user = NULL, const char *pwd = NULL);
+    /** http request (GET method)
+     */
+    int httpGet (const char *host, int port, const char *uri, bool ssl = false, const char *user = NULL, const char *pwd = NULL, void(*func)(int) = NULL);
+    int httpGet (const char *host, int port, const char *uri, void(*func)(int) = NULL) {
+        return httpGet(host, port, uri, false, NULL, NULL, func);
+    }
+    /** http request (POST method)
+     */
+    int httpPost (const char *host, int port, const char *uri, const char *body, bool ssl = false, const char *user = NULL, const char *pwd = NULL, void(*func)(int) = NULL);
+    int httpPost (const char *host, int port, const char *uri, const char *body, void(*func)(int) = NULL) {
+        return httpPost(host, port, uri, body, false, NULL, NULL, func);
+    }
+
     int base64encode (const char *input, int length, char *output, int len);
     int urlencode (const char *str, char *buf, int len);
     int urldecode (const char *str, char *buf, int len);
 
+#ifdef CFG_ENABLE_HTTPD
+    // ----- GSwifi_httpd.cpp -----
+    /** start http server
+     * @param port
+     */
+    int httpd (int port = 80);
+
+    // ----- GSwifi_httpd_util.cpp -----
+    /** attach uri to dirctory handler
+     */
+    void httpdError (int cid, int err);
+    /** attach uri to dirctory handler
+     */
+    int httpdAttach (const char *uri, const char *dir);
+    /** attach uri to cgi handler
+     */
+    int httpdAttach (const char *uri, void (*funcCgi)(int));
+#endif
+
+#ifdef CFG_ENABLE_WEBSOCKET
+    // ----- GSwifi_httpd_ws.cpp -----
+    /** websocket request (Upgrade method)
+     * @return CID, -1:failure
+     */
+    int wsOpen (const char *host, int port, const char *uri, const char *user = NULL, const char *pwd = NULL);
+    /** send websocket data
+     */
+    int wsSend (int cid, const char *buf, int len, const char *mask = NULL);
+#endif
+
+#ifdef CFG_ENABLE_SMTP
+    // ----- GSwifi_smtp.cpp -----
+    /** send mail (smtp)
+     * @param host SMTP server
+     * @param port SMTP port (25 or 587 or etc.)
+     * @param to To address
+     * @param from From address
+     * @param subject Subject
+     * @param mesg Message
+     * @param user username (SMTP Auth)
+     * @param pwd password (SMTP Auth)
+     * @retval 0 success
+     * @retval -1 failure
+     */
+    int mail (const char *host, int port, const char *to, const char *from, const char *subject, const char *mesg, const char *user = NULL, const char *pwd = NULL);
+#endif
+
     // ----- GSwifi_msg.cpp -----
 
     // ----- GSwifi_at.cpp -----
@@ -353,6 +440,8 @@
     LPC_UART1_TypeDef *_uart;
 #elif defined(TARGET_LPC11U24)
     LPC_USART_Type *_uart;
+#elif defined(TARGET_LPC11XX)
+    LPC_UART_TypeDef *_uart;
 #endif
     DigitalInOut _reset;
     DigitalInOut *_alarm;
@@ -395,20 +484,110 @@
         volatile bool received;
         volatile int parent;
         volatile bool accept;
+        void(*func)(int);
     } _con[16];
 
+#ifdef CFG_ENABLE_HTTPD
+    enum HttpdMode {
+        HTTPDMODE_REQUEST,
+        HTTPDMODE_REQUEST_STR,
+        HTTPDMODE_HEADER,
+        HTTPDMODE_BODY,
+        HTTPDMODE_ENTER,
+        HTTPDMODE_ERROR,
+        HTTPDMODE_WEBSOCKET,
+        HTTPDMODE_WEBSOCKET_MASK,
+        HTTPDMODE_WEBSOCKET_BODY,
+        HTTPDMODE_WEBSOCKET_ENTER,
+    };
+
+    enum HttpdReq {
+        REQ_HTTPGET,
+        REQ_HTTPPOST,
+    };
+
+    struct HTTPD {
+        HttpdMode mode;
+        HttpdReq req;
+        CircBuffer <char>*buf;
+        char *uri;
+        char *filename;
+        char *querystring;
+        int enter;
+        int length;
+        int n;
+        int keepalive;
+#ifdef CFG_ENABLE_WEBSOCKET
+        int websocket;
+        char *websocket_key;
+        int websocket_opcode;
+        int websocket_flg;
+        char websocket_mask[4];
+        int websocket_payload;
+#endif
+    } _httpd[16];
+
+    struct HTTPD_HANDLER {
+        char *uri;
+        char *dir;
+        void (*func)(int);
+    } _httpd_handler[CFG_HTTPD_HANDLER_NUM];
+
+    int _httpd_cid;
+    int _handler_count;
+#endif // CFG_ENABLE_HTTPD
+
 
     // ----- GSwifi.cpp -----
 #ifdef CFG_ENABLE_RTOS
     static void threadPoll (void const *args);
 #endif
 
+    // ----- GSwifi_sock.cpp -----
+    void initCon (int cid, bool connected);
+
     // ----- GSwifi_util.cpp -----
     int x2i (char c);
     char i2x (int i);
     int from_hex (int ch);
     int to_hex (int code);
 
+    // ----- GSwifi_http.cpp -----
+
+#ifdef CFG_ENABLE_HTTPD
+    // ----- GSwifi_httpd.cpp -----
+    void httpdRecvData (int cid, char c);
+    int httpdParseRequest (int cid);
+    void httpdPoll ();
+    int httpdParseHeader (int cid);
+    void reqContentLength (int cid, const char *buf);
+    void reqConnection (int cid, const char *buf);
+    void reqUpgrade (int cid, const char *buf);
+    void reqWebSocketVersion (int cid, const char *buf);
+    void reqWebSocketKey (int cid, const char *buf);
+
+    // ----- GSwifi_httpd_util.cpp -----
+    int httpdFile (int cid, char *dir);
+    int httpdGetHandler (const char *uri);
+    char *mimetype (char *file);
+    int strnicmp (const char *p1, const char *p2, int n);
+#endif
+
+#ifdef CFG_ENABLE_WEBSOCKET
+    // ----- GSwifi_httpd_ws.cpp -----
+    int wsWait (int cid, int code);
+#ifdef CFG_ENABLE_HTTPD
+    void wsRecvData (int cid, char c);
+    int wsParseRequest (int cid);
+    int wsAccept (int cid);
+#endif
+#endif
+
+#ifdef CFG_ENABLE_SMTP
+    // ----- GSwifi_smtp.cpp -----
+    int smtpWait (int cid, int code);
+#endif
+
     // ----- GSwifi_msg.cpp -----
     void recvData (char c);
     int parseMessage ();
@@ -430,6 +609,7 @@
     void resTime (const char*);
     void resChannel (const char*);
     void resStatus (const char*);
+    void resHttp (const char *buf);
 
     // ----- GSwifi_at.cpp -----
     void clearFlags ();
--- a/GSwifi/GSwifi_at.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_at.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -331,7 +331,7 @@
     } else {
         sprintf(cmd, "AT+HTTPOPEN=%s,%d", s, n);
     }
-    return sendCommand(cmd, RES_CONNECT, CFG_TIMEOUT);
+    return sendCommand(cmd, RES_HTTP, CFG_TIMEOUT);
 }
 
 int GSwifi::cmdHTTPSEND (int n, bool m, const char *s, int t) {
@@ -341,7 +341,7 @@
     } else {
         sprintf(cmd, "AT+HTTPSEND=%d,1,%d,%s", n, CFG_TIMEOUT / 1000, s);
     }
-    return sendCommand(cmd, RES_CONNECT, CFG_TIMEOUT);
+    return sendCommand(cmd);
 }
 
 int GSwifi::cmdHTTPCLOSE (int n) {
--- a/GSwifi/GSwifi_conf.h	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_conf.h	Fri Nov 22 14:03:07 2013 +0000
@@ -1,8 +1,13 @@
 
-#define DEBUG
+//#define DEBUG
+//#define DEBUG_DUMP
 
 #define CFG_ENABLE_RTOS
+//#define CFG_ENABLE_HTTPD
+//#define CFG_ENABLE_WEBSOCKET
+//#define CFG_ENABLE_SMTP
 //#define CFG_UART_DIRECT
+
 #define CFG_UART_BAUD 9600
 #define CFG_WREGDOMAIN 2 // 0:FCC, 1:ETSI, 2:TELEC
 #define CFG_DHCPNAME "mbed-gswifi"
@@ -13,11 +18,17 @@
 #define DEFAULT_WAIT_RESP_TIMEOUT 500
 #define CFG_TIMEOUT 30000 // ms
 
-#define CFG_CMD_SIZE 100
-#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+#define CFG_CMD_SIZE 128
+
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_LPC176X)
 #define CFG_DATA_SIZE 1024
-#elif defined(TARGET_LPC11U24)
-#define CFG_DATA_SIZE 128
-#elif defined(TARGET_LPC4088)
+#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC1114) || defined(TARGET_LPC11XX)
+#define CFG_DATA_SIZE 256
+#elif defined(TARGET_LPC4088) || defined(TARGET_LPC408X)
 #define CFG_DATA_SIZE 4096
+#elif defined(TARGET_KL25Z)
+#define CFG_DATA_SIZE 512
 #endif
+
+#define CFG_HTTPD_HANDLER_NUM 10
+#define CFG_HTTPD_KEEPALIVE 10
--- a/GSwifi/GSwifi_hal.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_hal.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -101,7 +101,7 @@
         t.start();
         while (_state.mode != MODE_COMMAND) {
             if (t.read_ms() >= ms) {
-                WARN("lock timeout\r\n");
+                WARN("lock timeout (%d)\r\n", _state.mode);
                 return -1;
             }
         }
@@ -155,7 +155,6 @@
     if (_baud) _gs.baud(_baud);
     _gs.attach(this, &GSwifi::isrUart, Serial::RxIrq);
 
-    _uart = NULL;
     _cts = NULL;
     _rts = NULL;
     _flow = 0;
--- a/GSwifi/GSwifi_http.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_http.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -18,11 +18,11 @@
 
 #include "GSwifi.h"
 
-int GSwifi::httpGet (const char *host, int port, const char *uri, bool ssl, const char *user, const char *pwd) {
+int GSwifi::httpGet (const char *host, int port, const char *uri, bool ssl, const char *user, const char *pwd, void(*func)(int)) {
     char ip[17];
     int cid;
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     if (getHostByName(host, ip)) return -1;
     if (! port) {
@@ -53,17 +53,18 @@
     cid = _state.cid;
     _con[cid].protocol = PROTO_HTTPGET;
     _con[cid].type = TYPE_CLIENT;
+    _con[cid].func = func;
 
     cmdHTTPSEND(cid, false, uri); // GET
     return cid;
 }
 
-int GSwifi::httpPost (const char *host, int port, const char *uri, const char *body, bool ssl, const char *user, const char *pwd) {
+int GSwifi::httpPost (const char *host, int port, const char *uri, const char *body, bool ssl, const char *user, const char *pwd, void(*func)(int)) {
     char cmd[CFG_CMD_SIZE];
     char ip[17];
     int cid, len;
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     if (getHostByName(host, ip)) return -1;
     if (! port) {
@@ -96,6 +97,7 @@
     cid = _state.cid;
     _con[cid].protocol = PROTO_HTTPPOST;
     _con[cid].type = TYPE_CLIENT;
+    _con[cid].func = func;
 
     cmdHTTPSEND(cid, true, uri, len); // POST
     sprintf(cmd, "\x1bH%X", cid);
@@ -104,7 +106,6 @@
 }
 
 
-
 /* base64encode code from 
  * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/GSwifi_httpd.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -0,0 +1,294 @@
+/* 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_HTTPD
+
+int GSwifi::httpd (int port) {
+    int i;
+
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
+
+    memset(&_httpd, 0, sizeof(_httpd));
+    for (i = 0; i < 16; i ++) {
+        _httpd[i].mode = HTTPDMODE_REQUEST;
+    }
+    _handler_count = 0;
+
+    _httpd_cid = listen(PROTO_TCP, port);
+    if (_httpd_cid < 0) return -1;
+
+    _con[_httpd_cid].protocol = PROTO_HTTPD;
+    return _httpd_cid;
+}
+
+void GSwifi::httpdRecvData (int cid, char c) {
+
+    switch (_httpd[cid].mode) {
+    case HTTPDMODE_REQUEST:
+        if (_con[cid].buf == NULL)
+            _con[cid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
+        _httpd[cid].buf = _con[cid].buf;
+        _httpd[cid].buf->flush();
+        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
+            _httpd[cid].buf->queue(c);
+            _httpd[cid].mode = HTTPDMODE_REQUEST_STR;
+        }
+        break;
+    case HTTPDMODE_REQUEST_STR:
+        switch (c) {
+        case 0:
+        case 0x0d: // CR
+            break;
+        case 0x0a: // LF
+            if (httpdParseRequest(cid)) {
+                _httpd[cid].mode = HTTPDMODE_REQUEST_STR;
+            } else {
+                _httpd[cid].mode = HTTPDMODE_HEADER;
+            }
+            _httpd[cid].enter = 0;
+            break;
+        default:
+            _httpd[cid].buf->queue(c);
+            break;
+        }
+        break;
+    case HTTPDMODE_HEADER:
+        switch (c) {
+        case 0:
+        case 0x0d: // CR
+            break;
+        case 0x0a: // LF
+            if (_httpd[cid].buf->available() == 0) {
+//                if ((_httpd[cid].enter == 0x0d && c == 0x0a) || (_httpd[cid].enter == 0x0a && c == 0x0a)) {
+                if (_httpd[cid].enter == 0x0a && c == 0x0a) {
+                    _httpd[cid].buf->flush();
+#ifdef CFG_ENABLE_WEBSOCKET
+                    if (_httpd[cid].websocket) {
+                        INFO("MODE_WEBSOCKET");
+                        wsAccept(cid);
+                        _httpd[cid].mode = HTTPDMODE_WEBSOCKET;
+                    } else
+#endif
+                    if (_httpd[cid].length) {
+                        INFO("MODE_BODY");
+                        _httpd[cid].mode = HTTPDMODE_BODY;
+                    } else {
+                        INFO("MODE_ENTER");
+                        _httpd[cid].mode = HTTPDMODE_ENTER;
+                        _con[cid].received = true;
+                    }
+                }
+                _httpd[cid].buf->flush();
+                _httpd[cid].enter = c;
+                break;
+            }
+
+            httpdParseHeader(cid);
+            _httpd[cid].enter = c;
+            break;
+        default:
+            _httpd[cid].buf->queue(c);
+            _httpd[cid].enter = 0;
+            break;
+        }
+        break;
+    case HTTPDMODE_BODY:
+        _httpd[cid].buf->queue(c);
+        if (_httpd[cid].buf->available() >= _httpd[cid].length) {
+            _httpd[cid].mode = HTTPDMODE_ENTER;
+            _con[cid].received = true;
+        }
+        break;
+#ifdef CFG_ENABLE_WEBSOCKET
+    case HTTPDMODE_WEBSOCKET:
+    case HTTPDMODE_WEBSOCKET_MASK:
+    case HTTPDMODE_WEBSOCKET_BODY:
+        wsRecvData(cid, c);
+        break;
+#endif
+    }
+}
+
+void GSwifi::httpdPoll () {
+    for (int cid = 0; cid < 16; cid ++) {
+        if (isConnected(cid) && _con[cid].protocol == PROTO_HTTPD) {
+
+    if (_httpd[cid].mode == HTTPDMODE_ENTER) {
+        int i = httpdGetHandler(_httpd[cid].uri);
+        if (i >= 0) { 
+            if (_httpd_handler[i].dir) {
+                // file
+                httpdFile(cid, _httpd_handler[i].dir);
+            } else
+            if (_httpd_handler[i].func) {
+                // cgi
+                _httpd_handler[i].func(cid);
+//                _httpd[cid].keepalive = 0;
+            } else {
+                httpdError(cid, 403);
+            }
+        } else {
+            httpdError(cid, 404);
+        }
+
+        if (_httpd[cid].keepalive) {
+            DBG("keepalive %d", _httpd[cid].keepalive);
+            _httpd[cid].keepalive --;
+        } else {
+            close(cid);
+        }
+        _httpd[cid].mode = HTTPDMODE_REQUEST;
+#ifdef CFG_ENABLE_WEBSOCKET
+    } else
+    if (_httpd[cid].mode == HTTPDMODE_WEBSOCKET_ENTER) {
+        wsParseRequest(cid);
+        _httpd[cid].mode = HTTPDMODE_WEBSOCKET;
+#endif
+    }
+
+        }
+    }
+}
+
+int GSwifi::httpdParseRequest (int cid) {
+    int i, j, len;
+    char buf[CFG_CMD_SIZE];
+
+    for (len = 0; len < sizeof(buf); len++) {
+        if (_httpd[cid].buf->dequeue(&buf[len]) == false) break;
+    }
+    buf[len] = 0;
+
+    if (strnicmp(buf, "GET ", 4) == 0) {
+        _httpd[cid].req = REQ_HTTPGET;
+        j = 4;
+    } else
+    if (strnicmp(buf, "POST ", 5) == 0) {
+        _httpd[cid].req = REQ_HTTPPOST;
+        j = 5;
+    } else {
+        return -1;
+    }
+
+    if (_httpd[cid].uri == NULL)
+        _httpd[cid].uri = (char*)malloc(CFG_CMD_SIZE);
+
+    for (i = 0; i < len - j; i ++) {
+        _httpd[cid].uri[i] = buf[i + j];
+        if (buf[i + j] == ' ' || i >= CFG_CMD_SIZE - 1) {
+            _httpd[cid].uri[i] = 0;
+            INFO("URI %d '%s'", _httpd[cid].req, _httpd[cid].uri);
+            _httpd[cid].mode = HTTPDMODE_HEADER;
+            _httpd[cid].buf->flush();
+            _httpd[cid].length = 0;
+            _httpd[cid].n = 0;
+            _httpd[cid].filename = NULL;
+            _httpd[cid].querystring = NULL;
+#ifdef CFG_ENABLE_WEBSOCKET
+            _httpd[cid].websocket = 0;
+#endif
+            break;
+        }
+    }
+
+    i = httpdGetHandler(_httpd[cid].uri);
+    if (i >= 0) { 
+        _httpd[cid].filename = &_httpd[cid].uri[strlen(_httpd_handler[i].uri)];
+        for (i = 0; i < strlen(_httpd[cid].filename); i ++) {
+            if (_httpd[cid].filename[i] == '?') {
+                _httpd[cid].filename[i] = 0;
+                _httpd[cid].querystring = _httpd[cid].filename + i + 1;
+                break;
+            }
+        }
+        INFO("FILE '%s' QUERY '%s'", _httpd[cid].filename, _httpd[cid].querystring);
+    }
+    return 0;
+}
+
+#define HEADER_TABLE_NUM 5
+int GSwifi::httpdParseHeader (int cid) {
+    int i;
+    char buf[CFG_CMD_SIZE];
+    static const struct HEADER_TABLE {
+        const char header[24];
+        void (GSwifi::*func)(int id, const char*);
+    } header_table[HEADER_TABLE_NUM] = {
+      {"Content-Length:",         &GSwifi::reqContentLength},
+      {"Connection:",             &GSwifi::reqConnection},
+      {"Upgrade: websocket",      &GSwifi::reqUpgrade},
+      {"Sec-WebSocket-Version:",  &GSwifi::reqWebSocketVersion},
+      {"Sec-WebSocket-Key:",      &GSwifi::reqWebSocketKey},
+    };
+    for (i = 0; i < sizeof(buf); i++) {
+        if (_httpd[cid].buf->dequeue(&buf[i]) == false) break;
+    }
+    buf[i] = 0;
+
+    for (i = 0; i < HEADER_TABLE_NUM; i ++) {
+        if (strnicmp(buf, header_table[i].header, strlen(header_table[i].header)) == 0) {
+            DBG("parse header %d '%s'\r\n", i, buf);
+            if (header_table[i].func != NULL) {
+                (this->*(header_table[i].func))(cid, buf);
+            }
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+void GSwifi::reqContentLength (int cid, const char *buf) {
+    _httpd[cid].length = atoi(&buf[16]);
+}
+
+void GSwifi::reqConnection (int cid, const char *buf) {
+    if (strnicmp(&buf[12], "Keep-Alive", 10) == 0 && _httpd[cid].keepalive == 0) {
+        _httpd[cid].keepalive = CFG_HTTPD_KEEPALIVE;
+    } else {
+        _httpd[cid].keepalive = 0;
+    }
+}
+
+#ifdef CFG_ENABLE_WEBSOCKET
+void GSwifi::reqUpgrade (int cid, const char *buf) {
+    if (! _httpd[cid].websocket) _httpd[cid].websocket = 1;
+}
+
+void GSwifi::reqWebSocketVersion (int cid, const char *buf) {
+    _httpd[cid].websocket = atoi(&buf[23]);
+}
+
+void GSwifi::reqWebSocketKey (int cid, const char *buf) {
+    if (_httpd[cid].websocket_key == NULL) {
+        _httpd[cid].websocket_key = (char*)malloc(30);
+    }
+    strncpy(_httpd[cid].websocket_key, &buf[19], 30);
+}
+#else
+void GSwifi::reqUpgrade (int cid, const char *buf) {
+}
+void GSwifi::reqWebSocketVersion (int cid, const char *buf) {
+}
+void GSwifi::reqWebSocketKey (int cid, const char *buf) {
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/GSwifi_httpd_util.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -0,0 +1,196 @@
+/* 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_HTTPD
+
+int GSwifi::httpdFile (int cid, char *dir) {
+    FILE *fp;
+    int i, len;
+    char buf[CFG_DATA_SIZE];
+    char file[CFG_CMD_SIZE];
+
+    INFO("httpdFile %d %s", cid, dir);
+
+    strcpy(file, dir);
+    strcat(file, _httpd[cid].filename);
+    if (file[strlen(file) - 1] == '/') {
+        strcat(file, "index.html");
+    }
+    DBG("file: %s\r\n", file);
+
+    fp = fopen(file, "r");
+    if (fp) {
+        strcpy(buf, "HTTP/1.1 200 OK\r\n");
+        send(cid, buf, strlen(buf));
+        {
+            // file size
+            i = ftell(fp);
+            fseek(fp, 0, SEEK_END);
+            len = ftell(fp);
+            fseek(fp, i, SEEK_SET);
+        }
+
+        strcpy(buf, "Server: GSwifi httpd\r\n");
+        send(cid, buf, strlen(buf));
+        if (_httpd[cid].keepalive) {
+            strcpy(buf, "Connection: Keep-Alive\r\n");
+        } else {
+            strcpy(buf, "Connection: close\r\n");
+        }
+        send(cid, buf, strlen(buf));
+        sprintf(buf, "Content-Type: %s\r\n", mimetype(file));
+        send(cid, buf, strlen(buf));
+        sprintf(buf, "Content-Length: %d\r\n\r\n", len);
+        send(cid, buf, strlen(buf));
+
+        for (;;) {
+            i = fread(buf, sizeof(char), sizeof(buf), fp);
+            if (i <= 0) break;
+            send(cid, buf, i);
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+            if (feof(fp)) break;
+#endif
+        }
+        fclose(fp);
+        return 0;
+    }
+
+    httpdError(cid, 404);
+    return -1;
+}
+
+void GSwifi::httpdError (int cid, int err) {
+    char buf[CFG_CMD_SIZE], msg[30];
+    
+    switch (err) {
+    case 400:
+        strcpy(msg, "Bad Request");
+        break;
+    case 403:
+        strcpy(msg, "Forbidden");
+        break;
+    case 404:
+        strcpy(msg, "Not Found");
+        break;
+    case 500:
+    default:
+        strcpy(msg, "Internal Server Error");
+        break;
+    }
+    DBG("httpd error: %d %d %s\r\n", cid, err, msg);
+    
+    sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg);
+    send(cid, buf, strlen(buf));
+    strcpy(buf, "Content-Type: text/html\r\n\r\n");
+    send(cid, buf, strlen(buf));
+
+    sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg);
+    send(cid, buf, strlen(buf));
+    sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg);
+    send(cid, buf, strlen(buf));
+    wait_ms(100);
+    close(cid);
+//    WARN("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]);
+//    WARN("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err);
+}
+
+int GSwifi::httpdGetHandler (const char *uri) {
+    int i;
+ 
+    for (i = 0; i < _handler_count; i ++) {
+        if (strncmp(uri, _httpd_handler[i].uri, strlen(_httpd_handler[i].uri)) == NULL) {
+            // found
+            return i;
+        }
+    }
+    return -1;
+}
+
+int GSwifi::httpdAttach (const char *uri, const char *dir) {
+    if (_handler_count < CFG_HTTPD_HANDLER_NUM) {
+        _httpd_handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
+        strcpy(_httpd_handler[_handler_count].uri, uri);
+        _httpd_handler[_handler_count].dir = (char*)malloc(strlen(dir) + 1);
+        strcpy(_httpd_handler[_handler_count].dir, dir);
+        _httpd_handler[_handler_count].func = NULL;
+        DBG("httpdAttach %s %s\r\n", _httpd_handler[_handler_count].uri, _httpd_handler[_handler_count].dir);
+        _handler_count ++;
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int GSwifi::httpdAttach (const char *uri, void (*funcCgi)(int)) {
+    if (_handler_count < CFG_HTTPD_HANDLER_NUM) {
+        _httpd_handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
+        strcpy(_httpd_handler[_handler_count].uri, uri);
+        _httpd_handler[_handler_count].dir = NULL;
+        _httpd_handler[_handler_count].func = funcCgi;
+        DBG("httpdAttach %s %08x\r\n", _httpd_handler[_handler_count].uri, _httpd_handler[_handler_count].func);
+        _handler_count ++;
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+
+#define MIMETABLE_NUM 9
+char *GSwifi::mimetype (char *file) {
+    static const struct MIMETABLE {
+        const char ext[5];
+        const char type[24];
+    } mimetable[MIMETABLE_NUM] = {
+        {"txt", "text/plain"},  // default
+        {"html", "text/html"},
+        {"htm", "text/html"},
+        {"css", "text/css"},
+        {"js", "application/javascript"},
+        {"jpg", "image/jpeg"},
+        {"png", "image/png"},
+        {"gif", "image/gif"},
+        {"ico", "image/x-icon"},
+    };
+    int i, j;
+
+    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 (char*)mimetable[i].type;
+        }
+    }
+    return (char*)mimetable[0].type;
+}
+
+int GSwifi::strnicmp (const char *p1, const char *p2, int n) {
+    int i, r = -1;
+    char c1, c2;
+    
+    for (i = 0; i < n; i ++) {
+        c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i];
+        c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i];
+        r = c1 - c2;
+        if (r) break;
+    }
+    return r;
+}
+#endif
--- /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
--- a/GSwifi/GSwifi_msg.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_msg.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -162,6 +162,7 @@
                     if (_con[cid].buf->available() > CFG_DATA_SIZE - 16) {
                         setRts(false);
                         _con[cid].received = true;
+                        WARN("buf full");
                     }
                 }
                 count ++;
@@ -180,7 +181,7 @@
             sub ++;
             len = 0;
             count = 0;
-            if (_state.mode == MODE_DATA_RX_BULK) {
+            if (_state.mode != MODE_DATA_RXUDP_BULK) {
                 sub = 3;
             }
             break;
@@ -215,11 +216,17 @@
             break;
         default:
             // data
+#ifdef CFG_ENABLE_HTTPD
+            if (_con[cid].protocol == PROTO_HTTPD) {
+                httpdRecvData(cid, c);
+            } else
+#endif
             if (_con[cid].buf != NULL) {
                 _con[cid].buf->queue(c);
                 if (_con[cid].buf->available() > CFG_DATA_SIZE - 16) {
                     setRts(false);
                     _con[cid].received = true;
+                    WARN("buf full");
                 }
             }
             count ++;
@@ -234,6 +241,8 @@
     }
 }
 
+#define MSG_TABLE_NUM 15
+#define RES_TABLE_NUM 10
 int GSwifi::parseMessage () {
     int i;
     char buf[256];
@@ -267,7 +276,7 @@
       {RES_MACADDRESS,  &GSwifi::resMacAddress},
       {RES_DHCP,        &GSwifi::resIp},
       {RES_DNSLOOKUP,   &GSwifi::resLookup},
-      {RES_HTTP,        &GSwifi::resConnect},
+      {RES_HTTP,        &GSwifi::resHttp},
       {RES_RSSI,        &GSwifi::resRssi},
       {RES_TIME,        &GSwifi::resTime},
       {RES_STATUS,      &GSwifi::resStatus},
@@ -344,15 +353,13 @@
         }
     }
 
-    // initalize
+    // initialize
+    initCon(acid, true);
     _con[acid].protocol = _con[cid].protocol;
     _con[acid].type = _con[cid].type;
     _con[acid].parent = cid;
+    _con[acid].func = _con[cid].func;
     _con[acid].accept = true;
-    if (_con[acid].buf == NULL)
-        _con[acid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
-    _con[acid].buf->flush();
-    _con[acid].connected = true;
 }
 
 void GSwifi::msgDisconnect (const char *buf) {
@@ -410,16 +417,10 @@
     if (strncmp(buf, "CONNECT ", 8) == 0 && buf[9] == 0) {
         cid = x2i(buf[8]);
         DBG("connect %d\r\n", cid);
-        // initalize
-        _con[cid].parent = -1;
-        _con[cid].accept = false;
-        if (_con[cid].buf == NULL)
-            _con[cid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
-        _con[cid].buf->flush();
-        _con[cid].connected = true;
+        // initialize
+        initCon(cid, true);
         _state.cid = cid;
         _state.res = RES_NULL;
-        return;
     }
 }
 
@@ -530,3 +531,17 @@
         _state.res = RES_NULL;
     }
 }
+
+void GSwifi::resHttp (const char *buf) {
+    int cid;
+
+    // http client socket
+    if (buf[0] >= '0' && buf[0] <= 'F' && buf[1] == 0) {
+        cid = x2i(buf[0]);
+        DBG("connect %d\r\n", cid);
+        // initialize
+        initCon(cid, true);
+        _state.cid = cid;
+        _state.res = RES_NULL;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/GSwifi_smtp.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -0,0 +1,145 @@
+/* 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_SMTP
+
+int GSwifi::mail (const char *host, int port, const char *to, const char *from, const char *subject, const char *mesg, const char *user, const char *pwd) {
+    int ret = -1;
+    int cid;
+    char cmd[CFG_DATA_SIZE];
+    char ip[17];
+
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
+
+    if (getHostByName(host, ip)) return -1;
+    if (! port) {
+        port = 25;
+    }
+
+    cid = open(PROTO_TCP, ip, port);
+    if (cid < 0) return -1;
+    DBG("cid %d\r\n", cid);
+
+    if (smtpWait(cid ,220)) goto exit;
+
+    // send request
+    snprintf(cmd, sizeof(cmd), "EHLO %s\r\n", _state.name);
+    send(cid, cmd, strlen(cmd));
+    wait_ms(100);
+    if (smtpWait(cid ,250)) goto quit;
+    smtpWait(cid ,0);
+
+    if (user && pwd) {
+        // smtp auth
+        int len;
+        snprintf(cmd, sizeof(cmd), "%s%c%s%c%s", user, 0, user, 0, pwd);
+        len = strlen(user) * 2 + strlen(pwd) + 2;
+        char tmp[len + (len / 2)];
+        base64encode(cmd, len, tmp, sizeof(tmp));
+        snprintf(cmd, sizeof(cmd), "AUTH PLAIN %s\r\n", tmp);
+        send(cid, cmd, strlen(cmd));
+        if (smtpWait(cid ,235)) goto quit;
+    }
+ 
+    snprintf(cmd, sizeof(cmd), "MAIL FROM: %s\r\n", from);
+    send(cid, cmd, strlen(cmd));
+    if (smtpWait(cid ,250)) goto quit;
+ 
+    snprintf(cmd, sizeof(cmd), "RCPT TO: %s\r\n", to);
+    send(cid, cmd, strlen(cmd));
+    if (smtpWait(cid ,250)) goto quit;
+ 
+    strcpy(cmd, "DATA\r\n");
+    send(cid, cmd, strlen(cmd));
+    if (smtpWait(cid ,354)) goto quit;
+ 
+    // mail data
+    snprintf(cmd, sizeof(cmd), "From: %s\r\n", from);
+    send(cid, cmd, strlen(cmd));
+    snprintf(cmd, sizeof(cmd), "To: %s\r\n", to);
+    send(cid, cmd, strlen(cmd));
+    snprintf(cmd, sizeof(cmd), "Subject: %s\r\n\r\n", subject);
+    send(cid, cmd, strlen(cmd));
+
+    send(cid, mesg, strlen(mesg));
+    strcpy(cmd, "\r\n.\r\n");
+    send(cid, cmd, strlen(cmd));
+    if (smtpWait(cid ,250)) goto quit;
+    ret = 0;
+
+    INFO("Mail, from: %s, to: %s %d\r\n", from, to, strlen(mesg));
+
+quit:
+    strcpy(cmd, "QUIT\r\n");
+    send(cid, cmd, strlen(cmd));
+    smtpWait(cid ,221);
+exit:
+    close(cid);
+    return ret;
+}
+
+int GSwifi::smtpWait (int cid, int code) {
+    Timer timeout;
+    int i, n, len = 0;
+    char buf[CFG_CMD_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;
+    DBG("smtp: %s\r\n", data);
+    timeout.stop();
+ 
+    // check return code
+    i = atoi(data);
+    DBG("smtp status %d\r\n", i);
+    return i == code ? 0 : -1;
+}
+
+#endif
--- a/GSwifi/GSwifi_sock.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_sock.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -22,7 +22,7 @@
 {
     int i, flg = 0;
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     for (i = 0; i < strlen(host); i ++) {
         if ((host[i] < '0' || host[i] > '9') && host[i] != '.') {
@@ -44,10 +44,10 @@
     return 0;
 }
 
-int GSwifi::open (Protocol proto, const char *ip, int port, int src) {
+int GSwifi::open (Protocol proto, const char *ip, int port, int src, void(*func)(int)) {
     int cid;
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     _state.cid = -1;
     if (proto == PROTO_TCP) {
@@ -59,13 +59,14 @@
     cid = _state.cid;
     _con[cid].protocol = proto;
     _con[cid].type = TYPE_CLIENT;
+    _con[cid].func = func;
     return cid;
 }
 
-int GSwifi::listen (Protocol proto, int port) {
+int GSwifi::listen (Protocol proto, int port, void(*func)(int)) {
     int cid;
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     _state.cid = -1;
     if (proto == PROTO_TCP) {
@@ -77,6 +78,7 @@
     cid = _state.cid;
     _con[cid].protocol = proto;
     _con[cid].type = TYPE_SERVER;
+    _con[cid].func = func;
     return cid;
 }
 
@@ -185,3 +187,15 @@
     *port = _con[cid].port;
     return 0;
 }
+
+void GSwifi::initCon (int cid, bool connected) {
+    _con[cid].parent = -1;
+    _con[cid].func = NULL;
+    _con[cid].accept = false;
+    if (_con[cid].buf == NULL) {
+        _con[cid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
+        if (_con[cid].buf == NULL) error("Can't allocate memory");
+    }
+    _con[cid].buf->flush();
+    _con[cid].connected = connected;
+}
--- a/GSwifi/GSwifi_util.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifi/GSwifi_util.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -87,7 +87,7 @@
 int GSwifi::ntpdate (char *host, int sec) {
     char ip[17];
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     if (getHostByName(host, ip)) return -1;
     return cmdNTIMESYNC(true, ip, sec);
@@ -99,7 +99,7 @@
 
 int GSwifi::provisioning (char *user, char *pass) {
 
-    if (!isConnected() && _state.status == STAT_READY) return -1;
+    if (!isAssociated() || _state.status != STAT_READY) return -1;
 
     return cmdWEBPROV(user, pass);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/sha1.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -0,0 +1,364 @@
+/*
+ * source from http://www.ipa.go.jp/security/rfc/RFC3174JA.html
+ */
+#include "sha1.h"
+
+/*
+ *  Define the SHA1 circular left shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+                (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/* Local Function Prototyptes */
+void SHA1PadMessage(SHA1Context *);
+void SHA1ProcessMessageBlock(SHA1Context *);
+
+/*
+ *  SHA1Reset
+ *
+ *  Description:
+ *      This function will initialize the SHA1Context in preparation
+ *      for computing a new SHA1 message digest.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to reset.
+ *
+ *  Returns:
+ *      sha Error Code.
+ *
+ */
+int SHA1Reset(SHA1Context *context)
+{
+    if (!context)
+    {
+        return shaNull;
+    }
+
+    context->Length_Low             = 0;
+    context->Length_High            = 0;
+    context->Message_Block_Index    = 0;
+
+    context->Intermediate_Hash[0]   = 0x67452301;
+    context->Intermediate_Hash[1]   = 0xEFCDAB89;
+    context->Intermediate_Hash[2]   = 0x98BADCFE;
+    context->Intermediate_Hash[3]   = 0x10325476;
+    context->Intermediate_Hash[4]   = 0xC3D2E1F0;
+
+    context->Computed   = 0;
+    context->Corrupted  = 0;
+
+    return shaSuccess;
+}
+
+/*
+ *  SHA1Result
+ *
+ *  Description:
+ *      This function will return the 160-bit message digest into the
+ *      Message_Digest array  provided by the caller.
+ *      NOTE: The first octet of hash is stored in the 0th element,
+ *            the last octet of hash in the 19th element.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to use to calculate the SHA-1 hash.
+ *      Message_Digest: [out]
+ *          Where the digest is returned.
+ *
+ *  Returns:
+ *      sha Error Code.
+ *
+ */
+int SHA1Result( SHA1Context *context,
+                uint8_t Message_Digest[SHA1HashSize])
+{
+    int i;
+
+    if (!context || !Message_Digest)
+    {
+        return shaNull;
+    }
+
+    if (context->Corrupted)
+    {
+        return context->Corrupted;
+    }
+
+    if (!context->Computed)
+    {
+        SHA1PadMessage(context);
+        for(i=0; i<64; ++i)
+        {
+            /* message may be sensitive, clear it out */
+            context->Message_Block[i] = 0;
+        }
+        context->Length_Low = 0;    /* and clear length */
+        context->Length_High = 0;
+        context->Computed = 1;
+    }
+
+    for(i = 0; i < SHA1HashSize; ++i)
+    {
+        Message_Digest[i] = context->Intermediate_Hash[i>>2]
+                            >> 8 * ( 3 - ( i & 0x03 ) );
+    }
+
+    return shaSuccess;
+}
+
+/*
+ *  SHA1Input
+ *
+ *  Description:
+ *      This function accepts an array of octets as the next portion
+ *      of the message.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The SHA context to update
+ *      message_array: [in]
+ *          An array of characters representing the next portion of
+ *          the message.
+ *      length: [in]
+ *          The length of the message in message_array
+ *
+ *  Returns:
+ *      sha Error Code.
+ *
+ */
+int SHA1Input(    SHA1Context    *context,
+                  const uint8_t  *message_array,
+                  unsigned       length)
+{
+    if (!length)
+    {
+        return shaSuccess;
+    }
+
+    if (!context || !message_array)
+    {
+        return shaNull;
+    }
+
+    if (context->Computed)
+    {
+        context->Corrupted = shaStateError;
+        return shaStateError;
+    }
+
+    if (context->Corrupted)
+    {
+         return context->Corrupted;
+    }
+    while(length-- && !context->Corrupted)
+    {
+    context->Message_Block[context->Message_Block_Index++] =
+                    (*message_array & 0xFF);
+
+    context->Length_Low += 8;
+    if (context->Length_Low == 0)
+    {
+        context->Length_High++;
+        if (context->Length_High == 0)
+        {
+            /* Message is too long */
+            context->Corrupted = 1;
+        }
+    }
+
+    if (context->Message_Block_Index == 64)
+    {
+        SHA1ProcessMessageBlock(context);
+    }
+
+    message_array++;
+    }
+
+    return shaSuccess;
+}
+
+/*
+ *  SHA1ProcessMessageBlock
+ *
+ *  Description:
+ *      This function will process the next 512 bits of the message
+ *      stored in the Message_Block array.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *      Many of the variable names in this code, especially the
+ *      single character names, were used because those were the
+ *      names used in the publication.
+ *
+ *
+ */
+void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+    const uint32_t K[] =    {       /* Constants defined in SHA-1   */
+                            0x5A827999,
+                            0x6ED9EBA1,
+                            0x8F1BBCDC,
+                            0xCA62C1D6
+                            };
+    int           t;                 /* Loop counter                */
+    uint32_t      temp;              /* Temporary word value        */
+    uint32_t      W[80];             /* Word sequence               */
+    uint32_t      A, B, C, D, E;     /* Word buffers                */
+
+    /*
+     *  Initialize the first 16 words in the array W
+     */
+    for(t = 0; t < 16; t++)
+    {
+        W[t] = context->Message_Block[t * 4] << 24;
+        W[t] |= context->Message_Block[t * 4 + 1] << 16;
+        W[t] |= context->Message_Block[t * 4 + 2] << 8;
+        W[t] |= context->Message_Block[t * 4 + 3];
+    }
+
+    for(t = 16; t < 80; t++)
+    {
+       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = context->Intermediate_Hash[0];
+    B = context->Intermediate_Hash[1];
+    C = context->Intermediate_Hash[2];
+    D = context->Intermediate_Hash[3];
+    E = context->Intermediate_Hash[4];
+
+    for(t = 0; t < 20; t++)
+    {
+        temp =  SHA1CircularShift(5,A) +
+                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 20; t < 40; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 40; t < 60; t++)
+    {
+        temp = SHA1CircularShift(5,A) +
+               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 60; t < 80; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    context->Intermediate_Hash[0] += A;
+    context->Intermediate_Hash[1] += B;
+    context->Intermediate_Hash[2] += C;
+    context->Intermediate_Hash[3] += D;
+    context->Intermediate_Hash[4] += E;
+
+    context->Message_Block_Index = 0;
+}
+
+
+/*
+ *  SHA1PadMessage
+ *
+ *  Description:
+ *      According to the standard, the message must be padded to an even
+ *      512 bits.  The first padding bit must be a '1'.  The last 64
+ *      bits represent the length of the original message.  All bits in
+ *      between should be 0.  This function will pad the message
+ *      according to those rules by filling the Message_Block array
+ *      accordingly.  It will also call the ProcessMessageBlock function
+ *      provided appropriately.  When it returns, it can be assumed that
+ *      the message digest has been computed.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to pad
+ *      ProcessMessageBlock: [in]
+ *          The appropriate SHA*ProcessMessageBlock function
+ *  Returns:
+ *      Nothing.
+ *
+ */
+
+void SHA1PadMessage(SHA1Context *context)
+{
+    /*
+     *  Check to see if the current message block is too small to hold
+     *  the initial padding bits and length.  If so, we will pad the
+     *  block, process it, and then continue padding into a second
+     *  block.
+     */
+    if (context->Message_Block_Index > 55)
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0x80;
+        while(context->Message_Block_Index < 64)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+
+        SHA1ProcessMessageBlock(context);
+
+        while(context->Message_Block_Index < 56)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+    }
+    else
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0x80;
+        while(context->Message_Block_Index < 56)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+    }
+
+    /*
+     *  Store the message length as the last 8 octets
+     */
+    context->Message_Block[56] = context->Length_High >> 24;
+    context->Message_Block[57] = context->Length_High >> 16;
+    context->Message_Block[58] = context->Length_High >> 8;
+    context->Message_Block[59] = context->Length_High;
+    context->Message_Block[60] = context->Length_Low >> 24;
+    context->Message_Block[61] = context->Length_Low >> 16;
+    context->Message_Block[62] = context->Length_Low >> 8;
+    context->Message_Block[63] = context->Length_Low;
+
+    SHA1ProcessMessageBlock(context);
+}
+
+void sha1 (const char *input, int len, char *output) {
+     SHA1Context sha;
+ 
+    SHA1Reset(&sha);
+    SHA1Input(&sha, (unsigned char*)input, len);
+    SHA1Result(&sha, (uint8_t*)output);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/sha1.h	Fri Nov 22 14:03:07 2013 +0000
@@ -0,0 +1,78 @@
+/*
+ * source from http://www.ipa.go.jp/security/rfc/RFC3174JA.html
+ */
+/*
+ *  sha1.h
+ *
+ *  Description:
+ *      This is the header file for code which implements the Secure
+ *      Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
+ *      April 17, 1995.
+ *
+ *      Many of the variable names in this code, especially the
+ *      single character names, were used because those were the names
+ *      used in the publication.
+ *
+ *      Please read the file sha1.c for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+#include "mbed.h"
+/*
+ * If you do not have the ISO standard stdint.h header file, then you
+ * must typdef the following:
+ *    name              meaning
+ *  uint32_t         unsigned 32 bit integer
+ *  uint8_t          unsigned 8 bit integer (i.e., unsigned char)
+ *  int_least16_t    integer of >= 16 bits
+ *
+ */
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+enum
+{
+    shaSuccess = 0,
+    shaNull,            /* Null pointer parameter */
+    shaInputTooLong,    /* input data too long */
+    shaStateError       /* called Input after Result */
+};
+#endif
+#define SHA1HashSize 20
+
+/*
+ *  This structure will hold context information for the SHA-1
+ *  hashing operation
+ */
+typedef struct SHA1Context
+{
+    uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest  */
+
+    uint32_t Length_Low;            /* Message length in bits      */
+    uint32_t Length_High;           /* Message length in bits      */
+
+                               /* Index into message block array   */
+    int_least16_t Message_Block_Index;
+    uint8_t Message_Block[64];      /* 512-bit message blocks      */
+
+    int Computed;               /* Is the digest computed?         */
+    int Corrupted;             /* Is the message digest corrupted? */
+} SHA1Context;
+
+/*
+ *  Function Prototypes
+ */
+
+int SHA1Reset(  SHA1Context *);
+int SHA1Input(  SHA1Context *,
+                const uint8_t *,
+                unsigned int);
+int SHA1Result( SHA1Context *,
+                uint8_t Message_Digest[SHA1HashSize]);
+
+
+void sha1 (const char *input, int len, char *output);
+#endif
--- a/GSwifiInterface.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/GSwifiInterface.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -35,7 +35,7 @@
 
 int GSwifiInterface::disconnect()
 {
-    return GSwifi::disconnect();
+    return GSwifi::dissociate();
 }
 
 char * GSwifiInterface::getMACAddress()
--- a/Socket/UDPSocket.cpp	Fri Nov 15 04:20:14 2013 +0000
+++ b/Socket/UDPSocket.cpp	Fri Nov 22 14:03:07 2013 +0000
@@ -49,7 +49,7 @@
     Timer tmr;
     int idx = 0;
 
-    if (_cid < 0 && _wifi->isConnected()) {
+    if (_cid < 0 && _wifi->isAssociated()) {
         // Socket open
         if (_server) {
             _cid = _wifi->listen(GSwifi::PROTO_UDP, _port);
@@ -87,7 +87,7 @@
     char ip[16];
     int port;
 
-    if (_cid < 0 && _wifi->isConnected()) {
+    if (_cid < 0 && _wifi->isAssociated()) {
         // Socket open
         if (_server) {
             _cid = _wifi->listen(GSwifi::PROTO_UDP, _port);