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

Dependencies:   EthernetNetIf mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TinyHTTP.cpp Source File

TinyHTTP.cpp

Go to the documentation of this file.
00001 /*
00002  * mbed Tiny HTTP Client
00003  * Copyright (c) 2011 Hiroshi Suga
00004  * Released under the MIT License: http://mbed.org/license/mit
00005  */
00006 
00007 /** @file
00008  * @brief Tiny HTTP Client
00009  */
00010 
00011 #include "mbed.h"
00012 #include "EthernetNetIf.h"
00013 #include "TCPSocket.h"
00014 #include "DNSRequest.h"
00015 #include "TinyHTTP.h"
00016 #include <ctype.h>
00017 
00018 
00019 TCPSocket *http;
00020 volatile int tcp_ready, tcp_readable, tcp_writable;
00021 volatile int dns_status;
00022 
00023 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00024 int base64enc(const char *input, unsigned int length, char *output, int len) {
00025   static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00026   unsigned int c, c1, c2, c3;
00027 
00028   if (len < ((((length-1)/3)+1)<<2)) return -1;
00029   for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
00030     c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
00031     c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
00032     c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
00033 
00034     c = ((c1 & 0xFC) >> 2);
00035     output[j+0] = base64[c];
00036     c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
00037     output[j+1] = base64[c];
00038     c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
00039     output[j+2] = (length>i+1)?base64[c]:'=';
00040     c = (c3 & 0x3F);
00041     output[j+3] = (length>i+2)?base64[c]:'=';
00042   }
00043   output[(((length-1)/3)+1)<<2] = '\0';
00044   return 0;
00045 }
00046 
00047 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00048 int urlencode(char *str, char *buf, int len) {
00049   static const char to_hex[] = "0123456789ABCDEF";
00050 //  char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
00051   char *pstr = str, *pbuf = buf;
00052 
00053   if (len < (strlen(str) * 3 + 1)) return -1;
00054   while (*pstr) {
00055     if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') {
00056       *pbuf++ = *pstr;
00057     } else if (*pstr == ' ') {
00058       *pbuf++ = '+';
00059     } else { 
00060       *pbuf++ = '%';
00061       *pbuf++ = to_hex[(*pstr >> 4) & 0x0f];
00062       *pbuf++ = to_hex[*pstr & 0x0f];
00063     }
00064     pstr++;
00065   }
00066   *pbuf = '\0';
00067   return 0;
00068 }
00069 
00070 
00071 void isr_http (TCPSocketEvent e) {
00072 
00073 #ifdef DEBUG
00074     printf("tcp(%d)\r\n", e);
00075 #endif
00076     switch(e) {
00077     case TCPSOCKET_CONNECTED:
00078         tcp_ready = 1;
00079         break;
00080 
00081     case TCPSOCKET_READABLE: //Incoming data
00082         tcp_readable = 1;
00083         break;
00084 
00085     case TCPSOCKET_WRITEABLE: //We can send data
00086         tcp_writable = 1;
00087         break;
00088 
00089     case TCPSOCKET_CONTIMEOUT:
00090     case TCPSOCKET_CONRST:
00091     case TCPSOCKET_CONABRT:
00092     case TCPSOCKET_ERROR:
00093     case TCPSOCKET_DISCONNECTED:
00094         tcp_ready = 0;
00095         break;
00096     }
00097 }
00098 
00099 void createauth (char *user, char *pwd, char *buf, int len) {
00100     char tmp[80];
00101 
00102     strncpy(buf, "Authorization: Basic ", len);
00103     snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
00104     base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf));
00105     strncat(buf, "\r\n", len - strlen(buf));
00106 }
00107 
00108 void isr_dns (DNSReply r) {
00109 
00110 #ifdef DEBUG
00111     printf("dns(%d)\r\n", r);
00112 #endif
00113     if (DNS_FOUND) {
00114         dns_status = 1;
00115     } else {
00116         dns_status = -1;
00117     }
00118 }
00119 
00120 int httpRequest (int method, Host *host, char *uri, char *head, char *body) {
00121     TCPSocketErr err;
00122     Timer timeout;
00123     char buf[1500];
00124     int i, ret = -1;
00125 
00126     http = new TCPSocket;
00127     tcp_ready = 0;
00128     tcp_readable = 0;
00129     tcp_writable = 0;
00130 
00131     http->setOnEvent(isr_http);
00132 
00133     // connect
00134     if (host->getIp().isNull()) {
00135         // resolv
00136         DNSRequest dns;
00137         dns_status = 0;
00138         dns.setOnReply(isr_dns);
00139         if (dns.resolve(host) != DNS_OK) goto exit;
00140         timeout.reset();
00141         timeout.start();
00142         while (timeout.read_ms() < HTTP_TIMEOUT) {
00143             if (dns_status) break;
00144             Net::poll();
00145         }
00146         timeout.stop();
00147         if (dns_status <= 0) goto exit;
00148 #ifdef DEBUG
00149         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]);
00150 #endif
00151     }
00152     if (! host->getPort()) {
00153         host->setPort(HTTP_PORT);
00154     }
00155     err = http->connect(*host);
00156     if (err != TCPSOCKET_OK) goto exit;
00157 
00158     // wait connect
00159     timeout.reset();
00160     timeout.start();
00161     while (timeout.read_ms() < HTTP_TIMEOUT) {
00162         if (tcp_ready) break;
00163         Net::poll();
00164     }
00165     timeout.stop();
00166     if (! tcp_ready) goto exit;
00167 
00168     // send request
00169     if (method == METHOD_POST) {
00170         http->send("POST ", 5);
00171     } else {
00172         http->send("GET ", 4);
00173     }
00174     http->send(uri, strlen(uri));
00175     http->send(" HTTP/1.1\r\nHost: ", 17);
00176     http->send(host->getName(), strlen(host->getName()));
00177     http->send("\r\n", 2);
00178     http->send("Connection: close\r\n", 19);
00179     if (head) {
00180         http->send(head, strlen(head));
00181     }
00182     if (method == METHOD_POST) {
00183         sprintf(buf, "Content-Length: %d\r\n", strlen(body));
00184         http->send(buf, strlen(buf));
00185     }
00186     http->send("\r\n", 2);
00187 
00188     // post method
00189     if (method == METHOD_POST && body) {
00190         http->send(body, strlen(body));
00191     }
00192 
00193     // wait responce
00194     timeout.reset();
00195     timeout.start();
00196     while (timeout.read_ms() < HTTP_TIMEOUT) {
00197         if (tcp_readable) break;
00198         Net::poll();
00199     }
00200     timeout.stop();
00201     if (! tcp_readable) goto exit;
00202 
00203     // recv responce
00204     i = http->recv(buf, sizeof(buf) - 1);
00205     buf[i] = 0;
00206     if (i < sizeof(buf) - 1) tcp_readable = 0;
00207     if (strncmp(buf, "HTTP/", 5) == 0) {
00208         ret = atoi(&buf[9]);
00209     }
00210 #ifdef DEBUG
00211     printf(buf);
00212 #endif
00213 
00214     // recv dummy
00215     timeout.reset();
00216     timeout.start();
00217     while (timeout.read_ms() < HTTP_TIMEOUT) {
00218         if (tcp_readable) {
00219             i = http->recv(buf, sizeof(buf) - 1);
00220             buf[i] = 0;
00221             if (i < sizeof(buf) - 1) tcp_readable = 0;
00222 #ifdef DEBUG
00223             printf(buf);
00224 #endif
00225             timeout.reset();
00226         } else
00227         if (! tcp_ready) {
00228             break;
00229         }
00230         Net::poll();
00231     }
00232     timeout.stop();
00233 
00234 exit:
00235     http->resetOnEvent();
00236     http->close();
00237     delete http;
00238 
00239     return ret;
00240 }