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

Dependencies:   EthernetNetIf mbed

Revision:
0:f2bf5f966801
Child:
1:9f15e579d914
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TinyHTTP.cpp	Wed Jul 27 16:08:54 2011 +0000
@@ -0,0 +1,215 @@
+/*
+ * 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"
+
+#define STATUS_NONE 0
+#define STATUS_READABLE 1
+#define STATUS_CONNECTED 2
+#define STATUS_ERROR 3
+#define STATUS_DISCONNECTED 4
+
+
+TCPSocket *http;
+volatile int tcp_status = 0, dns_status = 0;
+
+// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+void base64enc(const char *input, unsigned int length, char *output) {
+  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  unsigned int c, c1, c2, c3;
+  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';
+}
+/*
+// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+int url_encode(char *str, char *buf, int len) {
+//  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;
+  while (*pstr) {
+    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
+      *pbuf++ = *pstr;
+    else if (*pstr == ' ') 
+      *pbuf++ = '+';
+    else 
+      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
+    pstr++;
+  }
+  *pbuf = '\0';
+  return 0;
+}
+*/
+
+void isr_http (TCPSocketEvent e) {
+
+#ifdef DEBUG
+    printf("tcp(%d)\r\n", e);
+#endif
+    switch(e) {
+    case TCPSOCKET_READABLE: //Incoming data
+        tcp_status = STATUS_READABLE;
+        break;
+
+    case TCPSOCKET_CONNECTED:
+    case TCPSOCKET_WRITEABLE: //We can send data
+        tcp_status = STATUS_CONNECTED;
+        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;
+        break;
+    }
+}
+
+void createauth (char *user, char *pwd, char *buf) {
+    char tmp[80];
+
+    snprintf(tmp, sizeof(tmp), "Authorization: Basic %s:%s\n", user, pwd);
+    base64enc(tmp, strlen(tmp), buf);
+}
+
+void isr_dns (DNSReply r) {
+
+    if (DNS_FOUND) {
+        dns_status = 1;
+    } else {
+        dns_status = -1;
+    }
+}
+
+int httpRequest (int method, Host *host, char *uri, char *head, char *body) {
+    TCPSocketErr err;
+    char buf[500];
+    int i, ret = -1;
+
+    http = new TCPSocket;
+    tcp_status = STATUS_NONE;
+
+    http->setOnEvent(isr_http);
+
+    // connect
+    if (host->getIp().isNull()) {
+        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 ++) {
+            if (dns_status) break;
+            Net::poll();
+            wait_ms(10);
+        }
+        while (dns_status < 0) goto exit;
+    }
+    if (! host->getPort()) {
+        host->setPort(HTTP_PORT);
+    }
+    err = http->connect(*host);
+    if (err != TCPSOCKET_OK) goto exit;
+
+    // wait connect
+    for (i = 0; i < HTTP_TIMEOUT / 10; i ++) {
+        if (tcp_status != STATUS_NONE) break;
+        Net::poll();
+        wait_ms(10);
+    }
+    if (tcp_status != STATUS_CONNECTED) 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);
+    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
+    for (i = 0; i < 1500; i ++) {
+        if (tcp_status != STATUS_CONNECTED) break;
+        Net::poll();
+        wait_ms(10);
+    }
+    if (tcp_status != STATUS_READABLE) goto exit;
+
+    // recv responce
+    i = http->recv(buf, sizeof(buf));
+    buf[i] = 0;
+    if (strncmp(buf, "HTTP", 4) == 0) {
+        ret = atoi(&buf[9]);
+    }
+#ifdef DEBUG
+    printf(buf);
+#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;
+#ifdef DEBUG
+            printf(buf);
+#endif
+            break;
+        case STATUS_DISCONNECTED:
+        case STATUS_ERROR:
+            goto exit;
+        }
+        Net::poll();
+        wait_ms(10);
+    }
+
+exit:
+    http->resetOnEvent();
+    http->close();
+    delete http;
+
+    return ret;
+}