diff --git a/examples/esp8266/simplesample_http/iot_configs.h b/examples/esp8266/simplesample_http/iot_configs.h index 798e18b..0b6168f 100644 --- a/examples/esp8266/simplesample_http/iot_configs.h +++ b/examples/esp8266/simplesample_http/iot_configs.h @@ -17,4 +17,10 @@ */ #define IOT_CONFIG_CONNECTION_STRING "HostName=.azure-devices.net;DeviceId=;SharedAccessKey=" +/** + * Choose the transport protocol + */ +// #define IOT_CONFIG_MQTT // uncomment this line for MQTT +#define IOT_CONFIG_HTTP // uncomment this line for HTTP + #endif /* IOT_CONFIGS_H */ diff --git a/examples/esp8266/simplesample_http/simplesample_http.h b/examples/esp8266/simplesample_http/sample.h similarity index 64% rename from examples/esp8266/simplesample_http/simplesample_http.h rename to examples/esp8266/simplesample_http/sample.h index baf6975..ad6e441 100644 --- a/examples/esp8266/simplesample_http/simplesample_http.h +++ b/examples/esp8266/simplesample_http/sample.h @@ -1,17 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#ifndef SIMPLESAMPLEHTTP_H -#define SIMPLESAMPLEHTTP_H +#ifndef SAMPLE_H +#define SAMPLE_H #ifdef __cplusplus extern "C" { #endif - void simplesample_http_run(void); + void sample_run(void); #ifdef __cplusplus } #endif -#endif /* SIMPLESAMPLEHTTP_H */ +#endif /* SAMPLE_H */ diff --git a/examples/esp8266/simplesample_http/simplesample_http.c b/examples/esp8266/simplesample_http/simplesample_http.c index a199ba6..f5c011a 100644 --- a/examples/esp8266/simplesample_http/simplesample_http.c +++ b/examples/esp8266/simplesample_http/simplesample_http.c @@ -6,15 +6,10 @@ #include #include #include "iot_configs.h" - -/* This sample uses the _LL APIs of iothub_client for example purposes. -That does not mean that HTTP only works with the _LL APIs. -Simply changing the using the convenience layer (functions not having _LL) -and removing calls to _DoWork will yield the same results. */ +#include "sample.h" #include "AzureIoTHub.h" - /*String containing Hostname, Device Id & Device Key in the format: */ /* "HostName=;DeviceId=;SharedAccessKey=" */ static const char* connectionString = IOT_CONFIG_CONNECTION_STRING; @@ -247,3 +242,9 @@ void simplesample_http_run(void) platform_deinit(); } } + + +void sample_run(void) +{ + simplesample_http_run(); +} diff --git a/examples/esp8266/simplesample_http/simplesample_http.ino b/examples/esp8266/simplesample_http/simplesample_http.ino index 661568b..3958c84 100644 --- a/examples/esp8266/simplesample_http/simplesample_http.ino +++ b/examples/esp8266/simplesample_http/simplesample_http.ino @@ -1,86 +1,43 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Please use an Arduino IDE 1.6.8 or greater -// Use Arduino IDE 1.6.8 or later. - -#include -#include -#include -#include -#include - -// for ESP8266 -#include -#include -#include +// You must set the device id, device key, IoT Hub name and IotHub suffix in +// iot_configs.h +#include "iot_configs.h" #include -#include -#include +#if defined(IOT_CONFIG_MQTT) + #include +#elif defined(IOT_CONFIG_HTTP) + #include +#endif -#include "simplesample_http.h" -#include "iot_configs.h" +#include "sample.h" +#include "esp8266/sample_init.h" static char ssid[] = IOT_CONFIG_WIFI_SSID; static char pass[] = IOT_CONFIG_WIFI_PASSWORD; void setup() { - initSerial(); - initWifi(); - initTime(); + sample_init(ssid, pass); } +// Azure IoT samples contain their own loops, so only run them once +static bool done = false; void loop() { - simplesample_http_run(); -} - -void initSerial() { - // Start serial and initialize stdout - Serial.begin(115200); - Serial.setDebugOutput(true); -} - -void initWifi() { - - // check for the presence of the shield : - if (WiFi.status() == WL_NO_SHIELD) { - Serial.println("WiFi shield not present"); - // don't continue: - while (true); + if (!done) + { + // Run the sample + // You must set the device id, device key, IoT Hub name and IotHub suffix in + // iot_configs.h + sample_run(); + done = true; } - - // attempt to connect to Wifi network: - Serial.print("Attempting to connect to SSID: "); - Serial.println(ssid); - - // Connect to WPA/WPA2 network. Change this line if using open or WEP network: - WiFi.begin(ssid, pass); - - Serial.print("Waiting for Wifi connection."); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(500); + else + { + delay(500); } - - Serial.println("Connected to wifi"); } -void initTime() { - time_t epochTime; - - configTime(0, 0, "pool.ntp.org", "time.nist.gov"); - - while (true) { - epochTime = time(NULL); - - if (epochTime == 0) { - Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry."); - delay(2000); - } else { - Serial.print("Fetched NTP epoch time is: "); - Serial.println(epochTime); - break; - } - } -} diff --git a/examples/samd/simplesample_http/sample.h b/examples/samd/simplesample_http/sample.h new file mode 100644 index 0000000..ad6e441 --- /dev/null +++ b/examples/samd/simplesample_http/sample.h @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifndef SAMPLE_H +#define SAMPLE_H + +#ifdef __cplusplus +extern "C" { +#endif + + void sample_run(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SAMPLE_H */ diff --git a/examples/samd/simplesample_http/simplesample_http.c b/examples/samd/simplesample_http/simplesample_http.c index a199ba6..5f25db3 100644 --- a/examples/samd/simplesample_http/simplesample_http.c +++ b/examples/samd/simplesample_http/simplesample_http.c @@ -247,3 +247,9 @@ void simplesample_http_run(void) platform_deinit(); } } + +void sample_run(void) +{ + simplesample_http_run(); +} + diff --git a/examples/samd/simplesample_http/simplesample_http.ino b/examples/samd/simplesample_http/simplesample_http.ino index 7313c31..fb90b25 100644 --- a/examples/samd/simplesample_http/simplesample_http.ino +++ b/examples/samd/simplesample_http/simplesample_http.ino @@ -1,123 +1,43 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -// Please Use Arduino IDE 1.6.8 or later. +// Please use an Arduino IDE 1.6.8 or greater +// You must set the device id, device key, IoT Hub name and IotHub suffix in +// iot_configs.h #include "iot_configs.h" -#include -#include -#include -#include -#include -#include -#include - - -#include "simplesample_http.h" -#include "NTPClient.h" - #include -#include - -#ifdef ARDUINO_SAMD_FEATHER_M0 - -// Optional LIPO battery monitoring -#define VBAT_ENABLED 1 -#define VBAT_PIN A7 - -#define WINC_CS 8 -#define WINC_IRQ 7 -#define WINC_RST 4 -#define WINC_EN 2 - +#if defined(IOT_CONFIG_MQTT) + #include +#elif defined(IOT_CONFIG_HTTP) + #include #endif +#include "sample.h" +#include "samd/sample_init.h" static char ssid[] = IOT_CONFIG_WIFI_SSID; static char pass[] = IOT_CONFIG_WIFI_PASSWORD; -int status = WL_IDLE_STATUS; -WiFiSSLClient sslClient; - void setup() { - // The Feather M0 loses it's COMn connection with every reset. - // This 10 s delay allows you to reselect the COM port and open the serial monitor window. - delay(10000); - - initSerial(); - - #ifdef ARDUINO_SAMD_FEATHER_M0 - //Configure pins for Adafruit ATWINC1500 Feather - Serial.println(F("WINC1500 on FeatherM0 detected.")); - Serial.println(F("Setting pins for WiFi101 library (WINC1500 on FeatherM0)")); - WiFi.setPins(WINC_CS, WINC_IRQ, WINC_RST, WINC_EN); - // for the Adafruit WINC1500 we need to enable the chip - pinMode(WINC_EN, OUTPUT); - digitalWrite(WINC_EN, HIGH); - Serial.println(F("Enabled WINC1500 interface for FeatherM0")); - #endif - initWifi(); - - initTime(); + sample_init(ssid, pass); } +// Azure IoT samples contain their own loops, so only run them once +static bool done = false; void loop() { - simplesample_http_run(); -} - -void initSerial() { - // Start serial and initialize stdout - Serial.begin(115200); - //Serial.setDebugOutput(true); -} - -void initWifi() { - // Attempt to connect to Wifi network: - Serial.print("\r\n\r\nAttempting to connect to SSID: "); - Serial.println(ssid); - - // Connect to WPA/WPA2 network. Change this line if using open or WEP network: - status = WiFi.begin(ssid, pass); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); + if (!done) + { + // Run the sample + // You must set the device id, device key, IoT Hub name and IotHub suffix in + // iot_configs.h + sample_run(); + done = true; } - - Serial.println("\r\nConnected to wifi"); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -void initTime() { - WiFiUDP _udp; - - time_t epochTime = (time_t)-1; - - NTPClient ntpClient; - ntpClient.begin(); - - while (true) { - epochTime = ntpClient.getEpochTime("0.pool.ntp.org"); - - if (epochTime == (time_t)-1) { - Serial.println("Fetching NTP epoch time failed! Waiting 5 seconds to retry."); - delay(5000); - } else { - Serial.print("Fetched NTP epoch time is: "); - Serial.println(epochTime); - break; - } + else + { + delay(500); } - - ntpClient.end(); - - struct timeval tv; - tv.tv_sec = epochTime; - tv.tv_usec = 0; - - settimeofday(&tv, NULL); } - - diff --git a/library.properties b/library.properties index 9be6be9..b441f3e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AzureIoTUtility -version=1.0.41 +version=1.0.42 author=Microsoft maintainer=Microsoft sentence=Azure C shared utility library for Arduino. For the Arduino MKR1000 or Zero and WiFi Shield 101, Adafruit Huzzah and Feather M0, or SparkFun Thing. diff --git a/src/AzureIoTUtility.h b/src/AzureIoTUtility.h index d9ebc16..a819e62 100644 --- a/src/AzureIoTUtility.h +++ b/src/AzureIoTUtility.h @@ -7,6 +7,6 @@ #include "azure_c_shared_utility/lock.h" #include "azure_c_shared_utility/threadapi.h" -#define AzureIoTUtilityVersion "1.0.41" +#define AzureIoTUtilityVersion "1.0.42" #endif //AZUREIOTUTILITY_H diff --git a/src/adapters/tlsio_arduino.c b/src/adapters/tlsio_arduino.c index 9fd7efe..1559265 100644 --- a/src/adapters/tlsio_arduino.c +++ b/src/adapters/tlsio_arduino.c @@ -16,6 +16,7 @@ #include "azure_c_shared_utility/platform.h" #include "azure_c_shared_utility/threadapi.h" #include "azure_c_shared_utility/optionhandler.h" +#include "azure_c_shared_utility/tlsio_options.h" /* Codes_SRS_TLSIO_ARDUINO_21_001: [ The tlsio_arduino shall implement and export all the Concrete functions in the VTable IO_INTERFACE_DESCRIPTION defined in the `xio.h`. ]*/ /* Codes_SRS_TLSIO_ARDUINO_21_002: [ The tlsio_arduino shall report the open operation status using the IO_OPEN_RESULT enumerator defined in the `xio.h`.]*/ @@ -78,6 +79,7 @@ typedef struct ArduinoTLS_tag uint16_t port; TLSIO_ARDUINO_STATE state; int countTry; + TLSIO_OPTIONS options; } ArduinoTLS; /* Codes_SRS_TLSIO_ARDUINO_21_008: [ The tlsio_arduino_get_interface_description shall return the VTable IO_INTERFACE_DESCRIPTION. ]*/ @@ -128,6 +130,9 @@ CONCRETE_IO_HANDLE tlsio_arduino_create(void* io_create_parameters) /* Codes_SRS_TLSIO_ARDUINO_21_005: [ The tlsio_arduino shall received the connection information using the TLSIO_CONFIG structure defined in `tlsio.h`. ]*/ /* Codes_SRS_TLSIO_ARDUINO_21_017: [ The tlsio_arduino_create shall receive the connection configuration (TLSIO_CONFIG). ]*/ TLSIO_CONFIG* tlsio_config = (TLSIO_CONFIG*)io_create_parameters; + + // Arduino tlsio does not support any options + tlsio_options_initialize(&tlsio_instance->options, TLSIO_OPTION_BIT_NONE); /* Codes_SRS_TLSIO_ARDUINO_21_015: [ The tlsio_arduino_create shall set 10 seconds for the sslClient timeout. ]*/ sslClient_setTimeout(10000); @@ -184,6 +189,7 @@ void tlsio_arduino_destroy(CONCRETE_IO_HANDLE tlsio_handle) LogError("TLS destroyed with a SSL connection still active."); } + tlsio_options_release_resources(&tlsio_instance->options); /* Codes_SRS_TLSIO_ARDUINO_21_022: [ The tlsio_arduino_destroy shall free the memory allocated for tlsio_instance. ]*/ free(tlsio_instance); } @@ -498,20 +504,48 @@ void tlsio_arduino_dowork(CONCRETE_IO_HANDLE tlsio_handle) int tlsio_arduino_setoption(CONCRETE_IO_HANDLE tlsio_handle, const char* optionName, const void* value) { - /* Codes_SRS_TLSIO_ARDUINO_21_077: [ The tlsio_arduino_setoption shall not do anything, and return 0. ]*/ - (void)tlsio_handle, (void)optionName, (void)value; - - /* Not implementing any options */ - return 0; + ArduinoTLS* tls_io_instance = (ArduinoTLS*)tlsio_handle; + /* Codes_SRS_TLSIO_30_120: [ If the tlsio_handle parameter is NULL, tlsio_openssl_compact_setoption shall do nothing except log an error and return FAILURE. ]*/ + int result; + if (tls_io_instance == NULL) + { + LogError("NULL tlsio"); + result = __FAILURE__; + } + else + { + /* Codes_SRS_TLSIO_30_121: [ If the optionName parameter is NULL, tlsio_setoption shall do nothing except log an error and return FAILURE. ]*/ + /* Codes_SRS_TLSIO_30_122: [ If the value parameter is NULL, tlsio_setoption shall do nothing except log an error and return FAILURE. ]*/ + /* Codes_SRS_TLSIO_ARDUINO_21_077: [ The tlsio_arduino_setoption shall not do anything, and return __FAILURE__ . ]*/ + TLSIO_OPTIONS_RESULT options_result = tlsio_options_set(&tls_io_instance->options, optionName, value); + if (options_result != TLSIO_OPTIONS_RESULT_SUCCESS) + { + LogError("Failed tlsio_options_set"); + result = __FAILURE__; + } + else + { + result = 0; + } + } + return result; } OPTIONHANDLER_HANDLE tlsio_arduino_retrieveoptions(CONCRETE_IO_HANDLE tlsio_handle) { - /* Codes_SRS_TLSIO_ARDUINO_21_078: [ The tlsio_arduino_retrieveoptions shall not do anything, and return NULL. ]*/ - (void)(tlsio_handle); - - /* Not implementing any options */ - return NULL; + ArduinoTLS* tls_io_instance = (ArduinoTLS*)tlsio_handle; + /* Codes_SRS_TLSIO_ARDUINO_21_078: [ The tlsio_arduino_retrieveoptions shall return an empty options handler. ]*/ + OPTIONHANDLER_HANDLE result; + if (tls_io_instance == NULL) + { + LogError("NULL tlsio"); + result = NULL; + } + else + { + result = tlsio_options_retrieve_options(&tls_io_instance->options, tlsio_arduino_setoption); + } + return result; } diff --git a/src/azure_c_shared_utility/base32.c b/src/azure_c_shared_utility/base32.c index 355451f..bedb5c1 100644 --- a/src/azure_c_shared_utility/base32.c +++ b/src/azure_c_shared_utility/base32.c @@ -180,7 +180,7 @@ static BUFFER_HANDLE base32_decode_impl(const char* source) if (src_length % BASE32_INPUT_SIZE != 0) { /* Codes_SRS_BASE32_07_021: [ If the source length is not evenly divisible by 8, base32_decode_impl shall return NULL. ] */ - LogError("Failure invalid input length %zu", src_length); + LogError("Failure invalid input length %u", src_length); result = NULL; } else @@ -406,3 +406,4 @@ STRING_HANDLE Base32_Encode(BUFFER_HANDLE source) /* Codes_SRS_BASE32_07_002: [ If successful Base32_Encode shall return the base32 value of source. ] */ return result; } + diff --git a/src/azure_c_shared_utility/base64.c b/src/azure_c_shared_utility/base64.c index ccb1cbe..70270c3 100644 --- a/src/azure_c_shared_utility/base64.c +++ b/src/azure_c_shared_utility/base64.c @@ -366,3 +366,4 @@ STRING_HANDLE Base64_Encoder(BUFFER_HANDLE input) } return result; } + diff --git a/src/azure_c_shared_utility/buffer.c b/src/azure_c_shared_utility/buffer.c index e6a295a..74d1ba0 100644 --- a/src/azure_c_shared_utility/buffer.c +++ b/src/azure_c_shared_utility/buffer.c @@ -632,3 +632,4 @@ BUFFER_HANDLE BUFFER_clone(BUFFER_HANDLE handle) } return result; } + diff --git a/src/azure_c_shared_utility/connection_string_parser.c b/src/azure_c_shared_utility/connection_string_parser.c index 46c422d..7fd738d 100644 --- a/src/azure_c_shared_utility/connection_string_parser.c +++ b/src/azure_c_shared_utility/connection_string_parser.c @@ -232,3 +232,4 @@ int connectionstringparser_splitHostName(STRING_HANDLE hostNameString, STRING_HA return result; } + diff --git a/src/azure_c_shared_utility/consolelogger.c b/src/azure_c_shared_utility/consolelogger.c index 5958c81..075208e 100644 --- a/src/azure_c_shared_utility/consolelogger.c +++ b/src/azure_c_shared_utility/consolelogger.c @@ -228,3 +228,4 @@ void consolelogger_log(LOG_CATEGORY log_category, const char* file, const char* } } + diff --git a/src/azure_c_shared_utility/constbuffer.c b/src/azure_c_shared_utility/constbuffer.c index b3fedec..74e57eb 100644 --- a/src/azure_c_shared_utility/constbuffer.c +++ b/src/azure_c_shared_utility/constbuffer.c @@ -149,3 +149,4 @@ void CONSTBUFFER_Destroy(CONSTBUFFER_HANDLE constbufferHandle) } } } + diff --git a/src/azure_c_shared_utility/constmap.c b/src/azure_c_shared_utility/constmap.c index a6965bd..e5dda24 100644 --- a/src/azure_c_shared_utility/constmap.c +++ b/src/azure_c_shared_utility/constmap.c @@ -224,4 +224,5 @@ CONSTMAP_RESULT ConstMap_GetInternals(CONSTMAP_HANDLE handle, const char*const** result = ConstMap_ErrorConvert(mapResult); } return result; -} \ No newline at end of file +} + diff --git a/src/azure_c_shared_utility/crt_abstractions.c b/src/azure_c_shared_utility/crt_abstractions.c index fe4f23e..57c8f3a 100644 --- a/src/azure_c_shared_utility/crt_abstractions.c +++ b/src/azure_c_shared_utility/crt_abstractions.c @@ -528,7 +528,7 @@ static FLOAT_STRING_TYPE splitFloatString(const char* nptr, char** endptr, int * if (((**endptr) == 'e') || ((**endptr) == 'E')) { startptr = (*endptr) + 1; - (*exponential) = strtol(startptr, endptr, 10); + (*exponential) = (int)strtol(startptr, endptr, 10); if (((*exponential) < (DBL_MAX_10_EXP * (-1))) || ((*exponential) > DBL_MAX_10_EXP)) { result = FST_OVERFLOW; @@ -820,3 +820,4 @@ int size_tToString(char* destination, size_t destinationSize, size_t value) } return result; } + diff --git a/src/azure_c_shared_utility/doublylinkedlist.c b/src/azure_c_shared_utility/doublylinkedlist.c index a101c1e..ab496b6 100644 --- a/src/azure_c_shared_utility/doublylinkedlist.c +++ b/src/azure_c_shared_utility/doublylinkedlist.c @@ -105,3 +105,4 @@ void DList_InsertHeadList(PDLIST_ENTRY listHead, PDLIST_ENTRY entry) listHead->Flink->Blink = entry; listHead->Flink = entry; } + diff --git a/src/azure_c_shared_utility/gb_rand.c b/src/azure_c_shared_utility/gb_rand.c index 7df70fc..17decf9 100644 --- a/src/azure_c_shared_utility/gb_rand.c +++ b/src/azure_c_shared_utility/gb_rand.c @@ -14,3 +14,4 @@ int gb_rand(void) { return rand(); } + diff --git a/src/azure_c_shared_utility/gb_stdio.c b/src/azure_c_shared_utility/gb_stdio.c index 836fad8..f328435 100644 --- a/src/azure_c_shared_utility/gb_stdio.c +++ b/src/azure_c_shared_utility/gb_stdio.c @@ -50,3 +50,4 @@ int fprintf(FILE * stream, const char * format, ...) } #endif + diff --git a/src/azure_c_shared_utility/gb_time.c b/src/azure_c_shared_utility/gb_time.c index be832b8..b383f61 100644 --- a/src/azure_c_shared_utility/gb_time.c +++ b/src/azure_c_shared_utility/gb_time.c @@ -36,3 +36,4 @@ size_t gb_strftime(char * s, size_t maxsize, const char * format, const struct t } #endif + diff --git a/src/azure_c_shared_utility/gballoc.c b/src/azure_c_shared_utility/gballoc.c index a265a34..a32337b 100644 --- a/src/azure_c_shared_utility/gballoc.c +++ b/src/azure_c_shared_utility/gballoc.c @@ -439,3 +439,4 @@ void gballoc_resetMetrics() (void)Unlock(gballocThreadSafeLock); } } + diff --git a/src/azure_c_shared_utility/hmac.c b/src/azure_c_shared_utility/hmac.c index 53f2411..ce16186 100644 --- a/src/azure_c_shared_utility/hmac.c +++ b/src/azure_c_shared_utility/hmac.c @@ -231,3 +231,4 @@ int hmacResult(HMACContext *ctx, uint8_t *digest) } + diff --git a/src/azure_c_shared_utility/hmacsha256.c b/src/azure_c_shared_utility/hmacsha256.c index a7018ab..f72404c 100644 --- a/src/azure_c_shared_utility/hmacsha256.c +++ b/src/azure_c_shared_utility/hmacsha256.c @@ -33,3 +33,4 @@ HMACSHA256_RESULT HMACSHA256_ComputeHash(const unsigned char* key, size_t keyLen return result; } + diff --git a/src/azure_c_shared_utility/http_proxy_io.c b/src/azure_c_shared_utility/http_proxy_io.c index 410695b..8197850 100644 --- a/src/azure_c_shared_utility/http_proxy_io.c +++ b/src/azure_c_shared_utility/http_proxy_io.c @@ -507,7 +507,7 @@ static int ParseStringToDecimal(const char *src, int* dst) int result; char* next; - (*dst) = strtol(src, &next, 0); + (*dst) = (int)strtol(src, &next, 0); if ((src == next) || ((((*dst) == INT_MAX) || ((*dst) == INT_MIN)) && (errno != 0))) { result = __LINE__; @@ -957,3 +957,4 @@ const IO_INTERFACE_DESCRIPTION* http_proxy_io_get_interface_description(void) /* Codes_SRS_HTTP_PROXY_IO_01_049: [ `http_proxy_io_get_interface_description` shall return a pointer to an `IO_INTERFACE_DESCRIPTION` structure that contains pointers to the functions: `http_proxy_io_retrieve_options`, `http_proxy_io_retrieve_create`, `http_proxy_io_destroy`, `http_proxy_io_open`, `http_proxy_io_close`, `http_proxy_io_send` and `http_proxy_io_dowork`. ]*/ return &http_proxy_io_interface_description; } + diff --git a/src/azure_c_shared_utility/httpapiex.c b/src/azure_c_shared_utility/httpapiex.c index 1233135..62dff0f 100644 --- a/src/azure_c_shared_utility/httpapiex.c +++ b/src/azure_c_shared_utility/httpapiex.c @@ -655,3 +655,4 @@ HTTPAPIEX_RESULT HTTPAPIEX_SetOption(HTTPAPIEX_HANDLE handle, const char* option } return result; } + diff --git a/src/azure_c_shared_utility/httpapiexsas.c b/src/azure_c_shared_utility/httpapiexsas.c index 093e6e0..eb61cb5 100644 --- a/src/azure_c_shared_utility/httpapiexsas.c +++ b/src/azure_c_shared_utility/httpapiexsas.c @@ -133,3 +133,4 @@ HTTPAPIEX_RESULT HTTPAPIEX_SAS_ExecuteRequest(HTTPAPIEX_SAS_HANDLE sasHandle, HT /*Codes_SRS_HTTPAPIEXSAS_06_016: [HTTPAPIEX_ExecuteRequest with the remaining parameters (following sasHandle) as its arguments will be invoked and the result of that call is the result of HTTPAPIEX_SAS_ExecuteRequest.]*/ return HTTPAPIEX_ExecuteRequest(handle,requestType,relativePath,requestHttpHeadersHandle,requestContent,statusCode,responseHeadersHandle,responseContent); } + diff --git a/src/azure_c_shared_utility/httpheaders.c b/src/azure_c_shared_utility/httpheaders.c index f4c0962..61b1e21 100644 --- a/src/azure_c_shared_utility/httpheaders.c +++ b/src/azure_c_shared_utility/httpheaders.c @@ -333,3 +333,4 @@ HTTP_HEADERS_HANDLE HTTPHeaders_Clone(HTTP_HEADERS_HANDLE handle) } return result; } + diff --git a/src/azure_c_shared_utility/map.c b/src/azure_c_shared_utility/map.c index 28755a3..79679a5 100644 --- a/src/azure_c_shared_utility/map.c +++ b/src/azure_c_shared_utility/map.c @@ -674,4 +674,5 @@ STRING_HANDLE Map_ToJSON(MAP_HANDLE handle) } return result; -} \ No newline at end of file +} + diff --git a/src/azure_c_shared_utility/optionhandler.c b/src/azure_c_shared_utility/optionhandler.c index 19a6ac8..fc33308 100644 --- a/src/azure_c_shared_utility/optionhandler.c +++ b/src/azure_c_shared_utility/optionhandler.c @@ -266,3 +266,4 @@ void OptionHandler_Destroy(OPTIONHANDLER_HANDLE handle) DestroyInternal(handle); } } + diff --git a/src/azure_c_shared_utility/refcount.h b/src/azure_c_shared_utility/refcount.h index ad7d55d..7fbaac3 100644 --- a/src/azure_c_shared_utility/refcount.h +++ b/src/azure_c_shared_utility/refcount.h @@ -27,19 +27,8 @@ extern "C" #include #endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ == 201112) && (__STDC_NO_ATOMICS__!=1) -#define REFCOUNT_USE_STD_ATOMIC 1 -#endif - -#if defined(ARDUINO_ARCH_SAMD) -#undef REFCOUNT_USE_STD_ATOMIC -#endif - -#if defined(FREERTOS_ARCH_ESP8266) -#undef REFCOUNT_USE_STD_ATOMIC -#define REFCOUNT_ATOMIC_DONTCARE 1 -#undef __GNUC__ -#endif +// Include the platform-specific file that defines atomic functionality +#include "refcount_os.h" #define REFCOUNT_TYPE(type) \ struct C2(C2(REFCOUNT_, type), _TAG) @@ -55,14 +44,6 @@ C2(REFCOUNT_, type) /*the newly allocated memory shall be free'd by free()*/ /*and the ref counting is handled internally by the type in the _Create/ _Clone /_Destroy functions */ -#if defined(REFCOUNT_USE_STD_ATOMIC) -#define COUNT_TYPE _Atomic uint32_t -#elif defined(WIN32) -#define COUNT_TYPE LONG -#else -#define COUNT_TYPE uint32_t -#endif - #define DEFINE_REFCOUNT_TYPE(type) \ REFCOUNT_TYPE(type) \ { \ @@ -79,58 +60,15 @@ static type* REFCOUNT_TYPE_DECLARE_CREATE(type) (void) return (type*)result; \ } \ -/*the following macros increment/decrement a ref count in an atomic way, depending on the platform*/ -/*The following mechanisms are considered in this order -C11 - - will result in #include - - will use atomic_fetch_add/sub; - - about the return value: "Atomically, the value pointed to by object immediately before the effects" -windows - - will result in #include "windows.h" - - will use InterlockedIncrement/InterlockedDecrement; - - about the return value: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683580(v=vs.85).aspx "The function returns the resulting decremented value" -gcc - - will result in no include (for gcc these are intrinsics build in) - - will use __sync_fetch_and_add/sub - - about the return value: "... returns the value that had previously been in memory." (https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html#Atomic-Builtins) -other cases - - if REFCOUNT_ATOMIC_DONTCARE is defined, then - will result in ++/-- used for increment/decrement. - - if it is not defined, then error out - -It seems windows is "one off" because it returns the value "after" the decrement, as opposed to C11 standard and gcc that return the value "before". -The macro DEC_RETURN_ZERO will be "0" on windows, and "1" on the other cases. -*/ - -/*if macro DEC_REF returns DEC_RETURN_ZERO that means the ref count has reached zero.*/ -#if defined(REFCOUNT_USE_STD_ATOMIC) -#include -#define DEC_RETURN_ZERO (1) -#define INC_REF(type, var) atomic_fetch_add((&((REFCOUNT_TYPE(type)*)var)->count), 1) -#define DEC_REF(type, var) atomic_fetch_sub((&((REFCOUNT_TYPE(type)*)var)->count), 1) - -#elif defined(WIN32) -#include "windows.h" -#define DEC_RETURN_ZERO (0) -#define INC_REF(type, var) InterlockedIncrement(&(((REFCOUNT_TYPE(type)*)var)->count)) -#define DEC_REF(type, var) InterlockedDecrement(&(((REFCOUNT_TYPE(type)*)var)->count)) - -#elif defined(__GNUC__) -#define DEC_RETURN_ZERO (0) -#define INC_REF(type, var) __sync_add_and_fetch((&((REFCOUNT_TYPE(type)*)var)->count), 1) -#define DEC_REF(type, var) __sync_sub_and_fetch((&((REFCOUNT_TYPE(type)*)var)->count), 1) - -#else -#if defined(REFCOUNT_ATOMIC_DONTCARE) -#define DEC_RETURN_ZERO (0) -#define INC_REF(type, var) ++((((REFCOUNT_TYPE(type)*)var)->count)) -#define DEC_REF(type, var) --((((REFCOUNT_TYPE(type)*)var)->count)) -#else -#error do not know how to atomically increment and decrement a uint32_t :(. Platform support needs to be extended to your platform. -#endif /*defined(REFCOUNT_ATOMIC_DONTCARE)*/ -#endif - - +#ifndef DEC_RETURN_ZERO +#error refcount_os.h does not define DEC_RETURN_ZERO +#endif // !DEC_RETURN_ZERO +#ifndef INC_REF +#error refcount_os.h does not define INC_REF +#endif // !INC_REF +#ifndef DEC_REF +#error refcount_os.h does not define DEC_REF +#endif // !DEC_REF #ifdef __cplusplus } diff --git a/src/azure_c_shared_utility/refcount_os.h b/src/azure_c_shared_utility/refcount_os.h new file mode 100644 index 0000000..4bc257d --- /dev/null +++ b/src/azure_c_shared_utility/refcount_os.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// This file gets included into refcount.h as a means of extending the behavior of +// atomic increment, decrement, and test. +// +// The Azure IoT C SDK does not require thread-safe refcount operations, so +// this file is appropriate for any device when using the Azure IoT C SDK. + +#ifndef REFCOUNT_OS_H__GENERIC +#define REFCOUNT_OS_H__GENERIC + +#define COUNT_TYPE uint32_t + +#define DEC_RETURN_ZERO (0) +#define INC_REF(type, var) ++((((REFCOUNT_TYPE(type)*)var)->count)) +#define DEC_REF(type, var) --((((REFCOUNT_TYPE(type)*)var)->count)) + +#endif // REFCOUNT_OS_H__GENERIC diff --git a/src/azure_c_shared_utility/sastoken.c b/src/azure_c_shared_utility/sastoken.c index 389cc63..da390f9 100644 --- a/src/azure_c_shared_utility/sastoken.c +++ b/src/azure_c_shared_utility/sastoken.c @@ -344,3 +344,4 @@ STRING_HANDLE SASToken_CreateString(const char* key, const char* scope, const ch } return result; } + diff --git a/src/azure_c_shared_utility/sha1.c b/src/azure_c_shared_utility/sha1.c index ad8803c..1fdd86a 100644 --- a/src/azure_c_shared_utility/sha1.c +++ b/src/azure_c_shared_utility/sha1.c @@ -438,3 +438,4 @@ static void SHA1ProcessMessageBlock(SHA1Context *context) context->Message_Block_Index = 0; } + diff --git a/src/azure_c_shared_utility/sha224.c b/src/azure_c_shared_utility/sha224.c index 2671f8a..8d70be9 100644 --- a/src/azure_c_shared_utility/sha224.c +++ b/src/azure_c_shared_utility/sha224.c @@ -598,3 +598,4 @@ static int SHA224_256ResultN(SHA256Context *context, return shaSuccess; } + diff --git a/src/azure_c_shared_utility/sha384-512.c b/src/azure_c_shared_utility/sha384-512.c index ab097bd..b55ff9b 100644 --- a/src/azure_c_shared_utility/sha384-512.c +++ b/src/azure_c_shared_utility/sha384-512.c @@ -1044,3 +1044,4 @@ static int SHA384_512ResultN(SHA512Context *context, return shaSuccess; } + diff --git a/src/azure_c_shared_utility/singlylinkedlist.c b/src/azure_c_shared_utility/singlylinkedlist.c index 62c43a6..5d7ba34 100644 --- a/src/azure_c_shared_utility/singlylinkedlist.c +++ b/src/azure_c_shared_utility/singlylinkedlist.c @@ -364,4 +364,5 @@ int singlylinkedlist_foreach(SINGLYLINKEDLIST_HANDLE list, LIST_ACTION_FUNCTION } return result; -} \ No newline at end of file +} + diff --git a/src/azure_c_shared_utility/string_tokenizer.c b/src/azure_c_shared_utility/string_tokenizer.c index 658a29f..2d6290d 100644 --- a/src/azure_c_shared_utility/string_tokenizer.c +++ b/src/azure_c_shared_utility/string_tokenizer.c @@ -200,3 +200,4 @@ void STRING_TOKENIZER_destroy(STRING_TOKENIZER_HANDLE t) } } + diff --git a/src/azure_c_shared_utility/strings.c b/src/azure_c_shared_utility/strings.c index eaf4c9f..ac59a3f 100644 --- a/src/azure_c_shared_utility/strings.c +++ b/src/azure_c_shared_utility/strings.c @@ -840,3 +840,4 @@ int STRING_replace(STRING_HANDLE handle, char target, char replace) } return result; } + diff --git a/src/azure_c_shared_utility/tlsio_options.c b/src/azure_c_shared_utility/tlsio_options.c new file mode 100644 index 0000000..72d43d3 --- /dev/null +++ b/src/azure_c_shared_utility/tlsio_options.c @@ -0,0 +1,313 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include + +#include "azure_c_shared_utility/gballoc.h" +#include "azure_c_shared_utility/tlsio_options.h" +#include "azure_c_shared_utility/shared_util_options.h" +#include "azure_c_shared_utility/xlogging.h" +#include "azure_c_shared_utility/crt_abstractions.h" + + +// Initialize the TLSIO_OPTIONS struct +void tlsio_options_initialize(TLSIO_OPTIONS* options, int supported_options) +{ + // Using static function rules, so 'options' is not checked for NULL + // + // The supported_options value does not need validation because undefined bits are + // ignored, while any valid missing bits result in an "option not supported" error + // that will show up in unit testing. + options->supported_options = supported_options; + options->trusted_certs = NULL; + options->x509_type = TLSIO_OPTIONS_x509_TYPE_UNSPECIFIED; + options->x509_cert = NULL; + options->x509_key = NULL; +} + +static int set_and_validate_x509_type(TLSIO_OPTIONS* options, TLSIO_OPTIONS_x509_TYPE x509_type) +{ + int result; + if ((options->supported_options & x509_type) == 0) + { + // This case also rejects the nonsensical TLSIO_OPTIONS_x509_TYPE_UNSPECIFIED + LogError("Unsupported x509 type: %d", x509_type); + result = __FAILURE__; + } + else if (options->x509_type == TLSIO_OPTIONS_x509_TYPE_UNSPECIFIED) + { + // Initial type setting + options->x509_type = x509_type; + result = 0; + } + else if (options->x509_type != x509_type) + { + LogError("Supplied x509 type conflicts with previously set x509"); + result = __FAILURE__; + } + else + { + // The types match okay + result = 0; + } + + return result; +} + +void tlsio_options_release_resources(TLSIO_OPTIONS* options) +{ + if (options != NULL) + { + free((void*)options->trusted_certs); + free((void*)options->x509_cert); + free((void*)options->x509_key); + } + else + { + LogError("NULL options"); + } +} + +static bool is_supported_string_option(const char* name) +{ + return + (strcmp(name, OPTION_TRUSTED_CERT) == 0) || + (strcmp(name, SU_OPTION_X509_CERT) == 0) || + (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0) || + (strcmp(name, OPTION_X509_ECC_CERT) == 0) || + (strcmp(name, OPTION_X509_ECC_KEY) == 0); +} + +TLSIO_OPTIONS_RESULT tlsio_options_destroy_option(const char* name, const void* value) +{ + TLSIO_OPTIONS_RESULT result; + if (name == NULL || value == NULL) + { + LogError("NULL parameter: name: %p, value: %p", name, value); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (is_supported_string_option(name)) + { + free((void*)value); + result = TLSIO_OPTIONS_RESULT_SUCCESS; + } + else + { + result = TLSIO_OPTIONS_RESULT_NOT_HANDLED; + } + return result; +} + +TLSIO_OPTIONS_RESULT tlsio_options_clone_option(const char* name, const void* value, void** out_value) +{ + TLSIO_OPTIONS_RESULT result; + + if (name == NULL || value == NULL || out_value == NULL) + { + LogError("NULL parameter: name: %p, value: %p, out_value: %p", + name, value, out_value); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (is_supported_string_option(name)) + { + *out_value = NULL; + if (mallocAndStrcpy_s((char**)out_value, value) != 0) + { + LogError("unable to mallocAndStrcpy_s option value"); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else + { + result = TLSIO_OPTIONS_RESULT_SUCCESS; + } + } + else + { + result = TLSIO_OPTIONS_RESULT_NOT_HANDLED; + } + return result; +} + +TLSIO_OPTIONS_RESULT tlsio_options_set(TLSIO_OPTIONS* options, + const char* optionName, const void* value) +{ + TLSIO_OPTIONS_RESULT result; + char* copied_value = NULL; + + if (options == NULL || optionName == NULL || value == NULL) + { + LogError("NULL parameter: options: %p, optionName: %p, value: %p", + options, optionName, value); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (!is_supported_string_option(optionName)) + { + result = TLSIO_OPTIONS_RESULT_NOT_HANDLED; + } + else if(mallocAndStrcpy_s(&copied_value, value) != 0) + { + LogError("unable to mallocAndStrcpy_s option value"); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0) + { + if ((options->supported_options & TLSIO_OPTION_BIT_TRUSTED_CERTS) == 0) + { + LogError("Trusted certs option not supported"); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (options->trusted_certs != NULL) + { + LogError("unable to set trusted cert option more than once"); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else + { + options->trusted_certs = copied_value; + result = TLSIO_OPTIONS_RESULT_SUCCESS; + } + } + else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0) + { + TLSIO_OPTIONS_x509_TYPE this_type = (strcmp(SU_OPTION_X509_CERT, optionName) == 0) ? TLSIO_OPTIONS_x509_TYPE_RSA : TLSIO_OPTIONS_x509_TYPE_ECC; + if (options->x509_cert != NULL) + { + LogError("unable to set x509 cert more than once"); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (set_and_validate_x509_type(options, this_type) != 0) + { + // Error logged by helper + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else + { + options->x509_cert = copied_value; + result = TLSIO_OPTIONS_RESULT_SUCCESS; + } + } + else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0) + { + TLSIO_OPTIONS_x509_TYPE this_type = (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0) ? TLSIO_OPTIONS_x509_TYPE_RSA : TLSIO_OPTIONS_x509_TYPE_ECC; + if (options->x509_key != NULL) + { + LogError("unable to set x509 key more than once"); + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else if (set_and_validate_x509_type(options, this_type) != 0) + { + // Error logged by helper + result = TLSIO_OPTIONS_RESULT_ERROR; + } + else + { + options->x509_key = copied_value; + result = TLSIO_OPTIONS_RESULT_SUCCESS; + } + } + else + { + // This is logically impossible due to earlier tests, so just quiet the compiler + result = TLSIO_OPTIONS_RESULT_ERROR; + } + + if (result != TLSIO_OPTIONS_RESULT_SUCCESS) + { + free(copied_value); + } + + return result; +} + +// A helper that works if the tlsio does not use any extra options +static void* local_clone_option(const char* name, const void* value) +{ + void* result = NULL; + if (tlsio_options_clone_option(name, value, &result) != TLSIO_OPTIONS_RESULT_SUCCESS) + { + LogError("Unexpected local_clone_option failure"); + } + return result; +} + +// A helper that works if the tlsio does not use any extra options +void local_destroy_option(const char* name, const void* value) +{ + if (tlsio_options_destroy_option(name, value) != TLSIO_OPTIONS_RESULT_SUCCESS) + { + LogError("Unexpected local_destroy_option failure"); + } +} + +OPTIONHANDLER_HANDLE tlsio_options_retrieve_options(TLSIO_OPTIONS* options, pfSetOption setOption) +{ + return tlsio_options_retrieve_options_ex(options, local_clone_option, local_destroy_option, setOption); +} + + +OPTIONHANDLER_HANDLE tlsio_options_retrieve_options_ex(TLSIO_OPTIONS* options, + pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption) +{ + OPTIONHANDLER_HANDLE result; + if (options == NULL || cloneOption == NULL || destroyOption == NULL || setOption == NULL) + { + LogError("Null parameter in options: %p, cloneOption: %p, destroyOption: %p, setOption: %p", + options, cloneOption, destroyOption, setOption); + result = NULL; + } + else + { + result = OptionHandler_Create(cloneOption, destroyOption, setOption); + if (result == NULL) + { + LogError("OptionHandler_Create failed"); + /*return as is*/ + } + else if ( + (options->trusted_certs != NULL) && + (OptionHandler_AddOption(result, OPTION_TRUSTED_CERT, options->trusted_certs) != OPTIONHANDLER_OK) + ) + { + LogError("unable to save TrustedCerts option"); + OptionHandler_Destroy(result); + result = NULL; + } + else if (options->x509_type != TLSIO_OPTIONS_x509_TYPE_UNSPECIFIED) + { + const char* x509_cert_option; + const char* x509_key_option; + if (options->x509_type == TLSIO_OPTIONS_x509_TYPE_ECC) + { + x509_cert_option = OPTION_X509_ECC_CERT; + x509_key_option = OPTION_X509_ECC_KEY; + } + else + { + x509_cert_option = SU_OPTION_X509_CERT; + x509_key_option = SU_OPTION_X509_PRIVATE_KEY; + } + if ( + (options->x509_cert != NULL) && + (OptionHandler_AddOption(result, x509_cert_option, options->x509_cert) != OPTIONHANDLER_OK) + ) + { + LogError("unable to save x509 cert option"); + OptionHandler_Destroy(result); + result = NULL; + } + else if ( + (options->x509_key != NULL) && + (OptionHandler_AddOption(result, x509_key_option, options->x509_key) != OPTIONHANDLER_OK) + ) + { + LogError("unable to save x509 key option"); + OptionHandler_Destroy(result); + result = NULL; + } + } + } + + return result; +} + + diff --git a/src/azure_c_shared_utility/tlsio_options.h b/src/azure_c_shared_utility/tlsio_options.h new file mode 100644 index 0000000..0f5adeb --- /dev/null +++ b/src/azure_c_shared_utility/tlsio_options.h @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// tlsio_options handles only the most commonly-used options for tlsio adapters. Options +// not supported by this component may be handled in the tlsio adapter instead. + +#ifndef TLSIO_OPTIONS_H +#define TLSIO_OPTIONS_H + +#include "azure_c_shared_utility/xio.h" +#include "azure_c_shared_utility/umock_c_prod.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + // This enum identifies individual options + typedef enum TLSIO_OPTION_BIT_TAG + { + TLSIO_OPTION_BIT_NONE = 0x00, + TLSIO_OPTION_BIT_TRUSTED_CERTS = 0x01, + TLSIO_OPTION_BIT_x509_RSA_CERT = 0x02, + TLSIO_OPTION_BIT_x509_ECC_CERT = 0x04, + } TLSIO_OPTION_BIT; + + typedef enum TLSIO_OPTIONS_x509_TYPE_TAG + { + TLSIO_OPTIONS_x509_TYPE_UNSPECIFIED = TLSIO_OPTION_BIT_NONE, + TLSIO_OPTIONS_x509_TYPE_RSA = TLSIO_OPTION_BIT_x509_RSA_CERT, + TLSIO_OPTIONS_x509_TYPE_ECC = TLSIO_OPTION_BIT_x509_ECC_CERT + } TLSIO_OPTIONS_x509_TYPE; + + typedef enum TLSIO_OPTIONS_RESULT_TAG + { + TLSIO_OPTIONS_RESULT_SUCCESS, + TLSIO_OPTIONS_RESULT_NOT_HANDLED, + TLSIO_OPTIONS_RESULT_ERROR + } TLSIO_OPTIONS_RESULT; + + + // This struct contains the commonly-used options which + // are supported by tlsio_options. + typedef struct TLSIO_OPTIONS_TAG + { + int supported_options; + const char* trusted_certs; + TLSIO_OPTIONS_x509_TYPE x509_type; + const char* x509_cert; + const char* x509_key; + } TLSIO_OPTIONS; + + // Initialize the TLSIO_OPTIONS struct and specify which options are supported as a bit-or'ed + // set of TLSIO_OPTION_BIT. For the x509 certs, only the *_CERT bit need be specified; the *_KEY + // is understood to go with the cert. + void tlsio_options_initialize(TLSIO_OPTIONS* options, int option_caps); + + // This should be called in the tlsio destructor + void tlsio_options_release_resources(TLSIO_OPTIONS* options); + + // xio requires the implementation of four functions: xio_setoption, xio_retrieveoptions, + // an anonymous clone_option, and an anonymous destroy_option. + + // The helper for xio_setoption + TLSIO_OPTIONS_RESULT tlsio_options_set(TLSIO_OPTIONS* options, + const char* optionName, const void* value); + + // Use this helper for xio_retrieveoptions if this helper covers all your tlsio options + OPTIONHANDLER_HANDLE tlsio_options_retrieve_options(TLSIO_OPTIONS* options, pfSetOption setOption); + + // Use this helper for xio_retrieveoptions if your tlsio supports more options than this helper does + OPTIONHANDLER_HANDLE tlsio_options_retrieve_options_ex(TLSIO_OPTIONS* options, + pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption); + + // The helper for the anonymous clone_option -- needed only to support extra options + TLSIO_OPTIONS_RESULT tlsio_options_clone_option(const char* name, const void* value, void** out_value); + + // The helper for the anonymous destroy_option -- needed only to support extra options + TLSIO_OPTIONS_RESULT tlsio_options_destroy_option(const char* name, const void* value); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* TLSIO_OPTIONS_H */ diff --git a/src/azure_c_shared_utility/urlencode.c b/src/azure_c_shared_utility/urlencode.c index 9469f9d..80550dc 100644 --- a/src/azure_c_shared_utility/urlencode.c +++ b/src/azure_c_shared_utility/urlencode.c @@ -165,3 +165,4 @@ STRING_HANDLE URL_Encode(STRING_HANDLE input) } return result; } + diff --git a/src/azure_c_shared_utility/usha.c b/src/azure_c_shared_utility/usha.c index 8db8e96..5eb8306 100644 --- a/src/azure_c_shared_utility/usha.c +++ b/src/azure_c_shared_utility/usha.c @@ -261,3 +261,4 @@ int USHAHashSizeBits(enum SHAversion whichSha) } } + diff --git a/src/azure_c_shared_utility/utf8_checker.c b/src/azure_c_shared_utility/utf8_checker.c index fd3bffa..caaeb17 100644 --- a/src/azure_c_shared_utility/utf8_checker.c +++ b/src/azure_c_shared_utility/utf8_checker.c @@ -175,3 +175,4 @@ bool utf8_checker_is_valid_utf8(const unsigned char* utf8_str, size_t length) return result; } + diff --git a/src/azure_c_shared_utility/uuid.c b/src/azure_c_shared_utility/uuid.c index 2f68c2a..3ea8212 100644 --- a/src/azure_c_shared_utility/uuid.c +++ b/src/azure_c_shared_utility/uuid.c @@ -169,3 +169,4 @@ int UUID_generate(UUID* uuid) return result; } + diff --git a/src/azure_c_shared_utility/uws_client.c b/src/azure_c_shared_utility/uws_client.c index 0ab1917..a9364c5 100644 --- a/src/azure_c_shared_utility/uws_client.c +++ b/src/azure_c_shared_utility/uws_client.c @@ -113,7 +113,7 @@ UWS_CLIENT_HANDLE uws_client_create(const char* hostname, unsigned int port, con /* Codes_SRS_UWS_CLIENT_01_411: [ If `protocol_count` is non zero and `protocols` is NULL then `uws_client_create` shall fail and return NULL. ]*/ ((protocols == NULL) && (protocol_count > 0))) { - LogError("Invalid arguments: hostname = %p, resource_name = %p, protocols = %p, protocol_count = %zu", hostname, resource_name, protocols, protocol_count); + LogError("Invalid arguments: hostname = %p, resource_name = %p, protocols = %p, protocol_count = %u", hostname, resource_name, protocols, protocol_count); result = NULL; } else @@ -130,7 +130,7 @@ UWS_CLIENT_HANDLE uws_client_create(const char* hostname, unsigned int port, con if (i < protocol_count) { - LogError("Protocol index %zu has NULL name", i); + LogError("Protocol index %u has NULL name", i); result = NULL; } else @@ -347,7 +347,7 @@ UWS_CLIENT_HANDLE uws_client_create_with_io(const IO_INTERFACE_DESCRIPTION* io_i /* Codes_SRS_UWS_CLIENT_01_525: [ If `protocol_count` is non zero and `protocols` is NULL then `uws_client_create_with_io` shall fail and return NULL. ]*/ ((protocols == NULL) && (protocol_count > 0))) { - LogError("Invalid arguments: io_interface = %p, resource_name = %p, protocols = %p, protocol_count = %zu", io_interface, resource_name, protocols, protocol_count); + LogError("Invalid arguments: io_interface = %p, resource_name = %p, protocols = %p, protocol_count = %u", io_interface, resource_name, protocols, protocol_count); result = NULL; } else @@ -364,7 +364,7 @@ UWS_CLIENT_HANDLE uws_client_create_with_io(const IO_INTERFACE_DESCRIPTION* io_i if (i < protocol_count) { /* Codes_SRS_UWS_CLIENT_01_526: [ If the `protocol` member of any of the items in the `protocols` argument is NULL, then `uws_client_create_with_io` shall fail and return NULL. ]*/ - LogError("Protocol index %zu has NULL name", i); + LogError("Protocol index %u has NULL name", i); result = NULL; } else @@ -846,7 +846,7 @@ static int ParseStringToDecimal(const char *src, int* dst) int result; char* next; - (*dst) = strtol(src, &next, 0); + (*dst) = (int)strtol(src, &next, 0); if ((src == next) || ((((*dst) == INT_MAX) || ((*dst) == INT_MIN)) && (errno != 0))) { result = __FAILURE__; @@ -1975,3 +1975,4 @@ OPTIONHANDLER_HANDLE uws_client_retrieve_options(UWS_CLIENT_HANDLE uws_client) return result; } + diff --git a/src/azure_c_shared_utility/uws_frame_encoder.c b/src/azure_c_shared_utility/uws_frame_encoder.c index bb37c16..e7ccb30 100644 --- a/src/azure_c_shared_utility/uws_frame_encoder.c +++ b/src/azure_c_shared_utility/uws_frame_encoder.c @@ -189,3 +189,4 @@ BUFFER_HANDLE uws_frame_encoder_encode(WS_FRAME_TYPE opcode, const unsigned char return result; } + diff --git a/src/azure_c_shared_utility/vector.c b/src/azure_c_shared_utility/vector.c index 93468ba..de67eda 100644 --- a/src/azure_c_shared_utility/vector.c +++ b/src/azure_c_shared_utility/vector.c @@ -16,7 +16,7 @@ VECTOR_HANDLE VECTOR_create(size_t elementSize) /* Codes_SRS_VECTOR_10_002: [VECTOR_create shall fail and return NULL if elementsize is 0.] */ if (elementSize == 0) { - LogError("invalid elementSize(%zd).", elementSize); + LogError("invalid elementSize(%u).", elementSize); result = NULL; } else @@ -94,7 +94,7 @@ int VECTOR_push_back(VECTOR_HANDLE handle, const void* elements, size_t numEleme /* Codes_SRS_VECTOR_10_011: [VECTOR_push_back shall fail and return non-zero if `handle` is NULL.] */ /* Codes_SRS_VECTOR_10_034: [VECTOR_push_back shall fail and return non-zero if `elements` is NULL.] */ /* Codes_SRS_VECTOR_10_035: [VECTOR_push_back shall fail and return non-zero if `numElements` is 0.] */ - LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements); + LogError("invalid argument - handle(%p), elements(%p), numElements(%u).", handle, elements, numElements); result = __FAILURE__; } else @@ -130,7 +130,7 @@ void VECTOR_erase(VECTOR_HANDLE handle, void* elements, size_t numElements) /* Codes_SRS_VECTOR_10_015: [VECTOR_erase shall return if `handle` is NULL.] */ /* Codes_SRS_VECTOR_10_038: [VECTOR_erase shall return if `elements` is NULL.] */ /* Codes_SRS_VECTOR_10_039: [VECTOR_erase shall return if `numElements` is 0.] */ - LogError("invalid argument - handle(%p), elements(%p), numElements(%zd).", handle, elements, numElements); + LogError("invalid argument - handle(%p), elements(%p), numElements(%u).", handle, elements, numElements); } else { @@ -155,7 +155,7 @@ void VECTOR_erase(VECTOR_HANDLE handle, void* elements, size_t numElements) if (src > srcEnd) { /* Codes_SRS_VECTOR_10_040: [VECTOR_erase shall return if `elements` is out of bound.] */ - LogError("invalid argument - numElements(%zd) is out of bound.", numElements); + LogError("invalid argument - numElements(%u) is out of bound.", numElements); } else { @@ -218,7 +218,7 @@ void* VECTOR_element(VECTOR_HANDLE handle, size_t index) if (index >= handle->count) { /* Codes_SRS_VECTOR_10_020: [VECTOR_element shall fail and return NULL if the given index is out of range.] */ - LogError("invalid argument - index(%zd); should be >= 0 and < %zd.", index, handle->count); + LogError("invalid argument - index(%u); should be >= 0 and < %u.", index, handle->count); result = NULL; } else @@ -336,3 +336,4 @@ size_t VECTOR_size(VECTOR_HANDLE handle) } return result; } + diff --git a/src/azure_c_shared_utility/xio.c b/src/azure_c_shared_utility/xio.c index c3d1107..ec6092b 100644 --- a/src/azure_c_shared_utility/xio.c +++ b/src/azure_c_shared_utility/xio.c @@ -301,3 +301,4 @@ OPTIONHANDLER_HANDLE xio_retrieveoptions(XIO_HANDLE xio) return result; } + diff --git a/src/azure_c_shared_utility/xlogging.c b/src/azure_c_shared_utility/xlogging.c index b59b089..2cee864 100644 --- a/src/azure_c_shared_utility/xlogging.c +++ b/src/azure_c_shared_utility/xlogging.c @@ -68,3 +68,4 @@ LOGGER_LOG_GETLASTERROR xlogging_get_log_function_GetLastError(void) #endif #endif + diff --git a/src/esp8266/azcpgmspace.cpp b/src/esp8266/azcpgmspace.cpp new file mode 100644 index 0000000..b1dede1 --- /dev/null +++ b/src/esp8266/azcpgmspace.cpp @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if defined(ARDUINO_ARCH_ESP8266) +#include "azcpgmspace.h" +#include + +char* az_c_strncpy_P(char* dest, PGM_P src, size_t size) { + return strncpy_P(dest, src, size); +} + +size_t az_c_strlen_P(PGM_P s) { + return strlen_P(s); +} + +#endif diff --git a/src/esp8266/azcpgmspace.h b/src/esp8266/azcpgmspace.h new file mode 100644 index 0000000..4a29b1b --- /dev/null +++ b/src/esp8266/azcpgmspace.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +/** @file azcpgmspace.h +* @brief Function prototypes for pgmspace functions that need extern-ing to C +* +* @details These fucntions are just wrappers around existing ones in pgmspace.h that +* are not defined in a way to make them linkable from c libs. +*/ +#if defined(ARDUINO_ARCH_ESP8266) +#ifndef AZCPGMSPACE_H +#define AZCPGMSPACE_H + +#include +#include "azure_c_shared_utility/crt_abstractions.h" + + +#ifdef __cplusplus +#include +extern "C" { +#else +#include +#endif +extern char* az_c_strncpy_P(char* dest, PGM_P src, size_t size); +extern size_t az_c_strlen_P(PGM_P s); +#ifdef __cplusplus +} +#endif + +#endif // _AZCPGMSPACE_H + +#endif // #if defined(ARDUINO_ARCH_ESP8266) diff --git a/src/esp8266/sample_init.cpp b/src/esp8266/sample_init.cpp new file mode 100644 index 0000000..1799f87 --- /dev/null +++ b/src/esp8266/sample_init.cpp @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifdef ARDUINO_ARCH_ESP8266 + +#include +#include +#include +#include +#include + +// Times before 2010 (1970 + 40 years) are invalid +#define MIN_EPOCH 40 * 365 * 24 * 3600 + + +static void initSerial() { + // Start serial and initialize stdout + Serial.begin(115200); + Serial.setDebugOutput(true); +} + +static void initWifi(const char* ssid, const char* pass) { + // Attempt to connect to Wifi network: + Serial.print("\r\n\r\nAttempting to connect to SSID: "); + Serial.println(ssid); + + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + WiFi.begin(ssid, pass); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println("\r\nConnected to wifi"); +} + +static void initTime() { + time_t epochTime; + + configTime(0, 0, "pool.ntp.org", "time.nist.gov"); + + while (true) { + epochTime = time(NULL); + + if (epochTime < MIN_EPOCH) { + Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry."); + delay(2000); + } else { + Serial.print("Fetched NTP epoch time is: "); + Serial.println(epochTime); + break; + } + } +} + +void esp8266_sample_init(const char* ssid, const char* password) +{ + initSerial(); + initWifi(ssid, password); + initTime(); +} + +#endif // ARDUINO_ARCH_ESP8266 diff --git a/src/esp8266/sample_init.h b/src/esp8266/sample_init.h new file mode 100644 index 0000000..4305e0f --- /dev/null +++ b/src/esp8266/sample_init.h @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifndef SAMPLE_INIT_H +#define SAMPLE_INIT_H + +#define sample_init esp8266_sample_init + +void esp8266_sample_init(const char* ssid, const char* password); + +#endif // SAMPLE_INIT_H diff --git a/src/esp8266/time.cpp b/src/esp8266/time.cpp new file mode 100644 index 0000000..98e5c4b --- /dev/null +++ b/src/esp8266/time.cpp @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if defined(ARDUINO_ARCH_ESP8266) +#include + +extern "C" { + double difftime(time_t _time2, time_t _time1) + { + return (double)_time2 - (double)_time1; + } + + size_t strftime(char *s, size_t maxsize, const char* format, const struct tm *timeptr) + { + /*For now esp8266 will not report time.*/ + (void)(s, maxsize, format, timeptr); + return 0; + } +} +#endif \ No newline at end of file diff --git a/examples/samd/simplesample_http/NTPClient.cpp b/src/samd/NTPClientAz.cpp similarity index 80% rename from examples/samd/simplesample_http/NTPClient.cpp rename to src/samd/NTPClientAz.cpp index 90dd08e..c90c5ed 100644 --- a/examples/samd/simplesample_http/NTPClient.cpp +++ b/src/samd/NTPClientAz.cpp @@ -2,21 +2,21 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. #if defined(ARDUINO_ARCH_SAMD) -#include "NTPClient.h" +#include "NTPClientAz.h" #define LOCAL_UDP_PORT 2390 -NTPClient::NTPClient() : +NTPClientAz::NTPClientAz() : _udp() { } -int NTPClient::begin() +int NTPClientAz::begin() { return _udp.begin(LOCAL_UDP_PORT); } -uint32_t NTPClient::getEpochTime(const char* host, int port, unsigned long timeout) +uint32_t NTPClientAz::getEpochTime(const char* host, int port, unsigned long timeout) { if (host == NULL || port < 1) { return (uint32_t)-1; @@ -32,12 +32,12 @@ uint32_t NTPClient::getEpochTime(const char* host, int port, unsigned long timeo return parseResponse(); } -void NTPClient::end() +void NTPClientAz::end() { _udp.stop(); } -void NTPClient::prepareRequest() +void NTPClientAz::prepareRequest() { memset(_buffer, 0, NTP_PACKET_SIZE); @@ -55,14 +55,14 @@ void NTPClient::prepareRequest() _buffer[15] = 52; } -void NTPClient::sendRequest(const char* host, int port) +void NTPClientAz::sendRequest(const char* host, int port) { _udp.beginPacket(host, port); _udp.write(_buffer, NTP_PACKET_SIZE); _udp.endPacket(); } -int NTPClient::receiveResponse(unsigned long timeout) +int NTPClientAz::receiveResponse(unsigned long timeout) { long start = millis(); int size = 0; @@ -80,7 +80,7 @@ int NTPClient::receiveResponse(unsigned long timeout) return 1; } -uint32_t NTPClient::parseResponse() +uint32_t NTPClientAz::parseResponse() { uint16_t high = word(_buffer[40], _buffer[41]); uint16_t low = word(_buffer[42], _buffer[43]); diff --git a/examples/samd/simplesample_http/NTPClient.h b/src/samd/NTPClientAz.h similarity index 80% rename from examples/samd/simplesample_http/NTPClient.h rename to src/samd/NTPClientAz.h index bed5b21..050bcef 100644 --- a/examples/samd/simplesample_http/NTPClient.h +++ b/src/samd/NTPClientAz.h @@ -1,21 +1,23 @@ // Copyright (c) Arduino. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +#if defined(ARDUINO_ARCH_SAMD) + +#ifndef NTPCLIENT_AZ_H +#define NTPCLIENT_AZ_H + #include #include -#ifndef NTPCLIENT_H -#define NTPCLIENT_H - #define NTP_PACKET_SIZE 48 #define NTP_PORT 123 #define DEFAULT_NTP_TIMEOUT 10000 -class NTPClient +class NTPClientAz { public: - NTPClient(); + NTPClientAz(); int begin(); uint32_t getEpochTime(const char* host, int port = NTP_PORT, unsigned long timeout = DEFAULT_NTP_TIMEOUT); void end(); @@ -30,4 +32,6 @@ class NTPClient WiFiUDP _udp; }; -#endif // NTPCLIENT_H +#endif // NTPCLIENT_AZ_H + +#endif // ARDUINO_ARCH_SAMD diff --git a/src/samd/sample_init.cpp b/src/samd/sample_init.cpp new file mode 100644 index 0000000..e3908de --- /dev/null +++ b/src/samd/sample_init.cpp @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifdef ARDUINO_ARCH_SAMD + +#include +#include +#include +#include +#include +#include +#include +#include +#include "NTPClientAz.h" + +#ifdef ARDUINO_SAMD_FEATHER_M0 + +// Optional LIPO battery monitoring +#define VBAT_ENABLED 1 +#define VBAT_PIN A7 + +#define WINC_CS 8 +#define WINC_IRQ 7 +#define WINC_RST 4 +#define WINC_EN 2 + +#endif // ARDUINO_SAMD_FEATHER_M0 + + +static WiFiSSLClient sslClient; + + +static void initWifi(const char* ssid, const char* pass) +{ + #ifdef ARDUINO_SAMD_FEATHER_M0 + //Configure pins for Adafruit ATWINC1500 Feather + Serial.println(F("WINC1500 on FeatherM0 detected.")); + Serial.println(F("Setting pins for WiFi101 library (WINC1500 on FeatherM0)")); + WiFi.setPins(WINC_CS, WINC_IRQ, WINC_RST, WINC_EN); + // for the Adafruit WINC1500 we need to enable the chip + pinMode(WINC_EN, OUTPUT); + digitalWrite(WINC_EN, HIGH); + Serial.println(F("Enabled WINC1500 interface for FeatherM0")); + #endif + + // Attempt to connect to Wifi network: + int status = WL_IDLE_STATUS; + Serial.print("Attempting to connect to WPA SSID: "); + Serial.println(ssid); + + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + while ( status != WL_CONNECTED) + { + // Connect to WPA/WPA2 network: + status = WiFi.begin(ssid, pass); + Serial.print(" WiFi status: "); + Serial.println(status); + // wait 2 seconds to try again + delay(2000); + } + + Serial.println("\r\nConnected to wifi"); +} + +static void initTime() { + WiFiUDP _udp; + + time_t epochTime = (time_t)-1; + + NTPClientAz ntpClient; + Serial.println("Fetching NTP epoch time"); + ntpClient.begin(); + + while (true) { + epochTime = ntpClient.getEpochTime("0.pool.ntp.org"); + + if (epochTime == (time_t)-1) { + Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry."); + delay(2000); + } else { + Serial.print("Fetched NTP epoch time is: "); + Serial.println(epochTime); + break; + } + } + + ntpClient.end(); + + struct timeval tv; + tv.tv_sec = epochTime; + tv.tv_usec = 0; + + settimeofday(&tv, NULL); +} + +void m0_sample_init(const char* ssid, const char* password) +{ + // The Feather M0 loses it's COMn connection with every reset. + // This 10 s delay allows you to reselect the COM port and open the serial monitor window. + delay(10000); + Serial.begin(115200); + initWifi(ssid, password); + initTime(); +} + +#endif // ARDUINO_ARCH_SAMD diff --git a/src/samd/sample_init.h b/src/samd/sample_init.h new file mode 100644 index 0000000..9de648f --- /dev/null +++ b/src/samd/sample_init.h @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#ifndef SAMPLE_INIT_H +#define SAMPLE_INIT_H + +#define sample_init m0_sample_init + +void m0_sample_init(const char* ssid, const char* password); + +#endif // SAMPLE_INIT_H diff --git a/src/samd/stdio.cpp b/src/samd/stdio.cpp new file mode 100644 index 0000000..cb88ad9 --- /dev/null +++ b/src/samd/stdio.cpp @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if defined(ARDUINO_ARCH_SAMD) +#include + +#include "Arduino.h" + +// these are needed by the serializer, so force link +asm(".global _printf_float"); +asm(".global _scanf_float"); + +extern "C" { + size_t _write(int handle, const unsigned char *buf, size_t bufSize) + { + /* Check for the command to flush all handles */ + if (handle == -1) { + return 0; + } + + /* Check for stdout and stderr (only necessary if FILE descriptors are enabled.) */ + if (handle != 1 && handle != 2) { + return -1; + } + + size_t nChars = 0; + for (; bufSize > 0; --bufSize, ++buf, ++nChars) { + Serial.write(*buf); + } + return nChars; + } +} +#endif \ No newline at end of file diff --git a/src/samd/time.cpp b/src/samd/time.cpp new file mode 100644 index 0000000..a36df8d --- /dev/null +++ b/src/samd/time.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if defined(ARDUINO_ARCH_SAMD) +#include +#include + +#include + +RTCZero rtc; + +extern "C" { + int _gettimeofday(struct timeval* tp, void* /*tzvp*/) + { + tp->tv_sec = rtc.getEpoch(); + tp->tv_usec = 0; + + return 0; + } + + int settimeofday(const struct timeval* tp, const struct timezone* /*tzp*/) + { + rtc.begin(); + rtc.setEpoch(tp->tv_sec); + + return 0; + } +} +#endif \ No newline at end of file