Embedded system Fun Blog
























































Find out all the best information, libraries and circuit about the latest Embedded systems.
Showing posts with label client. Show all posts
Showing posts with label client. Show all posts

Sunday, 8 January 2012

MBED: Cool Tiny SMTP Client

.from: http://mbed.org/users/okini3939/programs/TinySMTP/lv1bdk

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinySMTP.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny SMTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny SMTP Client
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "DNSRequest.h"
#include "TinySMTP.h"

#define STATUS_NONE 0
#define STATUS_READABLE 1
#define STATUS_CONNECTED 2
#define STATUS_ERROR 3
#define STATUS_DISCONNECTED 4

static TCPSocket *smtp;
static volatile int tcp_ready, tcp_readable, tcp_writable;
static volatile int dns_status;


// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
int base64enc(const char *input, unsigned int length, char *output, int outputlen) {
  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  unsigned int c, c1, c2, c3;

  if (outputlen < (((length-1)/3)+1)<<2) return -1;

  for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
    c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
    c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
    c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;

    c = ((c1 & 0xFC) >> 2);
    output[j+0] = base64[c];
    c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
    output[j+1] = base64[c];
    c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
    output[j+2] = (length>i+1)?base64[c]:'=';
    c = (c3 & 0x3F);
    output[j+3] = (length>i+2)?base64[c]:'=';
  }
  output[(((length-1)/3)+1)<<2] = '\0';
  return 0;
}


void isr_smtp (TCPSocketEvent e) {

#ifdef DEBUG
    printf("tcp(%d)\r\n", e);
#endif
    switch(e) {
    case TCPSOCKET_CONNECTED:
        tcp_ready = 1;
        break;

    case TCPSOCKET_READABLE: //Incoming data
        tcp_readable = 1;
        break;

    case TCPSOCKET_WRITEABLE: //We can send data
        tcp_writable = 1;
        break;

    case TCPSOCKET_CONTIMEOUT:
    case TCPSOCKET_CONRST:
    case TCPSOCKET_CONABRT:
    case TCPSOCKET_ERROR:
    case TCPSOCKET_DISCONNECTED:
        tcp_ready = 0;
        break;
    }
}

int wait_smtp (int code) {
    Timer timeout;
    int i;
    char buf[1500];

    // wait responce
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < SMTP_TIMEOUT) {
        if (tcp_readable) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_readable) return -1;
    // recv
    i = smtp->recv(buf, sizeof(buf));
    if (i < sizeof(buf) - 1) tcp_readable = 0;
    buf[i] = 0;
#ifdef DEBUG
    printf(buf);
#endif

    // check return code
    if (atoi(buf) == code) return 0;

    return -1;
}

void isr_dns (DNSReply r) {

#ifdef DEBUG
    printf("dns(%d)\r\n", r);
#endif
    if (DNS_FOUND) {
        dns_status = 1;
    } else {
        dns_status = -1;
    }
}

int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd) {
    TCPSocketErr err;
    Timer timeout;
    int ret = -1;

    smtp = new TCPSocket;
    tcp_ready = 0;
    tcp_readable = 0;
    tcp_writable = 0;

    smtp->setOnEvent(isr_smtp);

    // connect
    if (host->getIp().isNull()) {
        DNSRequest dns;
        dns_status = 0;
        dns.setOnReply(isr_dns);
        if (dns.resolve(host) != DNS_OK) goto exit;
        timeout.reset();
        timeout.start();
        while (timeout.read_ms() < SMTP_TIMEOUT) {
            if (dns_status) break;
            Net::poll();
        }
        timeout.stop();
        if (dns_status <= 0) goto exit;
#ifdef DEBUG
        printf("%s [%d.%d.%d.%d]\r\n", host->getName(), (unsigned char)host->getIp()[0], (unsigned char)host->getIp()[1], (unsigned char)host->getIp()[2], (unsigned char)host->getIp()[3]);
#endif
    }
    if (! host->getPort()) {
        host->setPort(SMTP_PORT);
    }

    err = smtp->connect(*host);
    if (err != TCPSOCKET_OK) goto exit;

    // wait connect
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < SMTP_TIMEOUT) {
        if (tcp_ready) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_ready) goto exit;
    if (wait_smtp(220)) goto exit;

    // send request
    wait_ms(100);
    smtp->send("EHLO mbed\r\n", 11);
    if (wait_smtp(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;
        base64enc(tmp, len, buf, sizeof(buf));
        smtp->send("AUTH PLAIN ", 11);
        smtp->send(buf, strlen(buf));
        smtp->send("\r\n", 2);
        if (wait_smtp(235)) goto quit;
    }

    smtp->send("MAIL FROM: ", 11);
    smtp->send(from, strlen(from));
    smtp->send("\r\n", 2);
    if (wait_smtp(250)) goto quit;

    smtp->send("RCPT TO: ", 9);
    smtp->send(to, strlen(to));
    smtp->send("\r\n", 2);
    if (wait_smtp(250)) goto quit;

    smtp->send("DATA\r\n", 6);
    if (wait_smtp(354)) goto quit;

    // mail data
    smtp->send(data, strlen(data));
    smtp->send("\r\n.\r\n", 5);
    if (wait_smtp(250)) goto quit;
    ret = 0;

quit:
    smtp->send("QUIT\r\n", 6);
    if (wait_smtp(221)) goto exit;

exit:
    smtp->resetOnEvent();
    smtp->close();
    delete smtp;

    return ret;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinySMTP.h XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny SMTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny SMTP Client
 */

#ifndef TinySMTP_h
#define TinySMTP_h

#define DEBUG

#define SMTP_PORT 25
#define SMTP_TIMEOUT 15000 // ms

/** send mail
 * @param to mail address
 * @param from mail address
 * @param data mail body
 * @param host mail server
 * @param data mail body
 * @param user auth username (or NULL)
 * @param pwd auth password (or NULL)
 * @return 0:success, -1:failue
 */
int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd);

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx main.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "TinySMTP.h"

#define SMTP "mail.domain.name"
#define PORT 587 // or 25
#define FROM "from@domain.name"
#define TO "to@domain.name"
#define USER "authuser"
#define PWD "password"
#define SUBJECT "mail test"
#define BODY "TEST TEST"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
EthernetNetIf eth;

int main () {
    EthernetErr ethErr;
    Host host;
    int r;
    char data[500];

    myled = 1;

    strcpy(data, "From: " FROM "\r\nTo: " TO "\r\n");
    strcat(data, "Subject: " SUBJECT "\r\n\r\n" BODY "\r\n");

    ethErr = eth.setup();
    if(ethErr) {
        return -1;
    }

    host.setName(SMTP);
    host.setPort(PORT);
    r = sendmail(FROM, TO, data, &host, USER, PWD);

    if (r) {
        printf("error\r\n");
    } else {
        printf("sent\r\n");
    }

    myled = 0;
    return 0;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx


MBED: Tiny HTTP Client

.info: http://mbed.org/users/okini3939/programs/TinyHTTP/lv1tin

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinyHTTP.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny HTTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny HTTP Client
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "DNSRequest.h"
#include "TinyHTTP.h"
#include <ctype.h>


TCPSocket *http;
volatile int tcp_ready, tcp_readable, tcp_writable;
volatile int dns_status;

// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
int base64enc(const char *input, unsigned int length, char *output, int len) {
  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  unsigned int c, c1, c2, c3;

  if (len < ((((length-1)/3)+1)<<2)) return -1;
  for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
    c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
    c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
    c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;

    c = ((c1 & 0xFC) >> 2);
    output[j+0] = base64[c];
    c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
    output[j+1] = base64[c];
    c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
    output[j+2] = (length>i+1)?base64[c]:'=';
    c = (c3 & 0x3F);
    output[j+3] = (length>i+2)?base64[c]:'=';
  }
  output[(((length-1)/3)+1)<<2] = '\0';
  return 0;
}

// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
int urlencode(char *str, char *buf, int len) {
  static const char to_hex[] = "0123456789ABCDEF";
//  char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
  char *pstr = str, *pbuf = buf;

  if (len < (strlen(str) * 3 + 1)) return -1;
  while (*pstr) {
    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') {
      *pbuf++ = *pstr;
    } else if (*pstr == ' ') {
      *pbuf++ = '+';
    } else {
      *pbuf++ = '%';
      *pbuf++ = to_hex[(*pstr >> 4) & 0x0f];
      *pbuf++ = to_hex[*pstr & 0x0f];
    }
    pstr++;
  }
  *pbuf = '\0';
  return 0;
}


void isr_http (TCPSocketEvent e) {

#ifdef DEBUG
    printf("tcp(%d)\r\n", e);
#endif
    switch(e) {
    case TCPSOCKET_CONNECTED:
        tcp_ready = 1;
        break;

    case TCPSOCKET_READABLE: //Incoming data
        tcp_readable = 1;
        break;

    case TCPSOCKET_WRITEABLE: //We can send data
        tcp_writable = 1;
        break;

    case TCPSOCKET_CONTIMEOUT:
    case TCPSOCKET_CONRST:
    case TCPSOCKET_CONABRT:
    case TCPSOCKET_ERROR:
    case TCPSOCKET_DISCONNECTED:
        tcp_ready = 0;
        break;
    }
}

void createauth (char *user, char *pwd, char *buf, int len) {
    char tmp[80];

    strncpy(buf, "Authorization: Basic ", len);
    snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
    base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf));
    strncat(buf, "\r\n", len - strlen(buf));
}

void isr_dns (DNSReply r) {

#ifdef DEBUG
    printf("dns(%d)\r\n", r);
#endif
    if (DNS_FOUND) {
        dns_status = 1;
    } else {
        dns_status = -1;
    }
}

int httpRequest (int method, Host *host, char *uri, char *head, char *body) {
    TCPSocketErr err;
    Timer timeout;
    char buf[1500];
    int i, ret = -1;

    http = new TCPSocket;
    tcp_ready = 0;
    tcp_readable = 0;
    tcp_writable = 0;

    http->setOnEvent(isr_http);

    // connect
    if (host->getIp().isNull()) {
        // resolv
        DNSRequest dns;
        dns_status = 0;
        dns.setOnReply(isr_dns);
        if (dns.resolve(host) != DNS_OK) goto exit;
        timeout.reset();
        timeout.start();
        while (timeout.read_ms() < HTTP_TIMEOUT) {
            if (dns_status) break;
            Net::poll();
        }
        timeout.stop();
        if (dns_status <= 0) goto exit;
#ifdef DEBUG
        printf("%s [%d.%d.%d.%d]\r\n", host->getName(), (unsigned char)host->getIp()[0], (unsigned char)host->getIp()[1], (unsigned char)host->getIp()[2], (unsigned char)host->getIp()[3]);
#endif
    }
    if (! host->getPort()) {
        host->setPort(HTTP_PORT);
    }
    err = http->connect(*host);
    if (err != TCPSOCKET_OK) goto exit;

    // wait connect
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < HTTP_TIMEOUT) {
        if (tcp_ready) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_ready) goto exit;

    // send request
    if (method == METHOD_POST) {
        http->send("POST ", 5);
    } else {
        http->send("GET ", 4);
    }
    http->send(uri, strlen(uri));
    http->send(" HTTP/1.1\r\nHost: ", 17);
    http->send(host->getName(), strlen(host->getName()));
    http->send("\r\n", 2);
    http->send("Connection: close\r\n", 19);
    if (head) {
        http->send(head, strlen(head));
    }
    if (method == METHOD_POST) {
        sprintf(buf, "Content-Length: %d\r\n", strlen(body));
        http->send(buf, strlen(buf));
    }
    http->send("\r\n", 2);

    // post method
    if (method == METHOD_POST && body) {
        http->send(body, strlen(body));
    }

    // wait responce
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < HTTP_TIMEOUT) {
        if (tcp_readable) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_readable) goto exit;

    // recv responce
    i = http->recv(buf, sizeof(buf) - 1);
    buf[i] = 0;
    if (i < sizeof(buf) - 1) tcp_readable = 0;
    if (strncmp(buf, "HTTP/", 5) == 0) {
        ret = atoi(&buf[9]);
    }
#ifdef DEBUG
    printf(buf);
#endif

    // recv dummy
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < HTTP_TIMEOUT) {
        if (tcp_readable) {
            i = http->recv(buf, sizeof(buf) - 1);
            buf[i] = 0;
            if (i < sizeof(buf) - 1) tcp_readable = 0;
#ifdef DEBUG
            printf(buf);
#endif
            timeout.reset();
        } else
        if (! tcp_ready) {
            break;
        }
        Net::poll();
    }
    timeout.stop();

exit:
    http->resetOnEvent();
    http->close();
    delete http;

    return ret;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinyHTTP.h XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny HTTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny HTTP Client
 */

#ifndef TinyHTTP_h
#define TinyHTTP_h

#define DEBUG

#define HTTP_PORT 80
#define HTTP_TIMEOUT 15000 // ms

#define METHOD_GET 0
#define METHOD_POST 1

/** send http request
 * @param method METHOD_GET or METHOD_POST
 * @param host http server
 * @param uri URI
 * @param head http header (CR+LF) (or NULL)
 * @param body POST body (or NULL)
 * @return http code, -1:failue
 */
int httpRequest (int method, Host *host, char *uri, char *head, char *body);

void createauth (char *user, char *pwd, char *buf, int len);

int base64enc(const char *input, unsigned int length, char *output, int len);

int urlencode(char *str, char *buf, int len);

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx main.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "TinyHTTP.h"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
EthernetNetIf eth;


int pachube (int feedid, char *apikey, char *buf) {
    Host host;
    char uri[40], head[160];

    // header
    snprintf(head, sizeof(head), "Content-type: text/csv\r\nX-PachubeApiKey: %s\r\n", apikey);

    // uri
    snprintf(uri, sizeof(uri), "/v1/feeds/%d.csv?_method=put", feedid);

    host.setName("api.pachube.com");
    host.setPort(HTTP_PORT);
    return httpRequest(METHOD_POST, &host, uri, head, buf) == 200 ? 0 : -1;
}

int twitter (char *msg, char *user, char *pwd) {
    Host host;
    char buf[300], head[160];

    // header
    createauth(user, pwd, head, sizeof(head));
    strncat(head, "Content-type: application/x-www-form-urlencoded\r\n", sizeof(head) - strlen(head));

    // post data
    strcpy(buf, "status=");
    urlencode(msg, &buf[strlen(buf)], sizeof(buf) - strlen(buf));

    host.setName("api.supertweet.net");
    host.setPort(HTTP_PORT);
    return httpRequest(METHOD_POST, &host, "/1/statuses/update.xml", head, buf) == 200 ? 0 : -1;
}

int main () {
    EthernetErr ethErr;
    Host host;
    int r;

    myled = 1;
//    pc.baud(115200);

    ethErr = eth.setup();
    if(ethErr) {
        return -1;
    }

    host.setName("mbed.org");
    r = httpRequest(METHOD_GET, &host, "/", NULL, NULL);

//    r = twitter("test from #mbed TinyHTTP", "username", "password");

//    r = pachube(99999, "api key", "1000,30,70");

/*
    host.setName("www.domain.name");
    r = httpRequest(METHOD_POST, &host, "/xxx.cgi", "Content-Type: application/x-www-form-urlencoded\r\n", "key=value&key2=value2");
*/
    printf("status %d\r\n", r);

    myled = 0;
    return 0;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx