GainSpan Wi-Fi library see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
Dependents: GSwifi_httpd GSwifi_websocket GSwifi_tcpclient GSwifi_tcpserver ... more
Fork of GSwifi by
GainSpan Wi-Fi library
The GS1011 is an ultra low power 802.11b wireless module from GainSpan.
see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
ゲインスパン Wi-Fi モジュール ライブラリ
ゲインスパン社の低電力 Wi-Fiモジュール(無線LAN) GS1011 シリーズ用のライブラリです。
解説: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
Revision 18:4b97804c37d1, committed 2012-11-01
- 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
--- 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; +}