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:
Thu Nov 01 02:55:57 2012 +0000
Parent:
17:6828b084e74b
Child:
19:cad912f5a6ba
Commit message:
support smtp (send mail) and http server (httpd)

Changed in this revision

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_httpd.cpp Show annotated file Show diff for this revision Revisions of this file
GSwifi_net.h 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/GSwifi.cpp	Sun Oct 28 14:26:31 2012 +0000
+++ b/GSwifi.cpp	Thu Nov 01 02:55:57 2012 +0000
@@ -32,6 +32,7 @@
     _connect = false;
     _status = GSSTAT_READY;
     _escape = 0;
+    _response = 1;
     _gs_mode = GSMODE_COMMAND;
 
     _gs.baud(baud);
@@ -43,6 +44,7 @@
     _connect = false;
     _status = GSSTAT_READY;
     _escape = 0;
+    _response = 1;
     _gs_mode = GSMODE_COMMAND;
 
     _gs.baud(baud);
@@ -93,7 +95,7 @@
     dat = _gs_getc();
     
     if (flg & ((1 << 7)|(1 << 3)|(1 << 4))) return;
-//    DBG("%02x ", dat);
+//    DBG("%02x_", dat);
 
     switch (_gs_mode) {
     case GSMODE_COMMAND: // command responce
@@ -141,7 +143,10 @@
             if (dat != '\r') {
                 // command
                 _buf_cmd.put(dat);
-                if (dat == '\n') _gs_enter ++;
+                if (dat == '\n') {
+                    _gs_enter ++;
+                    if (!_response && _connect) poll_cmd();
+                }
             }
         }
         break;
@@ -299,19 +304,20 @@
 }
 
 int GSwifi::command (const char *cmd, GSRESPONCE res, int timeout) {
-    int i;
+    int i, r = 0;
 
     if (! cmd) {
         // dummy CR+LF
         _gs.printf("\r\n");
         for (i = 0; i < 10; i ++) {
             wait_ms(10);
-            poll();
+            poll_cmd();
             _buf_cmd.clear();
         }
         return 0;
     }
 
+    _response = 1;
     _buf_cmd.clear();
     _gs_ok = 0;
     _gs_failure = 0;
@@ -323,12 +329,12 @@
     _gs_putc('\n');
     DBG("command: %s\r\n", cmd);
     if (strlen(cmd) == 0) return 0;
-    wait_ms(50);
+    wait_ms(10);
     if (timeout) {
-        return cmdResponse(res, timeout);
-    } else {
-        return 0;
+        r = cmdResponse(res, timeout);
     }
+    _response = 0;
+    return r;
 }
 
 int GSwifi::cmdResponse (GSRESPONCE res, int ms) {
@@ -537,6 +543,12 @@
         break;
     }
 
+    if (r == 0 && !dhcp) {
+        sprintf(cmd, "AT+DNSSET=%d.%d.%d.%d",
+            _gateway[0], _gateway[1], _gateway[2], _gateway[3]);
+        command(cmd, GSRES_NORMAL);
+    }
+
     if (r == 0) _connect = true;
     return r;
 }
@@ -854,8 +866,8 @@
     return command(cmd, GSRES_NORMAL);
 }
 
-void GSwifi::poll() {
-    int i, j;
+void GSwifi::poll_cmd () {
+    int i;
 
     while (_gs_enter) {
         // received "\n"
@@ -877,22 +889,39 @@
         if (i == 0) {
         } else
         if (strncmp(buf, "CONNECT", 7) == 0 && buf[8] >= '0' && buf[8] <= 'F') {
-            i = x2i(buf[8]);
-            if (_gs_sock[i].type == GSTYPE_SERVER) {
+            int cid = x2i(buf[8]);
+            if (_gs_sock[cid].type == GSTYPE_SERVER) {
                 int acid, ip1, ip2, ip3, ip4;
                 char *tmp = buf + 12;
 
                 acid = x2i(buf[10]);
-                newSock(acid, _gs_sock[i].type, _gs_sock[i].protocol, _gs_sock[i].onGsReceive);
-                _gs_sock[acid].lcid = i;
+                DBG("connect %d -> %d\r\n", cid, acid);
+                newSock(acid, _gs_sock[cid].type, _gs_sock[cid].protocol, _gs_sock[cid].onGsReceive);
+                _gs_sock[acid].lcid = cid;
                 sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
                 _gs_sock[acid].host.setIp(IpAddr(ip1, ip2, ip3, ip4));
                 tmp = strstr(tmp, " ") + 1;
                 _gs_sock[acid].host.setPort(atoi(tmp));
+
+                if (_gs_sock[acid].protocol == GSPROT_HTTPD) {
+                    poll_httpd(acid, 0);
+                } else
+                if (_gs_sock[acid].onGsReceive != NULL) {
+                    _gs_sock[acid].onGsReceive(acid, 0); // event connected
+                }
             }
         } else
         if (strncmp(buf, "DISCONNECT", 10) == 0) {
-            _gs_sock[x2i(buf[11])].connect = false;
+            int cid = x2i(buf[11]);
+            DBG("disconnect %d\r\n", cid);
+            _gs_sock[cid].connect = false;
+
+            if (_gs_sock[cid].protocol == GSPROT_HTTPD) {
+                poll_httpd(cid, 0);
+            } else
+            if (_gs_sock[cid].onGsReceive != NULL) {
+                _gs_sock[cid].onGsReceive(cid, 0); // event disconnected
+            }
         } else
         if (strncmp(buf, "DISASSOCIATED", 13) == 0 ||
           strncmp(buf, "Disassociated", 13) == 0 ||
@@ -918,15 +947,27 @@
         }
         DBG("status: %d\r\n", _status);
     }
-    
+}
+
+void GSwifi::poll () {
+    int i, j;
+
+    poll_cmd();
+
     for (i = 0; i < 16; i ++) {
 //        if (_gs_sock[i].connect && _gs_sock[i].received) {
         if (_gs_sock[i].received && _gs_sock[i].data->use()) {
             // recv interrupt
             _gs_sock[i].received = 0;
+            if (_gs_sock[i].protocol == GSPROT_HTTPD) {
+                for (j = 0; j < 1500 / GS_DATA_SIZE + 1; j ++) {
+                    if (! _gs_sock[i].connect || ! _gs_sock[i].data->use()) break;
+                    poll_httpd(i, _gs_sock[i].data->use());
+                }
+            } else
             if (_gs_sock[i].onGsReceive != NULL) {
                 for (j = 0; j < 1500 / GS_DATA_SIZE + 1; j ++) {
-                    if (! _gs_sock[i].data->use()) break;
+                    if (! _gs_sock[i].connect || ! _gs_sock[i].data->use()) break;
                     _gs_sock[i].onGsReceive(i, _gs_sock[i].data->use());
                 }
             }
@@ -1005,7 +1046,8 @@
     if (! _gs_sock[cid].connect) return -1;
 
     if ((_gs_sock[cid].protocol == GSPROT_TCP) ||
-      (_gs_sock[cid].protocol == GSPROT_UDP && _gs_sock[cid].type == GSTYPE_CLIENT)) {
+      (_gs_sock[cid].protocol == GSPROT_UDP && _gs_sock[cid].type == GSTYPE_CLIENT) ||
+      (_gs_sock[cid].protocol == GSPROT_HTTPD)) {
         // TCP Client, TCP Server, UDP Client
         _gs_ok = 0;
         _gs_failure = 0;
@@ -1308,6 +1350,7 @@
 }
 
 
+#ifdef DEBUF
 // for test
 
 void GSwifi::test () {
@@ -1342,3 +1385,4 @@
     return _buf_cmd.use();
 //    return _buf_cmd.use() || (_gs_sock[0].data != NULL && _gs_sock[0].data->use());
 }
+#endif
--- a/GSwifi.h	Sun Oct 28 14:26:31 2012 +0000
+++ b/GSwifi.h	Thu Nov 01 02:55:57 2012 +0000
@@ -14,6 +14,7 @@
 #define _GSWIFI_H_
 
 #include "mbed.h"
+#include "GSwifi_net.h"
 #include "RingBuffer.h"
 #include "host.h"
 #include "ipaddr.h"
@@ -27,7 +28,8 @@
 #define GS_TIMEOUT2 30000 // ms
 #define GS_CMD_SIZE 100
 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
-#define GS_DATA_SIZE 1500
+//#define GS_DATA_SIZE 1500
+#define GS_DATA_SIZE 1000
 #elif defined(TARGET_LPC11U24)
 #define GS_DATA_SIZE 500
 #endif
@@ -55,6 +57,7 @@
     GSPROT_TCP = 1,
     GSPROT_HTTPGET,
     GSPROT_HTTPPOST,
+    GSPROT_HTTPD,
 };
 
 /**
@@ -270,6 +273,14 @@
      * @return CID, -1:failure
      */
     int listen (int port, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive = NULL);
+/*
+    template<typename T>
+    int listen2 (T* tptr, int port, GSPROTOCOL pro, void (T::*mptr)(int,int)) {
+        if((mptr != NULL) && (tptr != NULL)) {
+            return listen(port, pro, reinterpret_cast<onGsReceiveFunc>(mptr));
+        }
+    }
+*/
     /**
      * close client/server
      */
@@ -298,44 +309,90 @@
     bool isConnected (int cid);
 
     /**
-     * http request
-     * @return CID, -1:failure
-     * If you use ssl, please set system time.
+     * http request (GET method)
      */
     int httpGet (Host &host, char *uri, char *user, char *pwd, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL);
     int httpGet (Host &host, char *uri, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL);
     /**
-     * http request
-     * @return CID, -1:failure
-     * If you use ssl, please set system time.
+     * http request (POST method)
      */
     int httpPost (Host &host, char *uri, char *body, char *user, char *pwd, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL);
     int httpPost (Host &host, char *uri, char *body, int ssl = 0, onGsReceiveFunc ponGsReceive = NULL);
+
     /**
      * certificate 
      */
     int certAdd (char *name, char *cert, int len);
 
+    /**
+     * send mail (smtp)
+     * @param host SMTP server
+     * @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 (Host &host, char *to, char *from, char *subject, char *mesg, char *user = NULL, char *pwd = NULL);
+
+    /**
+     * start http server
+     * @param port
+     */
+    int httpd (int port = 80);
+    /**
+     * attach uri to dirctory handler
+     */
+    void send_httpd_error (int cid, int err);
+    /**
+     * attach uri to dirctory handler
+     */
+    int attach_httpd (char *uri, char *dir);
+    /**
+     * attach uri to cgi handler
+     */
+    int attach_httpd (char *uri, onHttpdCgiFunc ponHttpCgi);
+
+    /**
+     * base64 encode
+     */
     int base64encode (const char *input, int length, char *output, int len);
+    /**
+     * url encode
+     */
     int urlencode (char *str, char *buf, int len);
 
+#ifdef DEBUF
     void test ();
     int getc();
     void putc(char c);
     int readable();
+#endif
 
 protected:
+    void poll_cmd ();
     int x2i (char c);
     char i2x (int i);
     void isr_recv ();
     void newSock (int cid, GSTYPE type, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive);
 
+    // send mail (smtp)
+    int wait_smtp (int cid, int code);
+
+    // http server
+    void poll_httpd (int cid, int len);
+    int httpd_request (int cid, char *dir, char *file, int keep);
+
 private:
     Serial _gs;
     bool _rts;
     volatile bool _connect;
     volatile GSSTATUS _status;
     volatile int _gs_ok, _gs_failure, _gs_enter;
+    volatile int _response;
     GSMODE _gs_mode;
     int _escape;
     int _cid, _rssi;
@@ -345,6 +402,10 @@
     RingBuffer _buf_cmd;
     struct GS_Socket _gs_sock[16];
     time_t _time;
+    
+    struct GS_httpd _httpd[16];
+    struct GS_httpd_handler _handler[10];
+    int _handler_count;
 };
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi_httpd.cpp	Thu Nov 01 02:55:57 2012 +0000
@@ -0,0 +1,284 @@
+#include "dbg.h"
+#include "mbed.h"
+#include "GSwifi.h"
+
+#define HTTPD_REQUEST 0
+#define HTTPD_HEAD 1
+#define HTTPD_SPACE 2
+#define HTTPD_BODY 3
+#define HTTPD_ERROR 4
+
+int GSwifi::httpd (int port) {
+    int i;
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+
+    for (i = 0; i < 16; i ++) {
+        _httpd[i].mode = HTTPD_REQUEST;
+        _httpd[i].buf = NULL;
+        _httpd[i].uri = NULL;
+    }
+    _handler_count = 0;
+
+    sprintf(cmd, "AT+NSTCP=%d", port);
+    if (command(cmd, GSRES_CONNECT)) return -1;
+
+    newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, NULL);
+    return _cid;
+}
+
+void GSwifi::poll_httpd (int cid, int len) {
+    int i, j, flg = 0;
+    char c;
+
+    if (len == 0) {
+        _httpd[cid].mode = HTTPD_REQUEST;
+        _httpd[cid].len = 0;
+        _httpd[cid].keepalive = 0;
+        return;
+    }
+
+  while (_gs_sock[cid].connect && _gs_sock[cid].data->use()) {
+    flg = 0;
+    if (_httpd[cid].buf == NULL) {
+        _httpd[cid].buf = new char[HTTPD_BUF_SIZE];
+    }
+    for (j = 0; j < len; j ++) {
+        _gs_sock[cid].data->get(&c);
+        if (c == '\r') continue;
+        if (c == '\n' && _httpd[cid].mode != HTTPD_BODY) break;
+        
+        if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) {
+            _httpd[cid].buf[_httpd[cid].len] = c; 
+        }
+        _httpd[cid].len ++;
+        if (_httpd[cid].len >= _httpd[cid].length && _httpd[cid].mode == HTTPD_BODY) break;
+    }
+    if (j >= len) return;
+    if (_httpd[cid].len < HTTPD_BUF_SIZE) {
+        _httpd[cid].buf[_httpd[cid].len] = 0;
+        DBG("httpd: %d %s (%d)\r\n", _httpd[cid].mode, _httpd[cid].buf, _httpd[cid].len);
+    }
+
+    switch (_httpd[cid].mode) {
+    case HTTPD_REQUEST:
+        if (strncmp(_httpd[cid].buf, "GET ", 4) == 0) {
+            _httpd[cid].type = 0;
+            j = 4;
+        } else
+        if (strncmp(_httpd[cid].buf, "POST ", 5) == 0) {
+            _httpd[cid].type = 1;
+            j = 5;
+        } else {
+            _httpd[cid].mode = HTTPD_ERROR;
+            break;
+        }
+
+        for (i = j; i < _httpd[cid].len; i ++) {
+            if (_httpd[cid].buf[i] == ' ') break;
+        }
+        i = i - j;
+        if (i) {
+            if (_httpd[cid].uri == NULL) {
+                _httpd[cid].uri = new char[HTTPD_URI_SIZE];
+            }
+            strncpy(_httpd[cid].uri, &_httpd[cid].buf[j], i);
+            _httpd[cid].uri[i] = 0;
+        }
+        _httpd[cid].mode = HTTPD_HEAD;
+        _httpd[cid].length = 0;
+        DBG("uri: %s\r\n", _httpd[cid].uri);
+        break;
+        
+    case HTTPD_HEAD:
+        if (_httpd[cid].len == 0) {
+            _httpd[cid].mode = HTTPD_BODY;
+            if (_httpd[cid].length == 0) flg = 1;
+        } else
+        if (strncmp(_httpd[cid].buf, "Content-length: ", 16) == 0) {
+            _httpd[cid].length = atoi(&_httpd[cid].buf[16]);
+        } else
+        if (strncmp(_httpd[cid].buf, "Connection: Keep-Alive", 22) == 0) {
+            if (! _httpd[cid].keepalive) {
+                _httpd[cid].keepalive = HTTPD_KEEPALIVE;
+            }
+        }
+        break;
+
+    case HTTPD_BODY:
+        if (_httpd[cid].len >= _httpd[cid].length) {
+            DBG("body: %s\r\n", _httpd[cid].buf);
+            flg = 1;
+        }
+        break;
+    }
+
+    if (flg) {
+        // http request
+        _httpd[cid].buf[_httpd[cid].len] = 0;
+        // scan handler
+        flg = 0;
+        for (i = 0; i < _handler_count; i ++) {
+            j = strlen(_handler[i].uri);
+            if (strncmp(_httpd[cid].uri, _handler[i].uri, j) == NULL) {
+                if (_handler[i].dir) {
+                    // file
+                    httpd_request(cid, _handler[i].dir, &_httpd[cid].uri[j], _httpd[cid].keepalive);
+                    flg = 1;
+                } else
+                if (_handler[i].onHttpCgi) {
+                    // cgi
+                    _handler[i].onHttpCgi(cid, &_httpd[cid].uri[j], _httpd[cid].buf, _httpd[cid].len);
+                    flg = 1;
+                }
+                break;
+            }
+        }
+        if (! flg) {
+            send_httpd_error(cid, 403);
+        }
+        
+        if (_httpd[cid].keepalive) {
+            _httpd[cid].mode = HTTPD_REQUEST;
+            _httpd[cid].len = 0;
+            _httpd[cid].type = 0;
+            _httpd[cid].length = 0;
+            _httpd[cid].keepalive --;
+        } else {
+            close(cid);
+        }
+    }
+
+    if (_httpd[cid].mode == HTTPD_ERROR) {
+        send_httpd_error(cid, 400);
+    }
+
+    _httpd[cid].len = 0;
+  }
+}
+
+int GSwifi::httpd_request (int cid, char *dir, char *file, int keep) {
+    FILE *fp;
+    int i, j;
+    char buf[100], tmp[20];
+
+    strcpy(buf, dir);
+    strcat(buf, file);
+    if (buf[strlen(buf) - 1] == '/') {
+        strcat(buf, "index.htm");
+    }
+    DBG("file: %s\r\n", buf);
+    
+    fp = fopen(buf, "r");
+    if (fp) {
+        strcpy(buf, "HTTP/1.1 200 OK\r\n");
+        send(cid, buf, strlen(buf));
+        {
+            j = ftell(fp);
+            fseek(fp, 0, SEEK_END);
+            i = ftell(fp);
+            fseek(fp, j, SEEK_SET);
+        }
+        sprintf(buf, "Content-Length: %d\r\n", i);
+        send(cid, buf, strlen(buf));
+        j = strlen(file);
+        if (j == 0 || strncmp(&file[j - 4], ".htm", 4)) {
+            strcpy(tmp, "text/html");
+        } else
+        if (strncmp(&file[j - 4], ".jpg", 4)) {
+            strcpy(tmp, "image/jpeg");
+        } else
+        if (strncmp(&file[j - 4], ".png", 4)) {
+            strcpy(tmp, "image/png");
+        } else
+        if (strncmp(&file[j - 4], ".gif", 4)) {
+            strcpy(tmp, "image/gif");
+        } else {
+            strcpy(tmp, "text/plain");
+        }
+        sprintf(buf, "Content-Type: %s\r\n", tmp);
+        send(cid, buf, strlen(buf));
+        if (keep) {
+            strcpy(buf, "Connection: Keep-Alive\r\n");
+        } else {
+            strcpy(buf, "Connection: close\r\n");
+        }
+        send(cid, buf, strlen(buf));
+        strcpy(buf, "Server: GSwifi httpd\r\n");
+        send(cid, buf, strlen(buf));
+        send(cid, "\r\n", 2);
+
+        for (;;) {
+            i = fread(buf, sizeof(char), sizeof(buf), fp);
+            if (i == 0) break;
+            send(cid, buf, i);
+            if (feof(fp)) break;
+        }
+        fclose(fp);
+        return 0;
+    }
+
+    send_httpd_error(cid, 404);
+    return -1;
+}
+
+void GSwifi::send_httpd_error (int cid, int err) {
+    char buf[100], 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");
+    send(cid, buf, strlen(buf));
+    send(cid, "\r\n", 2);
+
+    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));
+    close(cid);
+}
+
+int GSwifi::attach_httpd (char *uri, char *dir) {
+    if (_handler_count < HTTPD_HANDLE) {
+        _handler[_handler_count].uri = new char[strlen(uri) + 1];
+        strcpy(_handler[_handler_count].uri, uri);
+        _handler[_handler_count].dir = new char[strlen(dir) + 1];
+        strcpy(_handler[_handler_count].dir, dir);
+        _handler[_handler_count].onHttpCgi = NULL;
+        _handler_count ++;
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int GSwifi::attach_httpd (char *uri, onHttpdCgiFunc ponHttpCgi) {
+    if (_handler_count < HTTPD_HANDLE) {
+        _handler[_handler_count].uri = new char[strlen(uri) + 1];
+        strcpy(_handler[_handler_count].uri, uri);
+        _handler[_handler_count].dir = NULL;
+        _handler[_handler_count].onHttpCgi = ponHttpCgi;
+        _handler_count ++;
+        return 0;
+    } else {
+        return -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi_net.h	Thu Nov 01 02:55:57 2012 +0000
@@ -0,0 +1,46 @@
+/**
+ * Gainspan wi-fi module library for mbed
+ * Copyright (c) 2012 gsfan
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief Gainspan wi-fi module library for mbed
+ * GS1011MIC, GS1011MIP, GainSpan WiFi Breakout, etc.
+ * module configuration: ATB=115200
+ */
+
+#ifndef _GSWIFI_NET_H_
+#define _GSWIFI_NET_H_
+
+#include "mbed.h"
+
+// GSwifi_smtp.cpp
+#define SMTP_TIMEOUT 15000
+
+// GSwifi_httpd.cpp
+#define HTTPD_TIMEOUT 15000
+#define HTTPD_HANDLE 10
+#define HTTPD_BUF_SIZE 100
+#define HTTPD_URI_SIZE 50
+#define HTTPD_KEEPALIVE 5
+
+typedef void (*onHttpdCgiFunc)(int cid, char *file, char *post, int len);
+
+struct GS_httpd {
+    int mode;
+    int type;
+    char *buf;
+    int len;
+    char *uri;
+    int length;
+    int keepalive;
+};
+
+struct GS_httpd_handler {
+    char *uri;
+    char *dir;
+    onHttpdCgiFunc onHttpCgi;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi_smtp.cpp	Thu Nov 01 02:55:57 2012 +0000
@@ -0,0 +1,107 @@
+#include "dbg.h"
+#include "mbed.h"
+#include "GSwifi.h"
+
+int GSwifi::mail (Host &host, char *to, char *from, char *subject, char *mesg, char *user, char *pwd) {
+    int ret = -1;
+    int cid;
+
+    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(25);
+    }
+
+    cid = open(host, GSPROT_TCP);
+    if (cid < 0) return -1;
+    DBG("cid %d\r\n", cid);
+
+    if (wait_smtp(cid ,220)) goto exit;
+
+    // send request
+    send(cid, "EHLO gainspan\r\n", 15);
+    wait_ms(100);
+    if (wait_smtp(cid ,250)) goto exit;
+
+    if (user && pwd) {
+        // smtp auth
+        char tmp[80], buf[100];
+        int len;
+        snprintf(tmp, sizeof(tmp), "%s%c%s%c%s", user, 0, user, 0, pwd);
+        len = strlen(user) * 2 + strlen(pwd) + 2;
+        base64encode(tmp, len, buf, sizeof(buf));
+        send(cid, "AUTH PLAIN ", 11);
+        send(cid, buf, strlen(buf));
+        send(cid, "\r\n", 2);
+        if (wait_smtp(cid ,235)) goto quit;
+    }
+ 
+    send(cid, "MAIL FROM: ", 11);
+    send(cid, from, strlen(from));
+    send(cid, "\r\n", 2);
+    if (wait_smtp(cid ,250)) goto quit;
+ 
+    send(cid, "RCPT TO: ", 9);
+    send(cid, to, strlen(to));
+    send(cid, "\r\n", 2);
+    if (wait_smtp(cid ,250)) goto quit;
+ 
+    send(cid, "DATA\r\n", 6);
+    if (wait_smtp(cid ,354)) goto quit;
+ 
+    // mail data
+    send(cid, mesg, strlen(mesg));
+    send(cid, "\r\n.\r\n", 5);
+    if (wait_smtp(cid ,250)) goto quit;
+    ret = 0;
+ 
+quit:
+    send(cid, "QUIT\r\n", 6);
+    if (wait_smtp(cid ,221)) goto exit;
+ 
+exit:
+    close(cid);
+    return ret;
+}
+
+int GSwifi::wait_smtp (int cid, int code) {
+    Timer timeout;
+    int i, n, len = 0;
+    char buf[500], data[100];
+
+    // wait responce
+    timeout.start();
+    while (timeout.read_ms() < SMTP_TIMEOUT) {
+        wait_ms(100);
+        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;
+    len = 0;
+    DBG("smtp: %s\r\n", data);
+    timeout.stop();
+ 
+    // check return code
+    i = atoi(data);
+    DBG("smtp status %d\r\n", i);
+    if (i == code) return 0;
+ 
+    return -1;
+}