nil jack
/
NuMaker-mbed-AWS-IoT-example
test
Revision 0:9d5f28595388, committed 2018-03-14
- Comitter:
- kernel2418
- Date:
- Wed Mar 14 03:03:16 2018 +0000
- Commit message:
- test
Changed in this revision
diff -r 000000000000 -r 9d5f28595388 .gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gitignore Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,6 @@ +.mbed +.build/ +BUILD/ +easy-connect/ +mbed-os/ +MQTT/
diff -r 000000000000 -r 9d5f28595388 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,9 @@ +# Use Python/Perl regexp +syntax: regexp + +^\.mbed$ +\.build/ +BUILD/ +easy-connect/ +mbed-os/ +MQTT/ \ No newline at end of file
diff -r 000000000000 -r 9d5f28595388 .mbedignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.mbedignore Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,6 @@ +easy-connect/atmel-rf-driver/* +easy-connect/mcr20a-rf-driver/* +easy-connect/stm-spirit1-rf-driver/* +easy-connect/wifi-x-nucleo-idw01m1/* + +
diff -r 000000000000 -r 9d5f28595388 MQTT.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MQTT.lib Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/teams/mqtt/code/MQTT/#9cff7b6bbd01
diff -r 000000000000 -r 9d5f28595388 README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,334 @@ +# Example for Connection with AWS IoT thru MQTT/HTTPS on Mbed OS + +This is an example to demonstrate connection with [AWS IoT](https://aws.amazon.com/iot) +on Nuvoton Mbed-enabled boards. + +## Supported platforms +On Mbed OS, connection with AWS IoT requires Mbed TLS. It requires more than 64 KB RAM. +Currently, the following Nuvoton Mbed-enalbed boards can afford such memory footprint: +- [NuMaker-PFM-NUC472](https://developer.mbed.org/platforms/Nuvoton-NUC472/) +- [NuMaker-PFM-M487](https://developer.mbed.org/platforms/NUMAKER-PFM-M487/) + +## Access and manage AWS IoT Service +To run the example, you need to register one [AWS account](https://aws.amazon.com/) +to access and manage AWS IoT Service for your device to connect with. +This [link](https://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html) gives detailed +information about it. + +1. Sign in to [AWS Management Console](https://aws.amazon.com/console/). +1. Enter AWS IoT Service. +1. In AWS IoT Service, create a thing. +The Console may prompt you to also create a certificate and a policy. Skip for creating them later. +1. In AWS IoT Service, create a policy. A workable example would be below. +Note that you need to replace **REGION** and **ACCOUNT** to match your case. + + <pre> + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "iot:Connect", + "Resource": "arn:aws:iot:<b>REGION</b>:<b>ACCOUNT</b>:client/*" + }, + { + "Effect": "Allow", + "Action": "iot:Subscribe", + "Resource": ["arn:aws:iot:<b>REGION</b>:<b>ACCOUNT</b>:topicfilter/*"] + }, + { + "Effect": "Allow", + "Action": ["iot:Publish", "iot:Receive"], + "Resource": "arn:aws:iot:<b>REGION</b>:<b>ACCOUNT</b>:topic/*" + }, + { + "Effect": "Allow", + "Action": ["iot:UpdateThingShadow", "iot:GetThingShadow", "iot:DeleteThingShadow"], + "Resource": "arn:aws:iot:<b>REGION</b>:<b>ACCOUNT</b>:thing/*" + } + ] + } + </pre> + +1. In AWS IoT Service, create a certificate. You would get 4 security credential files from it. + Download them for later use. + - AWS IoT's CA certificate + - User certificate + - User private key + - User public key + + After creating the certificate, do: + 1. Activate the certificate + 1. Attach the thing created above to the certificate + 1. Attach the policy created above to the certificate + +## Configure your device with AWS IoT +Before connecting your device with AWS IoT, you need to configure security credential and +protocol dependent parameters into your device. These configurations are all centralized in `main.cpp`. + +### Configure certificate into your device +From above, you've got 4 security credential files: CA certificate and user certificate/private key/public key. +Configure CA certificate, user certificate, and user private key into your device. +User public key has been included in user certificate and is not used here. +1. Replace CA certificate with downloaded from the Console. + ``` + const char SSL_CA_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" + "MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n" + "yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n" + ``` + +1. Replace user certificate with downloaded from the Console. + ``` + const char SSL_USER_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" + "MIIDWjCCAkKgAwIBAgIVALN/H7tr8cgpl2zwg0JjEE106XilMA0GCSqGSIb3DQEB\n" + "CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\n" + ``` + +1. Replace user private key with downloaded from the Console. + ``` + const char SSL_USER_PRIV_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n" + ``` + +**NOTE:** The credential hard-coded in source code is deactivated or deleted. + Use your own credential for connection with AWS IoT. + +### Connect through MQTT +To connect your device with AWS IoT through MQTT, you need to configure the following parameters. + +1. Enable connection through MQTT. + ``` + #define AWS_IOT_MQTT_TEST 1 + ``` + +1. Replace server name (endpoint). **Endpoint** has the following format and you just + need to modify **IDENTIFIER** and **REGION** to match your case. + <pre> + #define AWS_IOT_MQTT_SERVER_NAME "<b>IDENTIFIER</b>.iot.<b>REGION</b>.amazonaws.com" + </pre> + +1. Server port number is fixed. Don't change it. + ``` + #define AWS_IOT_MQTT_SERVER_PORT 8883 + ``` + +1. Replace **THINGNAME** to match your case. The **THINGNAME** is just the name of the thing you've created above. + <pre> + #define AWS_IOT_MQTT_THINGNAME "<b>THINGNAME</b>" + </pre> + +1. Replace **CLIENTNAME** to match your case. If you adopt the example policy above, + you can modify it arbitrarily because the policy permits any client name bound to your account. + <pre> + #define AWS_IOT_MQTT_CLIENTNAME "<b>CLIENTNAME</b>" + </pre> + +AWS IoT MQTT protocol supports topic subscribe/publish. The example demonstrates: +- Subscribe/publish with user topic +- Subscribe/publish with reserved topic (starting with $) to: + - Update thing shadow + - Get thing shadow + - Delete thing shadow + +### Connect through HTTPS +To connect your device with AWS IoT through HTTPS, you need to configure the following parameters. + +1. Enable connection through HTTPS. + ``` + #define AWS_IOT_HTTPS_TEST 1 + ``` + +1. Replace server name (endpoint). **Endpoint** has the following format and you just + need to modify **IDENTIFIER** and **REGION** to match your case. + <pre> + #define AWS_IOT_HTTPS_SERVER_NAME "<b>IDENTIFIER</b>.iot.<b>REGION</b>.amazonaws.com" + </pre> + +1. Server port number is fixed. Don't change it. + ``` + #define AWS_IOT_HTTPS_SERVER_PORT 8443 + ``` + +1. Replace **THINGNAME** to match your case. The **THINGNAME** is just the name of the thing you've created above. + <pre> + #define AWS_IOT_HTTPS_THINGNAME "<b>THINGNAME</b>" + </pre> + +AWS IoT HTTPS protocol supports topic publish-only and RESTful API. The example demonstrates: +- Publish to user topic +- Publish to reserved topic (starting with $) to: + - Update thing shadow + - Get thing shadow + - Delete thing shadow +- RESTful API to: + - Update thing shadow RESTfully through HTTPS/POST method + - Get thing shadow RESTfully through HTTPS/GET method + - Delete thing shadow RESTfully through HTTPS/DELETE method + +## Patch MQTT library +Currently, MQTT library has one issue with unsubscribe from topic multiple times. Fix it: + +In `MQTT/MQTTClient.h` > `MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::cycle`, +<pre> +switch (packet_type) + { + default: + // no more data to read, unrecoverable. Or read packet fails due to unexpected network error + rc = packet_type; + goto exit; + case 0: // timed out reading packet + break; + case CONNACK: + case PUBACK: + case SUBACK: + <b> + case UNSUBACK: + </b> + break; + case PUBLISH: + { +</pre> + +## Monitor the application +If you configure your terminal program with **9600/8-N-1**, you would see output similar to: + +**NOTE:** Make sure that the network is functional before running the application. + +<pre> +Starting AWS IoT test +Using Mbed OS 5.7.1 +[EasyConnect] IPv4 mode +Connecting with a1fbcwaqfqeozo.iot.us-east-1.amazonaws.com:8883 +Connecting to a1fbcwaqfqeozo.iot.us-east-1.amazonaws.com:8883 +</pre> + +If you get here successfully, it means configurations with security credential are correct. +<pre> +Starting the TLS handshake... +TLS connection to a1fbcwaqfqeozo.iot.us-east-1.amazonaws.com:8883 established +Server certificate: + cert. version : 3 + serial number : 3C:AC:B3:D3:3E:D8:6A:C9:2B:EF:D2:C5:B1:DC:BF:66 + issuer name : C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 ECC 256 bit SSL CA - G2 + subject name : C=US, ST=Washington, L=Seattle, O=Amazon.com, Inc., CN=*.iot.us-east-1.amazonaws.com + issued on : 2017-03-07 00:00:00 + expires on : 2018-03-08 23:59:59 + signed using : ECDSA with SHA256 + EC key size : 256 bits + basic constraints : CA=false + subject alt name : iot.us-east-1.amazonaws.com, *.iot.us-east-1.amazonaws.com + key usage : Digital Signature + ext key usage : TLS Web Server Authentication, TLS Web Client Authentication +Certificate verification passed + +Connects with a1fbcwaqfqeozo.iot.us-east-1.amazonaws.com:8883 OK +</pre> + +MQTT handshake goes: +<pre> +MQTT connects OK + +Subscribing/publishing user topic +MQTT subscribes to Nuvoton/Mbed/+ OK +Message to publish: +{ "message": "Hello from Nuvoton Mbed device" } +MQTT publishes message to Nuvoton/Mbed/D001 OK +Message arrived: qos 1, retained 0, dup 0, packetid 1 +Payload: +{ "message": "Hello from Nuvoton Mbed device" } + +MQTT unsubscribes from Nuvoton/Mbed/+ OK +Subscribes/publishes user topic OK + +Subscribing/publishing UpdateThingShadow topic +MQTT subscribes to $aws/things/Nuvoton-Mbed-D001/shadow/update/accepted OK +MQTT subscribes to $aws/things/Nuvoton-Mbed-D001/shadow/update/rejected OK +Message to publish: +{ "state": { "reported": { "attribute1": 3, "attribute2": "1" } } } +MQTT publishes message to $aws/things/Nuvoton-Mbed-D001/shadow/update OK +Message arrived: qos 1, retained 0, dup 0, packetid 1 +Payload: +{"state":{"reported":{"attribute1":3,"attribute2":"1"}},"metadata":{"reported":{"attribute1":{"timestamp":1514962195},"attribute2":{"timestamp":1514962195}}},"version":77,"timestamp":1514962195} + +MQTT unsubscribes from $aws/things/Nuvoton-Mbed-D001/shadow/update/accepted OK +MQTT unsubscribes from $aws/things/Nuvoton-Mbed-D001/shadow/update/rejected OK +Subscribes/publishes UpdateThingShadow topic OK + +Subscribing/publishing GetThingShadow topic +MQTT subscribes to $aws/things/Nuvoton-Mbed-D001/shadow/get/accepted OK +MQTT subscribes to $aws/things/Nuvoton-Mbed-D001/shadow/get/rejected OK +Message to publish: + +MQTT publishes message to $aws/things/Nuvoton-Mbed-D001/shadow/get OK +Message arrived: qos 1, retained 0, dup 0, packetid 1 +Payload: +{"state":{"reported":{"attribute1":3,"attribute2":"1"}},"metadata":{"reported":{"attribute1":{"timestamp":1514962195},"attribute2":{"timestamp":1514962195}}},"version":77,"timestamp":1514962198} + +MQTT unsubscribes from $aws/things/Nuvoton-Mbed-D001/shadow/get/accepted OK +MQTT unsubscribes from $aws/things/Nuvoton-Mbed-D001/shadow/get/rejected OK +Subscribes/publishes GetThingShadow topic OK + +Subscribing/publishing DeleteThingShadow topic +MQTT subscribes to $aws/things/Nuvoton-Mbed-D001/shadow/delete/accepted OK +MQTT subscribes to $aws/things/Nuvoton-Mbed-D001/shadow/delete/rejected OK +Message to publish: + +MQTT publishes message to $aws/things/Nuvoton-Mbed-D001/shadow/delete OK +Message arrived: qos 1, retained 0, dup 0, packetid 1 +Payload: +{"version":77,"timestamp":1514962202} + +MQTT unsubscribes from $aws/things/Nuvoton-Mbed-D001/shadow/delete/accepted OK +MQTT unsubscribes from $aws/things/Nuvoton-Mbed-D001/shadow/delete/rejected OK +Subscribes/publishes DeleteThingShadow topic OK + +MQTT disconnects OK +</pre> + +Dynamic memory footprint (heap) is output below. +Static memory footprint (global/stack) could be obtained by inspecting MAP file. +You could get total memory footprint by adding these two together. +<pre> +Current heap size: 1351 +Max heap size: 63022 +</pre> + +## Trouble-shooting +- Over ESP8266 WiFi, + if you make a loop test like below (`main.cpp`), you may always meet errors in the following loops + after some network error has happened in the previous one. + <pre> + <b>while (true) {</b> + #if AWS_IOT_MQTT_TEST + AWS_IoT_MQTT_Test *mqtt_test = new AWS_IoT_MQTT_Test(AWS_IOT_MQTT_SERVER_NAME, AWS_IOT_MQTT_SERVER_PORT, network); + mqtt_test->start_test(); + delete mqtt_test; + #endif // End of AWS_IOT_MQTT_TEST + + #if AWS_IOT_HTTPS_TEST + AWS_IoT_HTTPS_Test *https_test = new AWS_IoT_HTTPS_Test(AWS_IOT_HTTPS_SERVER_NAME, AWS_IOT_HTTPS_SERVER_PORT, network); + https_test->start_test(); + delete https_test; + #endif // End of AWS_IOT_HTTPS_TEST + <b>}</b> + </pre> + This issue would be caused by failure of ESP8266 AT commands **CLOSE**/**DISCONNECT** + because ESP8266 F/W is still busy in handling previous unfinished network transfer + due to bad network status and fails these commands. + These commands must be OK for ESP8266 F/W to reset connection state correctly. + If that happens, try enlarging [ESP8266 driver's](https://github.com/ARMmbed/esp8266-driver) timeout configuration. + For example, enlarge `ESP8266_SEND_TIMEOUT`/`ESP8266_RECV_TIMEOUT`/`ESP8266_MISC_TIMEOUT` (defined in + [ESP8266Interface.cpp](https://github.com/ARMmbed/esp8266-driver/blob/master/ESP8266Interface.cpp)) + to 5000/5000/5000 ms respectively (through `mbed_app.json`). + <pre> + { + "macros": [ + "MBED_CONF_APP_MAIN_STACK_SIZE=4096", + "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_user_config.h\"", + "MBED_HEAP_STATS_ENABLED=1", + "MBED_MEM_TRACING_ENABLED=1", + <b>"ESP8266_SEND_TIMEOUT=5000",</b> + <b>"ESP8266_RECV_TIMEOUT=5000",</b> + <b>"ESP8266_MISC_TIMEOUT=5000"</b> + ], + "config": { + </pre> \ No newline at end of file
diff -r 000000000000 -r 9d5f28595388 TLSSocket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TLSSocket.h Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,420 @@ +#ifndef _TLS_SOCKET_H_ +#define _TLS_SOCKET_H_ + +/* Change to a number between 1 and 4 to debug the TLS connection */ +#define DEBUG_LEVEL 0 + +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +#if DEBUG_LEVEL > 0 +#include "mbedtls/debug.h" +#endif + +#include "mbedtls_utils.h" + +/** + * \brief TLSSocket a wrapper around TCPSocket for interacting with TLS servers + */ +class TLSSocket { +public: + TLSSocket(NetworkInterface* net_iface, const char* ssl_ca_pem, const char* ssl_owncert_pem, const char* ssl_own_priv_key_pem) { + _tcpsocket = new TCPSocket(net_iface); + _ssl_ca_pem = ssl_ca_pem; + _ssl_owncert_pem = ssl_owncert_pem; + _ssl_own_priv_key_pem = ssl_own_priv_key_pem; + _is_connected = false; + _debug = false; + _hostname = NULL; + _port = 0; + _error = 0; + + DRBG_PERS = "mbed TLS helloword client"; + + mbedtls_entropy_init(&_entropy); + mbedtls_ctr_drbg_init(&_ctr_drbg); + mbedtls_x509_crt_init(&_cacert); + mbedtls_x509_crt_init(&_owncert); + mbedtls_pk_init(&_own_priv_key); + mbedtls_ssl_init(&_ssl); + mbedtls_ssl_config_init(&_ssl_conf); + } + + ~TLSSocket() { + mbedtls_entropy_free(&_entropy); + mbedtls_ctr_drbg_free(&_ctr_drbg); + mbedtls_x509_crt_free(&_cacert); + mbedtls_x509_crt_free(&_owncert); + mbedtls_pk_free(&_own_priv_key); + mbedtls_ssl_free(&_ssl); + mbedtls_ssl_config_free(&_ssl_conf); + + if (_tcpsocket) { + _tcpsocket->close(); + delete _tcpsocket; + } + + // @todo: free DRBG_PERS ? + } + + /** Close the socket + * + * Closes any open connection and deallocates any memory associated + * with the socket. Called from destructor if socket is not closed. + * + * @return 0 on success, negative error code on failure + */ + nsapi_error_t close() { + return _tcpsocket->close(); + } + + nsapi_error_t connect(const char *hostname, uint16_t port) { + _hostname = hostname; + _port = port; + + /* Initialize the flags */ + /* + * Initialize TLS-related stuf. + */ + int ret; + if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy, + (const unsigned char *) DRBG_PERS, + sizeof (DRBG_PERS))) != 0) { + print_mbedtls_error("mbedtls_crt_drbg_init", ret); + _error = ret; + return _error; + } + + if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *)_ssl_ca_pem, + strlen(_ssl_ca_pem) + 1)) != 0) { + print_mbedtls_error("mbedtls_x509_crt_parse", ret); + _error = ret; + return _error; + } + + if ((ret = mbedtls_x509_crt_parse(&_owncert, (const unsigned char *) _ssl_owncert_pem, + strlen(_ssl_owncert_pem) + 1)) != 0) { + print_mbedtls_error("mbedtls_x509_crt_parse", ret); + _error = ret; + return _error; + } + + if ((ret = mbedtls_pk_parse_key(&_own_priv_key, (const unsigned char *) _ssl_own_priv_key_pem, + strlen(_ssl_own_priv_key_pem) + 1, NULL, 0)) != 0) { + print_mbedtls_error("mbedtls_pk_parse_key", ret); + _error = ret; + return _error; + } + + if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + print_mbedtls_error("mbedtls_ssl_config_defaults", ret); + _error = ret; + return _error; + } + + mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL); + mbedtls_ssl_conf_own_cert(&_ssl_conf, &_owncert, &_own_priv_key); + mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); + + /* It is possible to disable authentication by passing + * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode() + */ + mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); + +#if DEBUG_LEVEL > 0 + mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL); + mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL); + mbedtls_debug_set_threshold(DEBUG_LEVEL); +#endif + + if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) { + print_mbedtls_error("mbedtls_ssl_setup", ret); + _error = ret; + return _error; + } + + mbedtls_ssl_set_hostname(&_ssl, _hostname); + + mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(_tcpsocket), + ssl_send, ssl_recv, NULL ); + + /* Connect to the server */ + if (_debug) mbedtls_printf("Connecting to %s:%d\r\n", _hostname, _port); + ret = _tcpsocket->connect(_hostname, _port); + if (ret != NSAPI_ERROR_OK) { + if (_debug) mbedtls_printf("Failed to connect\r\n"); + onError(_tcpsocket, -1); + return _error; + } + + /* Start the handshake, the rest will be done in onReceive() */ + if (_debug) mbedtls_printf("Starting the TLS handshake...\r\n"); + do { + ret = mbedtls_ssl_handshake(&_ssl); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); + if (ret < 0) { + print_mbedtls_error("mbedtls_ssl_handshake", ret); + onError(_tcpsocket, ret); + return ret; + } + + /* It also means the handshake is done, time to print info */ + if (_debug) mbedtls_printf("TLS connection to %s:%d established\r\n", _hostname, _port); + + const uint32_t buf_size = 1024; + char *buf = new char[buf_size]; + mbedtls_x509_crt_info(buf, buf_size, "\r ", + mbedtls_ssl_get_peer_cert(&_ssl)); + if (_debug) mbedtls_printf("Server certificate:\r\n%s\r", buf); + + uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl); + if( flags != 0 ) + { + mbedtls_x509_crt_verify_info(buf, buf_size, "\r ! ", flags); + if (_debug) mbedtls_printf("Certificate verification failed:\r\n%s\r\r\n", buf); + } + else { + if (_debug) mbedtls_printf("Certificate verification passed\r\n\r\n"); + } + delete [] buf; + buf = NULL; + + _is_connected = true; + + return 0; + } + + /** Send data over a TCP socket + * + * The socket must be connected to a remote host. Returns the number of + * bytes sent from the buffer. + * + * By default, send blocks until all data is sent. If socket is set to + * non-blocking or times out, a partial amount can be written. + * NSAPI_ERROR_WOULD_BLOCK is returned if no data was written. + * + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @return Number of sent bytes on success, negative error + * code on failure + */ + nsapi_size_or_error_t send(const void *data, nsapi_size_t size) { + return mbedtls_ssl_write(&_ssl, (const uint8_t *) data, size); + } + + /** Receive data over a TCP socket + * + * The socket must be connected to a remote host. Returns the number of + * bytes received into the buffer. + * + * By default, recv blocks until some data is received. If socket is set to + * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK can be returned to + * indicate no data. + * + * @param data Destination buffer for data received from the host + * @param size Size of the buffer in bytes + * @return Number of received bytes on success, negative error + * code on failure + */ + nsapi_size_or_error_t recv(void *data, nsapi_size_t size) { + return mbedtls_ssl_read(&_ssl, (uint8_t *) data, size); + } + + /** Set blocking or non-blocking mode of the socket + * + * Initially all sockets are in blocking mode. In non-blocking mode + * blocking operations such as send/recv/accept return + * NSAPI_ERROR_WOULD_BLOCK if they can not continue. + * + * set_blocking(false) is equivalent to set_timeout(-1) + * set_blocking(true) is equivalent to set_timeout(0) + * + * @param blocking true for blocking mode, false for non-blocking mode. + */ + void set_blocking(bool blocking) { + _tcpsocket->set_blocking(blocking); + } + + /** Set timeout on blocking socket operations + * + * Initially all sockets have unbounded timeouts. NSAPI_ERROR_WOULD_BLOCK + * is returned if a blocking operation takes longer than the specified + * timeout. A timeout of 0 removes the timeout from the socket. A negative + * value give the socket an unbounded timeout. + * + * set_timeout(0) is equivalent to set_blocking(false) + * set_timeout(-1) is equivalent to set_blocking(true) + * + * @param timeout Timeout in milliseconds + */ + void set_timeout(int timeout) { + _tcpsocket->set_timeout(timeout); + } + + bool connected() { + return _is_connected; + } + + nsapi_error_t error() { + return _error; + } + + TCPSocket* get_tcp_socket() { + return _tcpsocket; + } + + mbedtls_ssl_context* get_ssl_context() { + return &_ssl; + } + + /** + * Set the debug flag. + * + * If this flag is set, debug information from mbed TLS will be logged to stdout. + */ + void set_debug(bool debug) { + _debug = debug; + } + + /** + * Timed recv for MQTT lib + */ + int read(unsigned char* buffer, int len, int timeout) { + set_timeout(timeout); + return recv(buffer, len); + } + + /** + * Timed send for MQTT lib + */ + int write(unsigned char* buffer, int len, int timeout) { + set_timeout(timeout); + return send(buffer, len); + } + +protected: + +#if DEBUG_LEVEL > 0 + /** + * Debug callback for mbed TLS + * Just prints on the USB serial port + */ + static void my_debug(void *ctx, int level, const char *file, int line, + const char *str) + { + const char *p, *basename; + (void) ctx; + + /* Extract basename from file */ + for(p = basename = file; *p != '\0'; p++) { + if(*p == '/' || *p == '\\') { + basename = p + 1; + } + } + + if (_debug) { + mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); + } + } + + /** + * Certificate verification callback for mbed TLS + * Here we only use it to display information on each cert in the chain + */ + static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) + { + const uint32_t buf_size = 1024; + char *buf = new char[buf_size]; + (void) data; + + if (_debug) mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); + mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); + if (_debug) mbedtls_printf("%s", buf); + + if (*flags == 0) + if (_debug) mbedtls_printf("No verification issue for this certificate\n"); + else + { + mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); + if (_debug) mbedtls_printf("%s\n", buf); + } + + delete[] buf; + return 0; + } +#endif + + /** + * Receive callback for mbed TLS + */ + static int ssl_recv(void *ctx, unsigned char *buf, size_t len) { + int recv = -1; + TCPSocket *socket = static_cast<TCPSocket *>(ctx); + recv = socket->recv(buf, len); + + if (NSAPI_ERROR_WOULD_BLOCK == recv) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + else if (recv < 0) { + return -1; + } + else { + return recv; + } + } + + /** + * Send callback for mbed TLS + */ + static int ssl_send(void *ctx, const unsigned char *buf, size_t len) { + int size = -1; + TCPSocket *socket = static_cast<TCPSocket *>(ctx); + size = socket->send(buf, len); + + if(NSAPI_ERROR_WOULD_BLOCK == size) { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + else if (size < 0){ + return -1; + } + else { + return size; + } + } + +private: + void onError(TCPSocket *s, int error) { + s->close(); + _error = error; + } + + TCPSocket* _tcpsocket; + + const char* DRBG_PERS; + const char* _ssl_ca_pem; + const char* _ssl_owncert_pem; + const char* _ssl_own_priv_key_pem; + const char* _hostname; + uint16_t _port; + + bool _debug; + bool _is_connected; + + nsapi_error_t _error; + + mbedtls_entropy_context _entropy; + mbedtls_ctr_drbg_context _ctr_drbg; + mbedtls_x509_crt _cacert; + mbedtls_x509_crt _owncert; + mbedtls_pk_context _own_priv_key; + mbedtls_ssl_context _ssl; + mbedtls_ssl_config _ssl_conf; +}; + +#endif // _TLS_SOCKET_H_
diff -r 000000000000 -r 9d5f28595388 easy-connect.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect.lib Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/easy-connect/#1d9be07aa4c8a8fcf8fc482116f2a8b1f60a2957
diff -r 000000000000 -r 9d5f28595388 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,739 @@ +/* This example demonstrates connection with AWS IoT through MQTT/HTTPS protocol. + * + * AWS IoT: Thing Shadow MQTT Topics + * http://docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-mqtt.html + * + * AWS IoT: Publish to a topic through HTTPS/POST method: + * http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html + * + * AWS IoT: Thing Shadow RESTful API: + * http://docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-rest-api.html + */ + +#define AWS_IOT_MQTT_TEST 1 +#define AWS_IOT_HTTPS_TEST 0 + +#include "mbed.h" +#include "easy-connect.h" + +/* TLSSocket = Mbed TLS over TCPSocket */ +#include "TLSSocket.h" + +/* Measure memory footprint */ +#include "mbed_stats.h" + +#if AWS_IOT_MQTT_TEST +/* MQTT-specific header files */ +#include "MQTTmbed.h" +#include "MQTTClient.h" +#endif // End of AWS_IOT_MQTT_TEST + + +namespace { + +/* List of trusted root CA certificates + * currently only GlobalSign, the CA for os.mbed.com + * + * To add more than one root, just concatenate them. + */ +const char SSL_CA_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" + "MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n" + "yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n" + "ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\n" + "U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\n" + "ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\n" + "aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL\n" + "MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW\n" + "ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln\n" + "biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp\n" + "U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\n" + "aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1\n" + "nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex\n" + "t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz\n" + "SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG\n" + "BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+\n" + "rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/\n" + "NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E\n" + "BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH\n" + "BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy\n" + "aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv\n" + "MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE\n" + "p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y\n" + "5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK\n" + "WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ\n" + "4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N\n" + "hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq\n" + "-----END CERTIFICATE-----\n"; + +/* User certificate which has been activated and attached with specific thing and policy */ +const char SSL_USER_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" + "MIIDWjCCAkKgAwIBAgIVALN/H7tr8cgpl2zwg0JjEE106XilMA0GCSqGSIb3DQEB\n" + "CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\n" + "IEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0xNzEyMTQwOTE3\n" + "MjdaFw00OTEyMzEyMzU5NTlaMB4xHDAaBgNVBAMME0FXUyBJb1QgQ2VydGlmaWNh\n" + "dGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM/Ebg1vx305GeuQk8\n" + "UeYr+5IGBEoF6QwY9wjjliQMZKoIQk8eLYZxyjq/i0WRoXy+4l2IOZC0621bahHS\n" + "2iPC07Uxj1BXBW+f+V0pBnUnnGK0tT3uGOFVOoPUBoiYU9mB/Anv4wXRdqrUNAMW\n" + "Mq/lAzOvgfyFXnTu0AtvWwISNiAk3ly2E+3PC/Ma9RyMOAjsRUbQo66f2ERmd8yZ\n" + "PgCXlb/x2kCnjnkau6MS0tg83Ro+QvyQGqBRf3fbYIS8Hz6mIKGffguuelEEoMqP\n" + "H0beG0GO/T73uUAscbrOWzoVlNmFVt6Ly53s1tm9j/Spldl4EKmMD3vNetkInYDo\n" + "O55zAgMBAAGjYDBeMB8GA1UdIwQYMBaAFE17U+bgCNXEKf4sP134dtHLiNtcMB0G\n" + "A1UdDgQWBBSP7arfS0NaGmkNFBTg7SakJy0qEDAMBgNVHRMBAf8EAjAAMA4GA1Ud\n" + "DwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAW5RDTsZjhlkThMOrrP2XH1Cr\n" + "9rcoXGqo+jOq5a/yX/LVIM2W/9bIIaOEDScP2haJWceq0C1O6t2JGL0UtNGFyjYS\n" + "0Z3bCv77MNLhWc8GeIRHWAd65dlEspKO8P7UHNppHhh4/oKYpP2Nu/pvguofgIw6\n" + "XbKk9PYz4n/ebdhWi6nTBi6Yc3d9aczMh227HcUz7RFoBEhKhOi7IDWzS9X+sqfD\n" + "fg5NV+A4w6GMTAmLVU8ryodohSTaz34+bElnCdrAnMeSpR8BElTmojSdrA5eY5qZ\n" + "ib7kkPRPyM3QuqTiMPMyxdVDxkoNtRrJ8zw+l443oKvVsUvDZJbHURUt2d4htA==\n" + "-----END CERTIFICATE-----\n"; + +/* User private key paired with above */ +const char SSL_USER_PRIV_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEowIBAAKCAQEAzPxG4Nb8d9ORnrkJPFHmK/uSBgRKBekMGPcI45YkDGSqCEJP\n" + "Hi2Gcco6v4tFkaF8vuJdiDmQtOttW2oR0tojwtO1MY9QVwVvn/ldKQZ1J5xitLU9\n" + "7hjhVTqD1AaImFPZgfwJ7+MF0Xaq1DQDFjKv5QMzr4H8hV507tALb1sCEjYgJN5c\n" + "thPtzwvzGvUcjDgI7EVG0KOun9hEZnfMmT4Al5W/8dpAp455GrujEtLYPN0aPkL8\n" + "kBqgUX9322CEvB8+piChn34LrnpRBKDKjx9G3htBjv0+97lALHG6zls6FZTZhVbe\n" + "i8ud7NbZvY/0qZXZeBCpjA97zXrZCJ2A6DuecwIDAQABAoIBAEbY7rppM6tKoWrl\n" + "cy6487/B3E9eDiOKz5aVUyoty1nJNQdTu7qna29KwRFQ1oOl99KVtFQP6VbOg+Zz\n" + "e6OPp4p/14FAkjjxdQoqiqtSQw2kvGzOs4/mY4MsjUGr3GwhluyZKuoRYgJqbFKZ\n" + "g3OZozeY6rU/TQLfibS8jSc4ojeehQx3cesJmnYA16iFjN8K/D2Tw+aJiKx+0D8k\n" + "nbpy19/2MzBW+UhunMpCtfDNx/HLQAYtzxbxczw7yUiQnmyf+0t0/+xm0m04eic1\n" + "GRHHInZSKzMfGtzyJXliFP5o92dspCm5vsiyXMcPzqcX192IZSixbG8etrJk8jXy\n" + "bTi85VkCgYEA6hOkrSZjbZvsgtjJCIbjMmn9rpBrG0Bv+V1gJ/dH3hZjo2qUnVB0\n" + "8PfBZ+oOoNjEWJlS38zf4pwHSBR6WzvH/o35EHvXNCcdKA82jmv0lbbdH2a4y19n\n" + "lnlyEocsFmPtyuSp+TwIxKI1d+mk9q9D6FgWyLHSddn/qY56txOx7M8CgYEA4C8f\n" + "6bz4a64KBnIZ7yWwwNkZ3Jn8wI62NiZpPpY5PfKtdYCdBHyuCWApE0e8pZy6fTTN\n" + "VVH9RJEq3UHxvEPzNOOhlAoRKT3BakmQ+Yw9Dg+xk6XiiCQuJcEnWG+IUFIjsxEK\n" + "SgSfzrVHtF3udlbP58b3gOSZvxBt8a3qBFPARR0CgYEA08hIAz0rUn1zxIMdiHB6\n" + "WR+anXke3v4zEVwRZreNt3tsVOtWYOrtkyOmQj17VL4rD7pRSBmWKvJeiDG27pqs\n" + "/Tw4r1hMwmvtLlRtWPiFx3s2n3WSFrdQAs4IjojsM6nf+OVggBZ4HGhilga38VVr\n" + "zGj+3EA/Gc/OR/uYPdI89fMCgYAHOz3qSkAxKQIFxzRy9GJJNjeRWB5BD9ls0bxf\n" + "WnUqPGPAAJAQDv2GK+XnS08YgH+7fjKJaAWlapFZZcEoc4Cq2hTiM5juHaHZjdnx\n" + "Usa9Z2AxBQ7TmWcrrJlaTu60uJGSOyB71r5Y6pwPg2AnzRETxuVA8R7MfPku7I85\n" + "6IGxOQKBgHyvFe38EHJndwgTZYK0fWWghRb6XmdH4MxZip2W6yO2Kzav6JuWamV6\n" + "0x80T4RWTpWFXVb288EkSEambrKX8Y0ihn7bFK/cAxD4j7oAGJCgW85mbMAZsj4b\n" + "OAvPvajSMJKyKrgIX/wMfTQlTqAvcsEA2FbrgX67BEBw9HUP2Mm6\n" + "-----END RSA PRIVATE KEY-----\n"; + +#if AWS_IOT_MQTT_TEST + +#define AWS_IOT_MQTT_SERVER_NAME "a1fbcwaqfqeozo.iot.us-east-1.amazonaws.com" +#define AWS_IOT_MQTT_SERVER_PORT 8883 + +#define AWS_IOT_MQTT_THINGNAME "Nuvoton-Mbed-D001" +#define AWS_IOT_MQTT_CLIENTNAME "Nuvoton Client" + +/* User self-test topic */ +const char USER_MQTT_TOPIC[] = "Nuvoton/Mbed/D001"; +const char *USER_MQTT_TOPIC_FILTERS[] = { + "Nuvoton/Mbed/+" +}; +const char USER_MQTT_TOPIC_PUBLISH_MESSAGE[] = "{ \"message\": \"Hello from Nuvoton Mbed device\" }"; + +/* Update thing shadow */ +const char UPDATETHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update"; +const char *UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS[] = { + "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update/accepted", + "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update/rejected" +}; +const char UPDATETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "{ \"state\": { \"reported\": { \"attribute1\": 3, \"attribute2\": \"1\" } } }"; + +/* Get thing shadow */ +const char GETTHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get"; +const char *GETTHINGSHADOW_MQTT_TOPIC_FILTERS[] = { + "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get/accepted", + "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get/rejected" +}; +const char GETTHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = ""; + +/* Delete thing shadow */ +const char DELETETHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete"; +const char *DELETETHINGSHADOW_MQTT_TOPIC_FILTERS[] = { + "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete/accepted", + "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete/rejected" +}; +const char DELETETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = ""; + +/* MQTT user buffer size */ +const int MQTT_USER_BUFFER_SIZE = 600; + +/* Configure MAX_MQTT_PACKET_SIZE to meet your application. + * We may meet unknown MQTT error with MAX_MQTT_PACKET_SIZE too small, but + * MQTT lib doesn't tell enough error message. Try to enlarge it. */ +const int MAX_MQTT_PACKET_SIZE = 1000; + +#endif // End of AWS_IOT_MQTT_TEST + +#if AWS_IOT_HTTPS_TEST + +#define AWS_IOT_HTTPS_SERVER_NAME "a1fbcwaqfqeozo.iot.us-east-1.amazonaws.com" +#define AWS_IOT_HTTPS_SERVER_PORT 8443 + +#define AWS_IOT_HTTPS_THINGNAME "Nuvoton-Mbed-D001" + +/* Publish to user topic through HTTPS/POST + * HTTP POST https://"endpoint"/topics/"yourTopicHierarchy" */ +const char USER_TOPIC_HTTPS_PATH[] = "/topics/Nuvoton/Mbed/D001?qos=1"; +const char USER_TOPIC_HTTPS_REQUEST_METHOD[] = "POST"; +const char USER_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"message\": \"Hello from Nuvoton Mbed device\" }"; + +/* Update thing shadow by publishing to UpdateThingShadow topic through HTTPS/POST + * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/update */ +const char UPDATETHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/update?qos=1"; +const char UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST"; +const char UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"state\": { \"reported\": { \"attribute1\": 3, \"attribute2\": \"1\" } } }"; + +/* Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST + * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/get */ +const char GETTHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/get?qos=1"; +const char GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST"; +const char GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = ""; + +/* Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST + * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/delete */ +const char DELETETHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/delete?qos=1"; +const char DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST"; +const char DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = ""; + +/* Update thing shadow RESTfully through HTTPS/POST + * HTTP POST https://endpoint/things/thingName/shadow */ +const char UPDATETHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow"; +const char UPDATETHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "POST"; +const char UPDATETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"state\": { \"desired\": { \"attribute1\": 1, \"attribute2\": \"2\" }, \"reported\": { \"attribute1\": 2, \"attribute2\": \"1\" } } }"; + +/* Get thing shadow RESTfully through HTTPS/GET + * HTTP GET https://"endpoint"/things/"thingName"/shadow */ +const char GETTHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow"; +const char GETTHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "GET"; +const char GETTHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = ""; + +/* Delete thing shadow RESTfully through HTTPS/DELETE + * HTTP DELETE https://endpoint/things/thingName/shadow */ +const char DELETETHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow"; +const char DELETETHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "DELETE"; +const char DELETETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = ""; + +/* HTTPS user buffer size */ +const int HTTPS_USER_BUFFER_SIZE = 600; + +const char *HTTPS_OK_STR = "200 OK"; + +#endif // End of AWS_IOT_HTTPS_TEST + +} + +#if AWS_IOT_MQTT_TEST + +/** + * /brief AWS_IoT_MQTT_Test implements the logic with AWS IoT User/Thing Shadow topics through MQTT. + */ +class AWS_IoT_MQTT_Test { + +public: + /** + * @brief AWS_IoT_MQTT_Test Constructor + * + * @param[in] domain Domain name of the MQTT server + * @param[in] port Port number of the MQTT server + * @param[in] net_iface Network interface + */ + AWS_IoT_MQTT_Test(const char * domain, const uint16_t port, NetworkInterface *net_iface) : + _domain(domain), _port(port) { + _tlssocket = new TLSSocket(net_iface, SSL_CA_CERT_PEM, SSL_USER_CERT_PEM, SSL_USER_PRIV_KEY_PEM); + /* Blocking mode */ + _tlssocket->set_blocking(true); + /* Print Mbed TLS handshake log */ + _tlssocket->set_debug(true); + + _mqtt_client = new MQTT::Client<TLSSocket, Countdown, MAX_MQTT_PACKET_SIZE>(*_tlssocket); + } + + /** + * @brief AWS_IoT_MQTT_Test Destructor + */ + ~AWS_IoT_MQTT_Test() { + delete _mqtt_client; + _mqtt_client = NULL; + + _tlssocket->close(); + delete _tlssocket; + _tlssocket = NULL; + } + /** + * @brief Start AWS IoT test through MQTT + */ + void start_test() { + + int tls_rc; + int mqtt_rc; + + do { + /* Connect to the server */ + /* Initialize TLS-related stuff */ + printf("Connecting with %s:%d\n", _domain, _port); + tls_rc = _tlssocket->connect(_domain, _port); + if (tls_rc != NSAPI_ERROR_OK) { + printf("Connects with %s:%d failed: %d\n", _domain, _port, tls_rc); + break; + } + printf("Connects with %s:%d OK\n", _domain, _port); + + /* See the link below for AWS IoT support for MQTT: + * http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html */ + + /* MQTT connect */ + /* The message broker does not support persistent sessions (connections made with + * the cleanSession flag set to false. */ + MQTTPacket_connectData conn_data = MQTTPacket_connectData_initializer; + /* AWS IoT message broker implementation is based on MQTT version 3.1.1 + * 3 = 3.1 + * 4 = 3.1.1 */ + conn_data.MQTTVersion = 4; + /* Version number of this structure. Must be 0 */ + conn_data.struct_version = 0; + /* The message broker uses the client ID to identify each client. The client ID is passed + * in from the client to the message broker as part of the MQTT payload. Two clients with + * the same client ID are not allowed to be connected concurrently to the message broker. + * When a client connects to the message broker using a client ID that another client is using, + * a CONNACK message will be sent to both clients and the currently connected client will be + * disconnected. */ + conn_data.clientID.cstring = AWS_IOT_MQTT_CLIENTNAME; + /* The message broker does not support persistent sessions (connections made with + * the cleanSession flag set to false. The AWS IoT message broker assumes all sessions + * are clean sessions and messages are not stored across sessions. If an MQTT client + * attempts to connect to the AWS IoT message broker with the cleanSession set to false, + * the client will be disconnected. */ + conn_data.cleansession = 1; + //conn_data.username.cstring = "USERNAME"; + //conn_data.password.cstring = "PASSWORD"; + + MQTT::connackData connack_data; + + /* _tlssocket must connect to the network endpoint before calling this. */ + printf("MQTT connecting"); + if ((mqtt_rc = _mqtt_client->connect(conn_data, connack_data)) != 0) { + printf("\rMQTT connects failed: %d\n", mqtt_rc); + break; + } + printf("\rMQTT connects OK\n\n"); + + /* Subscribe/publish user topic */ + printf("Subscribing/publishing user topic\n"); + if (! sub_pub_topic(USER_MQTT_TOPIC, USER_MQTT_TOPIC_FILTERS, sizeof (USER_MQTT_TOPIC_FILTERS) / sizeof (USER_MQTT_TOPIC_FILTERS[0]), USER_MQTT_TOPIC_PUBLISH_MESSAGE)) { + break; + } + printf("Subscribes/publishes user topic OK\n\n"); + + /* Subscribe/publish UpdateThingShadow topic */ + printf("Subscribing/publishing UpdateThingShadow topic\n"); + if (! sub_pub_topic(UPDATETHINGSHADOW_MQTT_TOPIC, UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS, sizeof (UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS) / sizeof (UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS[0]), UPDATETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE)) { + break; + } + printf("Subscribes/publishes UpdateThingShadow topic OK\n\n"); + + /* Subscribe/publish GetThingShadow topic */ + printf("Subscribing/publishing GetThingShadow topic\n"); + if (! sub_pub_topic(GETTHINGSHADOW_MQTT_TOPIC, GETTHINGSHADOW_MQTT_TOPIC_FILTERS, sizeof (GETTHINGSHADOW_MQTT_TOPIC_FILTERS) / sizeof (GETTHINGSHADOW_MQTT_TOPIC_FILTERS[0]), GETTHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE)) { + break; + } + printf("Subscribes/publishes GetThingShadow topic OK\n\n"); + + /* Subscribe/publish DeleteThingShadow topic */ + printf("Subscribing/publishing DeleteThingShadow topic\n"); + if (! sub_pub_topic(DELETETHINGSHADOW_MQTT_TOPIC, DELETETHINGSHADOW_MQTT_TOPIC_FILTERS, sizeof (DELETETHINGSHADOW_MQTT_TOPIC_FILTERS) / sizeof (DELETETHINGSHADOW_MQTT_TOPIC_FILTERS[0]), DELETETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE)) { + break; + } + printf("Subscribes/publishes DeleteThingShadow topic OK\n\n"); + + } while (0); + + printf("MQTT disconnecting"); + if ((mqtt_rc = _mqtt_client->disconnect()) != 0) { + printf("\rMQTT disconnects failed %d\n", mqtt_rc); + } + printf("\rMQTT disconnects OK\n"); + + _tlssocket->close(); + } + + +protected: + + /** + * @brief Subscribe/publish specific topic + */ + bool sub_pub_topic(const char *topic, const char **topic_filters, size_t topic_filters_size, const char *publish_message_body) { + + bool ret = false; + int mqtt_rc; + + do { + const char **topic_filter; + const char **topic_filter_end = topic_filters + topic_filters_size; + + for (topic_filter = topic_filters; topic_filter != topic_filter_end; topic_filter ++) { + /* AWS IoT does not support publishing and subscribing with QoS 2. + * The AWS IoT message broker does not send a PUBACK or SUBACK when QoS 2 is requested. */ + printf("MQTT subscribing to %s", *topic_filter); + if ((mqtt_rc = _mqtt_client->subscribe(*topic_filter, MQTT::QOS1, message_arrived)) != 0) { + printf("\rMQTT subscribes to %s failed: %d\n", *topic_filter, mqtt_rc); + continue; + } + printf("\rMQTT subscribes to %s OK\n", *topic_filter); + } + + MQTT::Message message; + + int _bpos; + + _bpos = snprintf(_buffer, sizeof (_buffer) - 1, publish_message_body); + if (_bpos < 0 || ((size_t) _bpos) > (sizeof (_buffer) - 1)) { + printf("snprintf failed: %d\n", _bpos); + break; + } + _buffer[_bpos] = 0; + /* AWS IoT does not support publishing and subscribing with QoS 2. + * The AWS IoT message broker does not send a PUBACK or SUBACK when QoS 2 is requested. */ + message.qos = MQTT::QOS1; + message.retained = false; + message.dup = false; + message.payload = _buffer; + message.payloadlen = strlen(_buffer); + /* Print publish message */ + printf("Message to publish:\n"); + printf("%s\n", _buffer); + printf("MQTT publishing message to %s", topic); + if ((mqtt_rc = _mqtt_client->publish(topic, message)) != 0) { + printf("\rMQTT publishes message to %s failed: %d\n", topic, mqtt_rc); + break; + } + printf("\rMQTT publishes message to %s OK\n", topic); + + /* Receive message with subscribed topic */ + while (! _message_arrive_count) { + _mqtt_client->yield(100); + } + clear_message_arrive_count(); + printf("\n"); + + /* Unsubscribe + * We meet second unsubscribe failed. This is caused by MQTT lib bug. */ + for (topic_filter = topic_filters; topic_filter != topic_filter_end; topic_filter ++) { + printf("MQTT unsubscribing from %s", *topic_filter); + if ((mqtt_rc = _mqtt_client->unsubscribe(*topic_filter)) != 0) { + printf("\rMQTT unsubscribes from %s failed: %d\n", *topic_filter, mqtt_rc); + continue; + } + printf("\rMQTT unsubscribes from %s OK\n", *topic_filter); + } + + ret = true; + + } while (0); + + return ret; + } + +protected: + TLSSocket * _tlssocket; + MQTT::Client<TLSSocket, Countdown, MAX_MQTT_PACKET_SIZE> * _mqtt_client; + + const char *_domain; /**< Domain name of the MQTT server */ + const uint16_t _port; /**< Port number of the MQTT server */ + char _buffer[MQTT_USER_BUFFER_SIZE]; /**< User buffer */ + +private: + static volatile uint16_t _message_arrive_count; + + static void message_arrived(MQTT::MessageData& md) { + MQTT::Message &message = md.message; + printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id); + printf("Payload:\n"); + printf("%.*s\n", message.payloadlen, (char*)message.payload); + ++ _message_arrive_count; + } + + static void clear_message_arrive_count() { + _message_arrive_count = 0; + } +}; + +volatile uint16_t AWS_IoT_MQTT_Test::_message_arrive_count = 0; + +#endif // End of AWS_IOT_MQTT_TEST + + +#if AWS_IOT_HTTPS_TEST + +/** + * /brief AWS_IoT_HTTPS_Test implements the logic with AWS IoT User/Thing Shadow topics (publish-only) + * and Thing Shadow RESTful API through HTTPS. + */ +class AWS_IoT_HTTPS_Test { + +public: + /** + * @brief AWS_IoT_HTTPS_Test Constructor + * + * @param[in] domain Domain name of the HTTPS server + * @param[in] port Port number of the HTTPS server + * @param[in] net_iface Network interface + */ + AWS_IoT_HTTPS_Test(const char * domain, const uint16_t port, NetworkInterface *net_iface) : + _domain(domain), _port(port) { + + _tlssocket = new TLSSocket(net_iface, SSL_CA_CERT_PEM, SSL_USER_CERT_PEM, SSL_USER_PRIV_KEY_PEM); + /* Non-blocking mode */ + _tlssocket->set_blocking(false); + /* Print Mbed TLS handshake log */ + _tlssocket->set_debug(true); + } + /** + * @brief AWS_IoT_HTTPS_Test Destructor + */ + ~AWS_IoT_HTTPS_Test() { + _tlssocket->close(); + delete _tlssocket; + _tlssocket = NULL; + } + /** + * @brief Start AWS IoT test through HTTPS + * + * @param[in] path The path of the file to fetch from the HTTPS server + */ + void start_test() { + + int tls_rc; + + do { + /* Connect to the server */ + /* Initialize TLS-related stuff */ + printf("Connecting with %s:%d\n", _domain, _port); + tls_rc = _tlssocket->connect(_domain, _port); + if (tls_rc != NSAPI_ERROR_OK) { + printf("Connects with %s:%d failed: %d\n", _domain, _port, tls_rc); + break; + } + printf("Connects with %s:%d OK\n\n", _domain, _port); + + /* Publish to user topic through HTTPS/POST */ + printf("Publishing to user topic through HTTPS/POST\n"); + if (! run_req_resp(USER_TOPIC_HTTPS_PATH, USER_TOPIC_HTTPS_REQUEST_METHOD, USER_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Publishes to user topic through HTTPS/POST OK\n\n"); + + /* Update thing shadow by publishing to UpdateThingShadow topic through HTTPS/POST */ + printf("Updating thing shadow by publishing to Update Thing Shadow topic through HTTPS/POST\n"); + if (! run_req_resp(UPDATETHINGSHADOW_TOPIC_HTTPS_PATH, UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Update thing shadow by publishing to Update Thing Shadow topic through HTTPS/POST OK\n\n"); + + /* Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST */ + printf("Getting thing shadow by publishing to GetThingShadow topic through HTTPS/POST\n"); + if (! run_req_resp(GETTHINGSHADOW_TOPIC_HTTPS_PATH, GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST OK\n\n"); + + /* Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST */ + printf("Deleting thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST\n"); + if (! run_req_resp(DELETETHINGSHADOW_TOPIC_HTTPS_PATH, DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST OK\n\n"); + + /* Update thing shadow RESTfully through HTTPS/POST */ + printf("Updating thing shadow RESTfully through HTTPS/POST\n"); + if (! run_req_resp(UPDATETHINGSHADOW_THING_HTTPS_PATH, UPDATETHINGSHADOW_THING_HTTPS_REQUEST_METHOD, UPDATETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Update thing shadow RESTfully through HTTPS/POST OK\n\n"); + + /* Get thing shadow RESTfully through HTTPS/GET */ + printf("Getting thing shadow RESTfully through HTTPS/GET\n"); + if (! run_req_resp(GETTHINGSHADOW_THING_HTTPS_PATH, GETTHINGSHADOW_THING_HTTPS_REQUEST_METHOD, GETTHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Get thing shadow RESTfully through HTTPS/GET OK\n\n"); + + /* Delete thing shadow RESTfully through HTTPS/DELETE */ + printf("Deleting thing shadow RESTfully through HTTPS/DELETE\n"); + if (! run_req_resp(DELETETHINGSHADOW_THING_HTTPS_PATH, DELETETHINGSHADOW_THING_HTTPS_REQUEST_METHOD, DELETETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) { + break; + } + printf("Delete thing shadow RESTfully through HTTPS/DELETE OK\n\n"); + + } while (0); + + /* Close socket */ + _tlssocket->close(); + } + +protected: + + /** + * @brief Run request/response through HTTPS + */ + bool run_req_resp(const char *https_path, const char *https_request_method, const char *https_request_message_body) { + + bool ret = false; + + do { + int tls_rc; + bool _got200 = false; + + int _bpos; + + /* Fill the request buffer */ + _bpos = snprintf(_buffer, sizeof(_buffer) - 1, + "%s %s HTTP/1.1\r\n" "Host: %s\r\n" "Content-Length: %d\r\n" "\r\n" "%s", + https_request_method, https_path, AWS_IOT_HTTPS_SERVER_NAME, strlen(https_request_message_body), https_request_message_body); + if (_bpos < 0 || ((size_t) _bpos) > (sizeof (_buffer) - 1)) { + printf("snprintf failed: %d\n", _bpos); + break; + } + _buffer[_bpos] = 0; + /* Print request message */ + printf("HTTPS: Request message:\n"); + printf("%s\n", _buffer); + + int offset = 0; + do { + tls_rc = _tlssocket->send((const unsigned char *) _buffer + offset, _bpos - offset); + if (tls_rc > 0) { + offset += tls_rc; + } + } while (offset < _bpos && + (tls_rc > 0 || tls_rc == MBEDTLS_ERR_SSL_WANT_READ || tls_rc == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (tls_rc < 0) { + print_mbedtls_error("_tlssocket->send", tls_rc); + break; + } + + /* Read data out of the socket */ + offset = 0; + size_t content_length = 0; + size_t offset_end = 0; + char *line_beg = _buffer; + char *line_end = NULL; + do { + tls_rc = _tlssocket->recv((unsigned char *) _buffer + offset, sizeof(_buffer) - offset - 1); + if (tls_rc > 0) { + offset += tls_rc; + } + + /* Make it null-terminated */ + _buffer[offset] = 0; + + /* Scan response message + * + * 1. A status line which includes the status code and reason message (e.g., HTTP/1.1 200 OK) + * 2. Response header fields (e.g., Content-Type: text/html) + * 3. An empty line (\r\n) + * 4. An optional message body + */ + if (! offset_end) { + line_end = strstr(line_beg, "\r\n"); + if (line_end) { + /* Scan status line */ + if (! _got200) { + _got200 = strstr(line_beg, HTTPS_OK_STR) != NULL; + } + + /* Scan response header fields for Content-Length + * + * NOTE: Assume chunked transfer (Transfer-Encoding: chunked) is not used + * NOTE: Assume response field name are in lower case + */ + if (content_length == 0) { + sscanf(line_beg, "content-length:%d", &content_length); + } + + /* An empty line indicates end of response header fields */ + if (line_beg == line_end) { + offset_end = line_end - _buffer + 2 + content_length; + } + + /* Go to next line */ + line_beg = line_end + 2; + line_end = NULL; + } + } + } while ((offset_end == 0 || offset < offset_end) && + (tls_rc > 0 || tls_rc == MBEDTLS_ERR_SSL_WANT_READ || tls_rc == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (tls_rc < 0 && + tls_rc != MBEDTLS_ERR_SSL_WANT_READ && + tls_rc != MBEDTLS_ERR_SSL_WANT_WRITE) { + print_mbedtls_error("_tlssocket->read", tls_rc); + break; + } + _bpos = offset; + + _buffer[_bpos] = 0; + + /* Print status messages */ + printf("HTTPS: Received %d chars from server\n", _bpos); + printf("HTTPS: Received 200 OK status ... %s\n", _got200 ? "[OK]" : "[FAIL]"); + printf("HTTPS: Received message:\n"); + printf("%s\n", _buffer); + + ret = true; + + } while (0); + + return ret; + } + +protected: + TLSSocket * _tlssocket; + + const char *_domain; /**< Domain name of the HTTPS server */ + const uint16_t _port; /**< Port number of the HTTPS server */ + char _buffer[HTTPS_USER_BUFFER_SIZE]; /**< User buffer */ +}; + +#endif // End of AWS_IOT_HTTPS_TEST + +int main() { + + /* The default 9600 bps is too slow to print full TLS debug info and could + * cause the other party to time out. */ + + printf("\nStarting AWS IoT test\n"); + +#if defined(MBED_MAJOR_VERSION) + printf("Using Mbed OS %d.%d.%d\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); +#else + printf("Using Mbed OS from master.\n"); +#endif + + /* Use the easy-connect lib to support multiple network bearers. */ + /* See https://github.com/ARMmbed/easy-connect README.md for info. */ + + NetworkInterface* network = easy_connect(false); + if (NULL == network) { + printf("Connecting to the network failed. See serial output.\n"); + return 1; + } + +#if AWS_IOT_MQTT_TEST + AWS_IoT_MQTT_Test *mqtt_test = new AWS_IoT_MQTT_Test(AWS_IOT_MQTT_SERVER_NAME, AWS_IOT_MQTT_SERVER_PORT, network); + mqtt_test->start_test(); + delete mqtt_test; +#endif // End of AWS_IOT_MQTT_TEST + +#if AWS_IOT_HTTPS_TEST + AWS_IoT_HTTPS_Test *https_test = new AWS_IoT_HTTPS_Test(AWS_IOT_HTTPS_SERVER_NAME, AWS_IOT_HTTPS_SERVER_PORT, network); + https_test->start_test(); + delete https_test; +#endif // End of AWS_IOT_HTTPS_TEST + + /* Heap usage */ + mbed_stats_heap_t heap_stats; + mbed_stats_heap_get(&heap_stats); + printf("\nCurrent heap size: %lu\n", heap_stats.current_size); + printf("Max heap size: %lu\n\n", heap_stats.max_size); +}
diff -r 000000000000 -r 9d5f28595388 mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#91e6db1ea251ffcc973001ed90477f42fdca5751
diff -r 000000000000 -r 9d5f28595388 mbed_app.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,48 @@ +{ + "macros": [ + "MBED_CONF_APP_MAIN_STACK_SIZE=4096", + "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_user_config.h\"", + "MBED_HEAP_STATS_ENABLED=1", + "MBED_MEM_TRACING_ENABLED=1" + ], + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, WIFI_IDW01M1, WIFI_RTW, MESH_LOWPAN_ND, MESH_THREAD", + "value": "ETHERNET" + }, + "esp8266-tx": { + "help": "Pin used as TX (connects to ESP8266 RX)", + "value": "D1" + }, + "esp8266-rx": { + "help": "Pin used as RX (connects to ESP8266 TX)", + "value": "D0" + }, + "esp8266-debug": { + "value": false + }, + "wifi-ssid": { + "value": "\"SSID\"" + }, + "wifi-password": { + "value": "\"PASSWORD\"" + } + }, + "target_overrides": { + "*": { + "platform.stdio-baud-rate": 9600, + "platform.stdio-convert-newlines": true + }, + "UBLOX_EVK_ODIN_W2": { + "target.device_has_remove": ["EMAC"] + }, + "NUMAKER_PFM_NUC472": { + "target.macros_remove": ["MBEDTLS_CONFIG_HW_SUPPORT"], + "drivers.uart-serial-rxbuf-size": 1024 + }, + "NUMAKER_PFM_M487": { + "target.macros_remove": ["MBEDTLS_CONFIG_HW_SUPPORT"], + "drivers.uart-serial-rxbuf-size": 1024 + } + } +}
diff -r 000000000000 -r 9d5f28595388 mbedtls_user_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedtls_user_config.h Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2006-2016, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && \ + !defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_TEST_NULL_ENTROPY) +#error "This hardware does not have an entropy source." +#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !MBEDTLS_ENTROPY_NV_SEED && + * !MBEDTLS_TEST_NULL_ENTROPY */ + +#if !defined(MBEDTLS_SHA1_C) +#define MBEDTLS_SHA1_C +#endif /* !MBEDTLS_SHA1_C */ + +/* + * This value is sufficient for handling 2048 bit RSA keys. + * + * Set this value higher to enable handling larger keys, but be aware that this + * will increase the stack usage. + */ +#define MBEDTLS_MPI_MAX_SIZE 256 + +#define MBEDTLS_MPI_WINDOW_SIZE 1 + +#if defined(TARGET_STM32F439xI) && defined(MBEDTLS_CONFIG_HW_SUPPORT) +#undef MBEDTLS_AES_ALT +#endif /* TARGET_STM32F439xI && MBEDTLS_CONFIG_HW_SUPPORT */ + +/* Internal test only. Don't uncomment it out */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 4096
diff -r 000000000000 -r 9d5f28595388 mbedtls_utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedtls_utils.h Wed Mar 14 03:03:16 2018 +0000 @@ -0,0 +1,36 @@ +/* + * PackageLicenseDeclared: Apache-2.0 + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MBEDTLS_UTILS_H_ +#define _MBEDTLS_UTILS_H_ + +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +/** + * Helper for pretty-printing mbed TLS error codes + */ +__STATIC_INLINE void print_mbedtls_error(const char *name, int err) { + char buf[128]; + mbedtls_strerror(err, buf, sizeof (buf)); + mbedtls_printf("%s() failed: -0x%04x (%d): %s\r\n", name, -err, err, buf); +} + +#endif // _MBEDTLS_UTILS_H_