Tiny HTTP Client http://mbed.org/users/okini3939/notebook/tinyhttp

Dependencies:   EthernetNetIf mbed

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Thu Jul 28 16:35:09 2011 +0000
Parent:
1:9f15e579d914
Commit message:

Changed in this revision

TinyHTTP.cpp Show annotated file Show diff for this revision Revisions of this file
TinyHTTP.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 9f15e579d914 -r 764ecec3dc59 TinyHTTP.cpp
--- a/TinyHTTP.cpp	Wed Jul 27 16:19:14 2011 +0000
+++ b/TinyHTTP.cpp	Thu Jul 28 16:35:09 2011 +0000
@@ -13,21 +13,19 @@
 #include "TCPSocket.h"
 #include "DNSRequest.h"
 #include "TinyHTTP.h"
-
-#define STATUS_NONE 0
-#define STATUS_READABLE 1
-#define STATUS_CONNECTED 2
-#define STATUS_ERROR 3
-#define STATUS_DISCONNECTED 4
+#include <ctype.h>
 
 
 TCPSocket *http;
-volatile int tcp_status = 0, dns_status = 0;
+volatile int tcp_ready, tcp_readable, tcp_writable;
+volatile int dns_status;
 
 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
-void base64enc(const char *input, unsigned int length, char *output) {
+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;
@@ -43,26 +41,32 @@
     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 url_encode(char *str, char *buf, int len) {
+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;
-  if (len < strlen(str) * 3 + 1) return -1;
   char *pstr = str, *pbuf = buf;
+
+  if (len < (strlen(str) * 3 + 1)) return -1;
   while (*pstr) {
-    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
+    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') {
       *pbuf++ = *pstr;
-    else if (*pstr == ' ') 
+    } else if (*pstr == ' ') {
       *pbuf++ = '+';
-    else 
-      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
+    } else { 
+      *pbuf++ = '%';
+      *pbuf++ = to_hex[(*pstr >> 4) & 0x0f];
+      *pbuf++ = to_hex[*pstr & 0x0f];
+    }
     pstr++;
   }
   *pbuf = '\0';
   return 0;
 }
-*/
+
 
 void isr_http (TCPSocketEvent e) {
 
@@ -70,37 +74,42 @@
     printf("tcp(%d)\r\n", e);
 #endif
     switch(e) {
-    case TCPSOCKET_READABLE: //Incoming data
-        tcp_status = STATUS_READABLE;
+    case TCPSOCKET_CONNECTED:
+        tcp_ready = 1;
         break;
 
-    case TCPSOCKET_CONNECTED:
+    case TCPSOCKET_READABLE: //Incoming data
+        tcp_readable = 1;
+        break;
+
     case TCPSOCKET_WRITEABLE: //We can send data
-        tcp_status = STATUS_CONNECTED;
+        tcp_writable = 1;
         break;
 
     case TCPSOCKET_CONTIMEOUT:
     case TCPSOCKET_CONRST:
     case TCPSOCKET_CONABRT:
     case TCPSOCKET_ERROR:
-        tcp_status = STATUS_ERROR;
-        break;
-
     case TCPSOCKET_DISCONNECTED:
-        tcp_status = STATUS_DISCONNECTED;
+        tcp_ready = 0;
         break;
     }
 }
 
-void createauth (char *user, char *pwd, char *buf) {
+void createauth (char *user, char *pwd, char *buf, int len) {
     char tmp[80];
 
-    snprintf(tmp, sizeof(tmp), "Authorization: Basic %s:%s\n", user, pwd);
-    base64enc(tmp, strlen(tmp), buf);
+    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 {
@@ -110,26 +119,35 @@
 
 int httpRequest (int method, Host *host, char *uri, char *head, char *body) {
     TCPSocketErr err;
-    char buf[500];
+    Timer timeout;
+    char buf[1500];
     int i, ret = -1;
 
     http = new TCPSocket;
-    tcp_status = STATUS_NONE;
+    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;
-        for (i = 0; i < HTTP_TIMEOUT / 10; i ++) {
+        timeout.reset();
+        timeout.start();
+        while (timeout.read_ms() < HTTP_TIMEOUT) {
             if (dns_status) break;
             Net::poll();
-            wait_ms(10);
         }
-        while (dns_status < 0) goto exit;
+        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);
@@ -138,12 +156,14 @@
     if (err != TCPSOCKET_OK) goto exit;
 
     // wait connect
-    for (i = 0; i < HTTP_TIMEOUT / 10; i ++) {
-        if (tcp_status != STATUS_NONE) break;
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < HTTP_TIMEOUT) {
+        if (tcp_ready) break;
         Net::poll();
-        wait_ms(10);
     }
-    if (tcp_status != STATUS_CONNECTED) goto exit;
+    timeout.stop();
+    if (! tcp_ready) goto exit;
 
     // send request
     if (method == METHOD_POST) {
@@ -171,17 +191,20 @@
     }
 
     // wait responce
-    for (i = 0; i < 1500; i ++) {
-        if (tcp_status != STATUS_CONNECTED) break;
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < HTTP_TIMEOUT) {
+        if (tcp_readable) break;
         Net::poll();
-        wait_ms(10);
     }
-    if (tcp_status != STATUS_READABLE) goto exit;
+    timeout.stop();
+    if (! tcp_readable) goto exit;
 
     // recv responce
-    i = http->recv(buf, sizeof(buf));
+    i = http->recv(buf, sizeof(buf) - 1);
     buf[i] = 0;
-    if (strncmp(buf, "HTTP", 4) == 0) {
+    if (i < sizeof(buf) - 1) tcp_readable = 0;
+    if (strncmp(buf, "HTTP/", 5) == 0) {
         ret = atoi(&buf[9]);
     }
 #ifdef DEBUG
@@ -189,23 +212,24 @@
 #endif
 
     // recv dummy
-    for (i = 0; i < HTTP_TIMEOUT / 10; i ++) {
-        switch (tcp_status) {
-        case STATUS_READABLE:
-            int n = http->recv(buf, sizeof(buf));
-            buf[n] = 0;
-            i = 0;
+    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;
-        case STATUS_DISCONNECTED:
-        case STATUS_ERROR:
-            goto exit;
         }
         Net::poll();
-        wait_ms(10);
     }
+    timeout.stop();
 
 exit:
     http->resetOnEvent();
diff -r 9f15e579d914 -r 764ecec3dc59 TinyHTTP.h
--- a/TinyHTTP.h	Wed Jul 27 16:19:14 2011 +0000
+++ b/TinyHTTP.h	Thu Jul 28 16:35:09 2011 +0000
@@ -29,4 +29,10 @@
  */
 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
diff -r 9f15e579d914 -r 764ecec3dc59 main.cpp
--- a/main.cpp	Wed Jul 27 16:19:14 2011 +0000
+++ b/main.cpp	Thu Jul 28 16:35:09 2011 +0000
@@ -7,12 +7,46 @@
 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) {
@@ -21,6 +55,11 @@
 
     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");