Example program demonstrating use of HTTP or HTTPS protocol over a cellular connection with httpbin.org using the MTSAS library. (Demonstrates GET,POST,basic-auth)

Dependencies:   mbed mtsas

Files at this revision

API Documentation at this revision

Comitter:
Vanger
Date:
Mon Mar 16 21:35:01 2015 +0000
Parent:
5:931abf45fb92
Child:
7:c477f2ab9624
Commit message:
Added example code for HTTPS connections. (Trusted certificates are stored in certs.h)

Changed in this revision

certs.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
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/certs.h	Mon Mar 16 21:35:01 2015 +0000
@@ -0,0 +1,62 @@
+/** Any non-root certificates will have no effect on the SSL client, but will
+ * use up extra space for their allocation into the certificate list.
+ * Methods for obtaining the Root CA certificate(s) for a website:
+ * 1. Open a browser to the target website using HTTPS. 
+ *      (These instructions are for Chrome, but should be similar for other browsers)
+ *      Click on the lock icon at the beginning of the url, select the "connection" tab,
+ *      and click the "certificate information" hyperlink. The browser will open a new window
+ *      labeled "Certificate". Switch to the "Certification Path" tab, click the certificate 
+ *      closest to the top of the window, then click "View Certificate". This will open a new
+ *      window labeled "Certificate" again. This time, click on the "Details" tab, then click 
+ *      "Copy to File". This will open a "Certificate Export Wizard". Click next, and choose the 
+ *      "Base-64 encoded X.509 (.CER)" option, then click next. Choose the name and location where
+ *      you want to save the PEM formatted certificate, then click next, then finish. Open the file
+ *      that was created and copy-paste the certificate into this certs.h file. Format the certificate
+ *      data so that each line begins with " and is appended with \r\n"
+ *
+ * 2. Go to https://www.bluessl.com/en/ssltest and enter the website for which you wish to get the root CA
+ *      certificates. Click the [Click here to download the public part of this certificate] button located
+ *      underneath the certificates that label themselves as Root, or Root CA. The root CA certificate should
+ *      self-signed, otherwise it is not the root CA certificate. Take the downloaded file, copy the data
+ *      into this certs.h file, and format the data so that each line begins with " and is appended with \r\n"
+ *      
+ * 3. Using openssl on linux: (Make sure you have openssl installed.) Run the command: openssl s_client
+ *      -showcerts -connect <host>:<port> </dev/null
+ *      Where <host> is the host name (www.google.com for example), and port is the port on which the connection
+ *      will be made (usually 443). When the connection is made with the remote server, the last certificate(s)
+ *      listed will be the Root CA certificate(s). Merely copy-paste those certificates into this certs.h file
+ *      and format them with each line beginning with " and ending with \r\n"
+ *      
+ */
+
+
+//Root Certificates
+char CERTIFICATES[1547] = 
+    
+    //Root certificate Authority for Httpbin.org
+    "-----BEGIN CERTIFICATE-----\r\n"
+    "MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU\r\n"
+    "MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs\r\n"
+    "IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290\r\n"
+    "MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux\r\n"
+    "FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h\r\n"
+    "bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v\r\n"
+    "dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt\r\n"
+    "H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9\r\n"
+    "uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX\r\n"
+    "mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX\r\n"
+    "a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN\r\n"
+    "E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0\r\n"
+    "WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD\r\n"
+    "VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0\r\n"
+    "Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU\r\n"
+    "cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx\r\n"
+    "IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN\r\n"
+    "AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH\r\n"
+    "YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5\r\n"
+    "6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC\r\n"
+    "Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX\r\n"
+    "c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a\r\n"
+    "mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=\r\n"
+    "-----END CERTIFICATE-----\r\n"
+    ;
\ No newline at end of file
--- a/main.cpp	Mon Mar 16 18:41:09 2015 +0000
+++ b/main.cpp	Mon Mar 16 21:35:01 2015 +0000
@@ -1,3 +1,13 @@
+/** For an unsecure HTTP example, just build as is. But, to use the
+ *  HTTPS example, comment out the first main declaration and 
+ *  uncomment the second main declaration at the end of this file.
+ */
+
+//Start of the HTTP code
+///The example HTTP code sets up a connection to httpbin.org,
+///sends a get request on the url: http://httpbin.org/get,
+///then it sends a post request to the url: http://httpbin.org/post
+///Please let us know if you have any questions/would like more examples.
 #include "mbed.h"
 #include "mtsas.h"
 
@@ -13,37 +23,32 @@
     char rbuf[4000];
     
     //url strings for HTTP requests, httpbin.org is a public website for fielding test HTTP requests
-    string url, base_url = "http://httpbin.org:80", url_get = "/get";
+    string url, base_url = "http://httpbin.org:80", url_get = "/get", url_post = "/post";
     
-    /** STMicro Nucelo F401RE
-    * The supported jumper configurations of the MTSAS do not line up with
-    * the pin mapping of the Nucleo F401RE. Therefore, the MTSAS serial TX
-    * pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
-    * and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
-    * Serial1 TX (Shield pin D8).
-    * Uncomment the following line to use the STMicro Nuceleo F401RE
-    */
+    /// STMicro Nucelo F401RE
+    /// The supported jumper configurations of the MTSAS do not line up with
+    /// the pin mapping of the Nucleo F401RE. Therefore, the MTSAS serial TX
+    /// pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
+    /// and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
+    /// Serial1 TX (Shield pin D8).
+    /// Uncomment the following line to use the STMicro Nuceleo F401RE
     MTSSerialFlowControl* io = new MTSSerialFlowControl(D8, D2, D3, D6);
     
-    /** Dragonfly
-    * To configure the serial pins for the Dragonfly board, use:
-    * RADIO_TX = pin PC_7, RADIO_RX = pin PC_6
-    * RADIO_RTS = pin PB_10,RADIO_CTS = pin PB_12
-    * Uncomment the following lines to use the Dragonfly board
-    */
+    /// Dragonfly
+    /// To configure the serial pins for the Dragonfly board, use:
+    /// RADIO_TX = pin PC_7, RADIO_RX = pin PC_6
+    /// RADIO_RTS = pin PB_10,RADIO_CTS = pin PB_12
+    /// Uncomment the following lines to use the Dragonfly board
     //MTSSerialFlowControl* io = new MTSSerialFlowControl(PC_7, PC_6, PB_10, PB_12);
-    //reset_pin = NC;
     
-    /** Freescale KL46Z
-    * To configure the serial pins for the Freescale KL46Z board, use MTSAS jumper
-    * configuration B. Uncomment the following line to use the Freescale KL46Z board
-    */
+    /// Freescale KL46Z
+    /// To configure the serial pins for the Freescale KL46Z board, use MTSAS jumper
+    /// configuration B. Uncomment the following line to use the Freescale KL46Z board
     //MTSSerialFlowControl* io = new MTSSerialFlowControl(D2, D9, D3, D6);
     
-    /** Freescale K64F
-    * To configure the serial pins for the Freescale K64F board, use MTSAS jumper
-    * configuration A. Uncomment the following line to use the Freescale K64F board
-    */
+    /// Freescale K64F
+    /// To configure the serial pins for the Freescale K64F board, use MTSAS jumper
+    /// configuration A. Uncomment the following line to use the Freescale K64F board
     //MTSSerialFlowControl* io = new MTSSerialFlowControl(D1, D0, D3, D6);
     
     //Sets the baud rate for communicating with the radio
@@ -94,7 +99,6 @@
     //Send HTTP GET request
     for (int i = 0; i < 10; i++) {
         if(http->get(url.c_str(), receive, 5000) == HTTP_OK) {
-            http->get(url.c_str(), receive, 5000);
             logInfo("HTTP get succeeded\n%s",  rbuf);
             break;
         }
@@ -104,9 +108,247 @@
         wait(1);
     }
     
+    //Format HTTP POST request
+    url = base_url + url_post;
+    
+    //Create data to send
+    char sbuf[60] = "Hello World! We are testing the MTSAS HTTP Example Program";
+    HTTPText send = HTTPText(sbuf);
+    
+    //Send HTTP POST request
+    for (int i = 0; i < 10; i++) {
+        if(http->post(url.c_str(), send, receive, 5000) == HTTP_OK) {
+            logInfo("HTTP POST succeeded\n%s",  rbuf);
+            break;
+        }
+        if (i >= 10) {
+            logError("HTTP POST failed");
+        }
+        wait(1);
+    }
+    
     //Disconnect PPP link
     radio->disconnect();
     
     logInfo("End of example code\n");
     return 0;
-}
\ No newline at end of file
+}
+//End of the HTTP code
+
+
+//Start of the HTTPS code
+///The example HTTPS code sets up a secure connection to httpbin.org,
+///sends a get request on the url: https://httpbin.org/get,
+///then it sends a post request to the url: https://httpbin.org/post
+///and finally it demonstrates a basic authentication with a get request
+///to the url: https://httpin.org/basic-auth/Bob/123
+///Please let us know if you have any questions/would like more examples.
+/*
+#include "mbed.h"
+#include "mtsas.h"
+#include "certs.h"
+
+//Function to convert http int results to string messages
+char * httpResToStr(HTTPResult res);
+
+int main(){
+    
+    //Modify to match your apn if you are using an HSPA radio with a SIM card
+    const char APN[] = "";
+    
+    //Sets the log level to INFO, higher log levels produce more log output.
+    //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
+    MTSLog::setLogLevel(MTSLog::INFO_LEVEL);
+    
+    //Receive buffer
+    char rbuf[4000];
+    
+    //url strings for HTTPS requests, httpbin.org is a public website for fielding test HTTPS requests
+    string url, secure_url = "https://httpbin.org:443", url_get = "/get", url_auth = "/basic-auth", url_post = "/post";
+    
+    /// STMicro Nucelo F401RE
+    /// The supported jumper configurations of the MTSAS do not line up with
+    /// the pin mapping of the Nucleo F401RE. Therefore, the MTSAS serial TX
+    /// pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
+    /// and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
+    /// Serial1 TX (Shield pin D8).
+    /// Uncomment the following line to use the STMicro Nuceleo F401RE
+    MTSSerialFlowControl* io = new MTSSerialFlowControl(D8, D2, D3, D6);
+    
+    /// Dragonfly
+    /// To configure the serial pins for the Dragonfly board, use:
+    /// RADIO_TX = pin PC_7, RADIO_RX = pin PC_6
+    /// RADIO_RTS = pin PB_10,RADIO_CTS = pin PB_12
+    /// Uncomment the following lines to use the Dragonfly board
+    //MTSSerialFlowControl* io = new MTSSerialFlowControl(PC_7, PC_6, PB_10, PB_12);
+    
+    /// Freescale KL46Z
+    /// To configure the serial pins for the Freescale KL46Z board, use MTSAS jumper
+    /// configuration B. Uncomment the following line to use the Freescale KL46Z board
+    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D2, D9, D3, D6);
+    
+    /// Freescale K64F
+    /// To configure the serial pins for the Freescale K64F board, use MTSAS jumper
+    /// configuration A. Uncomment the following line to use the Freescale K64F board
+    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D1, D0, D3, D6);
+    
+    //Sets the baud rate for communicating with the radio
+    io->baud(115200); 
+    
+    MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
+    
+    //Initialize radio configurations
+    Cellular* radio = CellularFactory::create(io);
+    if( ! radio) {
+        logFatal("Radio initialization failed");
+        return 1;
+    }
+    
+    radio->configureSignals(D4,D7,RESET);
+    Transport::setTransport(radio);
+    
+    //Set radio APN
+    for (int i = 0; i < 10; i++) {
+        if (i >= 10) {
+            logFatal("Failed to set APN to %s", APN);
+            return 1;
+        }
+        if (radio->setApn(APN) == MTS_SUCCESS) {
+            logInfo("Successfully set APN to %s", APN);
+            break;
+        } else {
+            wait(1);
+        }
+    }
+    
+    //Establish PPP link
+    for (int i = 0; i < 10; i++) {
+        if (i >= 10) {
+            logError("Failed to establish PPP link");
+        }
+        if (radio->connect() == true) {
+            logInfo("Successfully established PPP link");
+            break;
+        } else {
+            wait(1);
+        }
+    }
+    
+    //Set up HTTP interface
+    HTTPClient* http = new HTTPClient();
+    HTTPText* receive = new HTTPText(rbuf, 5000);
+    HTTPResult res;
+    
+    //Adds the root certificates for accepted websites to verify that
+    //the remote host is who it says it is. 
+    //Instructions on obtaining the root certificate is included in certs.h
+    //(Basically, only load certificates of trusted websites)
+    //Certificates should be written in PEM format, starts with
+    //-----BEGIN CERTIFICATE----- and ends with -----END CERTIFICATE-----
+    //Each line in between must be less than 64 or less characters in length,
+    //and each line in the certificate must end with /r/n, ex:
+    //-----BEGIN CERTIFICATE-----\r\n
+    //923JNF0A7H43HA3F90JA3JMFGNM9A...\r\n
+    //9823HJ9F8HA8GF283H9A8JF901239...\r\n
+    //239F8A93HUF898AYU230FUA0239UF...\r\n
+    //98HAW9EFH98H9WE8\r\n
+    //-----END CERTIFICATE-----\r\n
+    res = http->addRootCACertificate(CERTIFICATES);
+    if(res != HTTP_OK) {
+        logError("Failed to load CERTIFICATES");
+    }
+    
+    //Call with argument VERIFY_PEER to turn on SSL security (HTTPS)
+    //Default argument is VERIFY_NONE which operates as without SSL security (HTTP)
+    http->setPeerVerification(VERIFY_PEER);
+    
+    //Format HTTPS GET request
+    url = secure_url + url_get;
+    
+    //Send HTTPS GET request
+    for (int i = 0; i < 10; i++) {
+        if(http->get(url.c_str(), receive, 5000) == HTTP_OK) {
+            logInfo("HTTPS GET succeeded\n%s",  rbuf);
+            break;
+        }
+        if (i >= 10) {
+            logError("HTTPS GET failed");
+        }
+        wait(1);
+    }
+    
+    //Format HTTPS POST request
+    url = secure_url + url_post;
+    
+    //Create data to send
+    char sbuf[60] = "Hello World! We are testing the MTSAS HTTPS Example Program";
+    HTTPText send = HTTPText(sbuf);
+    
+    //Send HTTPS POST request
+    for (int i = 0; i < 10; i++) {
+        if(http->post(url.c_str(), send, receive, 5000) == HTTP_OK) {
+            logInfo("HTTPS POST succeeded\n%s",  rbuf);
+            break;
+        }
+        if (i >= 10) {
+            logError("HTTPS POST failed");
+        }
+        wait(1);
+    }
+    
+    //Basic authentication test values, can be modified
+    //to any test username and password. Format for url_usr_pw:  /<user>/<password>
+    string url_usr_pw = "/Bob/123";
+    const char user[] = "Bob",pw[] = "123";
+    
+    //Format HTTPS basic authentication GET request
+    url = secure_url + url_auth + url_usr_pw;
+    
+    res = http->basicAuth(user,pw);
+    logTrace("Set username and password?: %s",httpResToStr(res));
+    
+    res = http->get(url.c_str(), receive);
+        if(res == HTTP_OK) {
+            logInfo("HTTPS Authenticated GET succeeded [%s]",  rbuf);
+        } else {
+            logInfo("HTTPS Authenticated GET failed [%s]", httpResToStr(res));
+        }
+        
+    res = http->basicAuth(NULL,NULL);
+    logTrace("Reset username and password?: %s",httpResToStr(res));
+    
+    return 0;
+}
+
+char * httpResToStr(HTTPResult res) {
+    switch(res) {
+        case HTTP_PROCESSING:
+            return "HTTP_PROCESSING";
+        case HTTP_PARSE:
+            return "HTTP_PARSE";
+        case HTTP_DNS:
+            return "HTTP_DNS";
+        case HTTP_PRTCL:
+            return "HTTP_PRTCL";
+        case HTTP_NOTFOUND:
+            return "HTTP_NOTFOUND";
+        case HTTP_REFUSED:
+            return "HTTP_REFUSED";
+        case HTTP_ERROR:
+            return "HTTP_ERROR";
+        case HTTP_TIMEOUT:
+            return "HTTP_TIMEOUT";
+        case HTTP_CONN:
+            return "HTTP_CONN";
+        case HTTP_CLOSED:
+            return "HTTP_CLOSED";
+        case HTTP_REDIRECT:
+            return "HTTP_REDIRECT";
+        case HTTP_OK:
+            return "HTTP_OK";
+        default:
+            return "HTTP Result unknown";
+    }
+}
+//End of the HTTPS code
+*/
\ No newline at end of file
--- a/mbed.bld	Mon Mar 16 18:41:09 2015 +0000
+++ b/mbed.bld	Mon Mar 16 21:35:01 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/04dd9b1680ae
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/7e07b6fb45cf
\ No newline at end of file