Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
Revision 6:c55b013dfc2a, committed 2016-07-01
- Comitter:
- Azure.IoT Build
- Date:
- Fri Jul 01 10:43:23 2016 -0700
- Parent:
- 5:921351ce6973
- Child:
- 7:1af47e3a19b6
- Commit message:
- 1.0.10
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/azure_c_shared_utility/consolelogger.h Fri Jul 01 10:43:23 2016 -0700
@@ -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.
+
+#ifndef CONSOLELOGGER_H
+#define CONSOLELOGGER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "azure_c_shared_utility/xlogging.h"
+
+ extern void consolelogger_log(LOG_CATEGORY log_category, unsigned int options, const char* format, ...);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CONSOLELOGGER_H */
--- a/azure_c_shared_utility/httpapi.h Fri Jun 17 17:03:29 2016 -0700 +++ b/azure_c_shared_utility/httpapi.h Fri Jul 01 10:43:23 2016 -0700 @@ -47,6 +47,7 @@ HTTPAPI_ALLOC_FAILED, \ HTTPAPI_INIT_FAILED, \ HTTPAPI_INSUFFICIENT_RESPONSE_BUFFER, \ +HTTPAPI_SET_X509_FAILURE, \ HTTPAPI_SET_TIMEOUTS_FAILED \ /** @brief Enumeration specifying the possible return values for the APIs in
--- a/azure_c_shared_utility/iot_logging.h Fri Jun 17 17:03:29 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-#ifndef LOGGING_H
-#define LOGGING_H
-
-/*no logging is useful when time and fprintf are mocked*/
-#ifdef NO_LOGGING
-#define LogInfo(...)
-#define LogError(FORMAT, ...)
-#else
-
-#include <stdio.h>
-#include "azure_c_shared_utility/agenttime.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#define STRINGIFY(a) (#a)
-
-#define LOG_LINE 0x01
-
-//Adding a do while(0) to force the user to add ; after LogInfo and LogError.
-#if defined _MSC_VER
-#define LogInfo(FORMAT, ...) do{(void)fprintf(stdout,"Info: " FORMAT "\r\n", __VA_ARGS__); }while(0)
-#else
-#define LogInfo(FORMAT, ...) do{(void)fprintf(stdout,"Info: " FORMAT "\r\n", ##__VA_ARGS__); }while(0)
-#endif
-
-#if defined _MSC_VER
-#define LogError(FORMAT, ...) do{ time_t t = time(NULL); (void)fprintf(stderr,"Error: Time:%.24s File:%s Func:%s Line:%d " FORMAT "\r\n", ctime(&t), __FILE__, __FUNCDNAME__, __LINE__, __VA_ARGS__); }while(0)
-#else
-#define LogError(FORMAT, ...) do{ time_t t = time(NULL); (void)fprintf(stderr,"Error: Time:%.24s File:%s Func:%s Line:%d " FORMAT "\r\n", ctime(&t), __FILE__, __func__, __LINE__, ##__VA_ARGS__); }while(0)
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
-
-#endif /* LOGGING_H */
--- a/azure_c_shared_utility/socketio.h Fri Jun 17 17:03:29 2016 -0700 +++ b/azure_c_shared_utility/socketio.h Fri Jul 01 10:43:23 2016 -0700 @@ -24,7 +24,7 @@ #define RECEIVE_BYTES_VALUE 64 -MOCKABLE_FUNCTION(, CONCRETE_IO_HANDLE, socketio_create, void*, io_create_parameters, LOGGER_LOG, logger_log); +MOCKABLE_FUNCTION(, CONCRETE_IO_HANDLE, socketio_create, void*, io_create_parameters); MOCKABLE_FUNCTION(, void, socketio_destroy, CONCRETE_IO_HANDLE, socket_io); MOCKABLE_FUNCTION(, int, socketio_open, CONCRETE_IO_HANDLE, socket_io, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context); MOCKABLE_FUNCTION(, int, socketio_close, CONCRETE_IO_HANDLE, socket_io, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
--- a/azure_c_shared_utility/tlsio_wolfssl.h Fri Jun 17 17:03:29 2016 -0700 +++ b/azure_c_shared_utility/tlsio_wolfssl.h Fri Jul 01 10:43:23 2016 -0700 @@ -12,9 +12,9 @@ #endif /* __cplusplus */ #include "azure_c_shared_utility/xio.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" -extern CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters, LOGGER_LOG logger_log); +extern CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters); extern void tlsio_wolfssl_destroy(CONCRETE_IO_HANDLE tls_io); extern int tlsio_wolfssl_open(CONCRETE_IO_HANDLE tls_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context); extern int tlsio_wolfssl_close(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context);
--- a/azure_c_shared_utility/xio.h Fri Jun 17 17:03:29 2016 -0700
+++ b/azure_c_shared_utility/xio.h Fri Jul 01 10:43:23 2016 -0700
@@ -37,7 +37,7 @@
typedef void(*ON_IO_CLOSE_COMPLETE)(void* context);
typedef void(*ON_IO_ERROR)(void* context);
-typedef CONCRETE_IO_HANDLE(*IO_CREATE)(void* io_create_parameters, LOGGER_LOG logger_log);
+typedef CONCRETE_IO_HANDLE(*IO_CREATE)(void* io_create_parameters);
typedef void(*IO_DESTROY)(CONCRETE_IO_HANDLE concrete_io);
typedef int(*IO_OPEN)(CONCRETE_IO_HANDLE concrete_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context);
typedef int(*IO_CLOSE)(CONCRETE_IO_HANDLE concrete_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context);
@@ -56,7 +56,7 @@
IO_SETOPTION concrete_io_setoption;
} IO_INTERFACE_DESCRIPTION;
-MOCKABLE_FUNCTION(, XIO_HANDLE, xio_create, const IO_INTERFACE_DESCRIPTION*, io_interface_description, const void*, io_create_parameters, LOGGER_LOG, logger_log);
+MOCKABLE_FUNCTION(, XIO_HANDLE, xio_create, const IO_INTERFACE_DESCRIPTION*, io_interface_description, const void*, io_create_parameters);
MOCKABLE_FUNCTION(, void, xio_destroy, XIO_HANDLE, xio);
MOCKABLE_FUNCTION(, int, xio_open, XIO_HANDLE, xio, ON_IO_OPEN_COMPLETE, on_io_open_complete, void*, on_io_open_complete_context, ON_BYTES_RECEIVED, on_bytes_received, void*, on_bytes_received_context, ON_IO_ERROR, on_io_error, void*, on_io_error_context);
MOCKABLE_FUNCTION(, int, xio_close, XIO_HANDLE, xio, ON_IO_CLOSE_COMPLETE, on_io_close_complete, void*, callback_context);
--- a/azure_c_shared_utility/xlogging.h Fri Jun 17 17:03:29 2016 -0700
+++ b/azure_c_shared_utility/xlogging.h Fri Jul 01 10:43:23 2016 -0700
@@ -3,17 +3,56 @@
#ifndef XLOGGING_H
#define XLOGGING_H
-#include <stdio.h>
#ifdef __cplusplus
+#include <cstdio>
extern "C" {
+#else
+#include <stdio.h>
#endif /* __cplusplus */
-typedef void(*LOGGER_LOG)(unsigned int options, char* format, ...);
+#include "azure_c_shared_utility/agenttime.h"
+
+/*no logging is useful when time and fprintf are mocked*/
+#ifdef NO_LOGGING
+#define LOG(...)
+#define LogInfo(...)
+#define LogError(...)
+#define xlogging_get_log_function() NULL
+#else
+
+typedef enum LOG_CATEGORY_TAG
+{
+ LOG_ERROR,
+ LOG_INFO,
+ LOG_TRACE
+} LOG_CATEGORY;
+
+typedef void(*LOGGER_LOG)(LOG_CATEGORY log_category, unsigned int options, const char* format, ...);
#define LOG_LINE 0x01
-#define LOG(logger, ...) if (logger != NULL) logger(__VA_ARGS__)
+#if defined _MSC_VER
+#define LOG(log_category, log_options, format, ...) { LOGGER_LOG l = xlogging_get_log_function(); if (l != NULL) l(log_category, log_options, format, __VA_ARGS__); }
+#else
+#define LOG(log_category, log_options, format, ...) { LOGGER_LOG l = xlogging_get_log_function(); if (l != NULL) l(log_category, log_options, format, ##__VA_ARGS__); }
+#endif
+
+#if defined _MSC_VER
+#define LogInfo(FORMAT, ...) do{LOG(LOG_INFO, LOG_LINE, "Info: " FORMAT, __VA_ARGS__); }while(0)
+#else
+#define LogInfo(FORMAT, ...) do{LOG(LOG_INFO, LOG_LINE, "Info: " FORMAT, ##__VA_ARGS__); }while(0)
+#endif
+
+#if defined _MSC_VER
+#define LogError(FORMAT, ...) do{ time_t t = time(NULL); LOG(LOG_ERROR, LOG_LINE, "Error: Time:%.24s File:%s Func:%s Line:%d " FORMAT, ctime(&t), __FILE__, __FUNCDNAME__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define LogError(FORMAT, ...) do{ time_t t = time(NULL); LOG(LOG_ERROR, LOG_LINE, "Error: Time:%.24s File:%s Func:%s Line:%d " FORMAT, ctime(&t), __FILE__, __func__, __LINE__, ##__VA_ARGS__); }while(0)
+#endif
+
+extern void xlogging_set_log_function(LOGGER_LOG log_function);
+extern LOGGER_LOG xlogging_get_log_function(void);
+#endif
#ifdef __cplusplus
}
--- a/base64.c Fri Jun 17 17:03:29 2016 -0700
+++ b/base64.c Fri Jul 01 10:43:23 2016 -0700
@@ -16,7 +16,7 @@
// PUT NO CLIENT LIBRARY INCLUDES BEFORE HERE !!!!
//
#include "azure_c_shared_utility/base64.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
static const char base64char[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
--- a/buffer.c Fri Jun 17 17:03:29 2016 -0700
+++ b/buffer.c Fri Jul 01 10:43:23 2016 -0700
@@ -17,7 +17,7 @@
//
#include "azure_c_shared_utility/buffer_.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
typedef struct BUFFER_TAG
{
--- a/condition_rtx_mbed.cpp Fri Jun 17 17:03:29 2016 -0700
+++ b/condition_rtx_mbed.cpp Fri Jul 01 10:43:23 2016 -0700
@@ -7,9 +7,9 @@
#endif
#include "azure_c_shared_utility/lock.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/condition.h"
#include "rtos.h"
-#include "azure_c_shared_utility/condition.h"
COND_HANDLE Condition_Init(void)
{
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/consolelogger.c Fri Jul 01 10:43:23 2016 -0700
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#ifdef _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include "azure_c_shared_utility/xlogging.h"
+
+void consolelogger_log(LOG_CATEGORY log_category,unsigned int options, const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ (void)vprintf(format, args);
+ va_end(args);
+
+ (void)log_category;
+ if (options & LOG_LINE)
+ {
+ (void)printf("\r\n");
+ }
+}
--- a/constbuffer.c Fri Jun 17 17:03:29 2016 -0700 +++ b/constbuffer.c Fri Jul 01 10:43:23 2016 -0700 @@ -11,7 +11,7 @@ #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/constbuffer.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/refcount.h" typedef struct CONSTBUFFER_HANDLE_DATA_TAG
--- a/constmap.c Fri Jun 17 17:03:29 2016 -0700 +++ b/constmap.c Fri Jul 01 10:43:23 2016 -0700 @@ -9,7 +9,7 @@ #include "azure_c_shared_utility/map.h" #include "azure_c_shared_utility/constmap.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/refcount.h" DEFINE_ENUM_STRINGS(CONSTMAP_RESULT, CONSTMAP_RESULT_VALUES);
--- a/crt_abstractions.c Fri Jun 17 17:03:29 2016 -0700
+++ b/crt_abstractions.c Fri Jul 01 10:43:23 2016 -0700
@@ -264,14 +264,16 @@
else
{
size_t l = strlen(source);
- *destination = (char*)malloc(l + 1);
+ char* temp = (char*)malloc(l + 1);
+
/*Codes_SRS_CRT_ABSTRACTIONS_99_037: [Upon failure to allocate memory for the destination, the function will return ENOMEM.]*/
- if (*destination == NULL)
+ if (temp == NULL)
{
result = ENOMEM;
}
else
{
+ *destination = temp;
/*Codes_SRS_CRT_ABSTRACTIONS_99_039: [mallocAndstrcpy_s shall copy the contents in the address source, including the terminating null character into location specified by the destination pointer after the memory allocation.]*/
int temp = strcpy_s(*destination, l + 1, source);
if (temp < 0) /*strcpy_s error*/
--- a/gballoc.c Fri Jun 17 17:03:29 2016 -0700 +++ b/gballoc.c Fri Jul 01 10:43:23 2016 -0700 @@ -7,7 +7,7 @@ #endif #include "azure_c_shared_utility/lock.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include <stdint.h> #ifndef SIZE_MAX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/httpapi_compact.c Fri Jul 01 10:43:23 2016 -0700
@@ -0,0 +1,800 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#include <stdlib.h>
+#ifdef _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "azure_c_shared_utility/httpapi.h"
+#include "azure_c_shared_utility/httpheaders.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/xio.h"
+#include "azure_c_shared_utility/platform.h"
+#include "azure_c_shared_utility/tlsio.h"
+#include "azure_c_shared_utility/threadapi.h"
+#include <string.h>
+
+#define MAX_HOSTNAME 64
+#define TEMP_BUFFER_SIZE 4096
+
+#define CHAR_COUNT(A) (sizeof(A) - 1)
+
+DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
+
+typedef enum SEND_ALL_RESULT_TAG
+{
+ SEND_ALL_RESULT_NOT_STARTED,
+ SEND_ALL_RESULT_PENDING,
+ SEND_ALL_RESULT_OK,
+ SEND_ALL_RESULT_ERROR
+} SEND_ALL_RESULT;
+
+typedef struct HTTP_HANDLE_DATA_TAG
+{
+ char host[MAX_HOSTNAME];
+ char* certificate;
+ XIO_HANDLE xio_handle;
+ size_t received_bytes_count;
+ unsigned char* received_bytes;
+ SEND_ALL_RESULT send_all_result;
+ unsigned int is_io_error : 1;
+ unsigned int is_connected : 1;
+} HTTP_HANDLE_DATA;
+
+HTTPAPI_RESULT HTTPAPI_Init(void)
+{
+ return HTTPAPI_OK;
+}
+
+void HTTPAPI_Deinit(void)
+{
+}
+
+HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName)
+{
+ HTTP_HANDLE_DATA* handle = NULL;
+
+ if (hostName)
+ {
+ handle = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
+ if (handle != NULL)
+ {
+ if (strcpy_s(handle->host, MAX_HOSTNAME, hostName) != 0)
+ {
+ LogError("HTTPAPI_CreateConnection::Could not strcpy_s");
+ free(handle);
+ handle = NULL;
+ }
+ else
+ {
+ TLSIO_CONFIG tlsio_config = { hostName, 443 };
+ handle->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
+ if (handle->xio_handle == NULL)
+ {
+ LogError("HTTPAPI_CreateConnection::xio_create failed");
+ free(handle->host);
+ free(handle);
+ handle = NULL;
+ }
+ else
+ {
+ handle->is_connected = 0;
+ handle->is_io_error = 0;
+ handle->received_bytes_count = 0;
+ handle->received_bytes = NULL;
+ handle->send_all_result = SEND_ALL_RESULT_NOT_STARTED;
+ handle->certificate = NULL;
+ }
+ }
+ }
+ }
+ else
+ {
+ LogInfo("HTTPAPI_CreateConnection:: null hostName parameter");
+ }
+
+ return (HTTP_HANDLE)handle;
+}
+
+void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
+{
+ HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
+
+ if (h)
+ {
+ if (h->xio_handle != NULL)
+ {
+ LogInfo("HTTPAPI_CloseConnection xio_destroy(); to %s", h->host);
+ xio_destroy(h->xio_handle);
+ }
+
+ if (h->certificate)
+ {
+ free(h->certificate);
+ }
+
+ free(h);
+ }
+}
+
+static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
+{
+ HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
+ if (open_result == IO_OPEN_OK)
+ {
+ h->is_connected = 1;
+ h->is_io_error = 0;
+ }
+ else
+ {
+ h->is_io_error = 1;
+ }
+}
+
+static int my_strnicmp(const char* s1, const char* s2, size_t n)
+{
+ size_t i;
+ int result = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ /* compute the difference between the chars */
+ result = tolower(s1[i]) - tolower(s2[i]);
+
+ /* break if we have a difference ... */
+ if ((result != 0) ||
+ /* ... or if we got to the end of one the strings */
+ (s1[i] == '\0') || (s2[i] == '\0'))
+ {
+ break;
+ }
+ }
+
+ return result;
+}
+
+static int my_stricmp(const char* s1, const char* s2)
+{
+ size_t i = 0;
+
+ while ((s1[i] != '\0') && (s2[i] != '\0'))
+ {
+ /* break if we have a difference ... */
+ if (tolower(s1[i]) != tolower(s2[i]))
+ {
+ break;
+ }
+
+ i++;
+ }
+
+ /* if we broke because we are at end of string this will yield 0 */
+ /* if we broke because there was a difference this will yield non-zero */
+ return tolower(s1[i]) - tolower(s2[i]);
+}
+
+static void on_bytes_received(void* context, const unsigned char* buffer, size_t size)
+{
+ HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
+
+ /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */
+ unsigned char* new_received_bytes = (unsigned char*)realloc(h->received_bytes, h->received_bytes_count + size);
+ if (new_received_bytes == NULL)
+ {
+ h->is_io_error = 1;
+ LogError("on_bytes_received: Error allocating memory for received data");
+ }
+ else
+ {
+ h->received_bytes = new_received_bytes;
+ (void)memcpy(h->received_bytes + h->received_bytes_count, buffer, size);
+ h->received_bytes_count += size;
+ }
+}
+
+static void on_io_error(void* context)
+{
+ HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
+ h->is_io_error = 1;
+ LogError("on_io_error: Error signalled by underlying IO");
+}
+
+static int conn_receive(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
+{
+ int result = 0;
+
+ if (count < 0)
+ {
+ result = -1;
+ }
+ else
+ {
+ while (result < count)
+ {
+ xio_dowork(http_instance->xio_handle);
+
+ /* if any error was detected while receiving then simply break and report it */
+ if (http_instance->is_io_error != 0)
+ {
+ result = -1;
+ break;
+ }
+
+ if (http_instance->received_bytes_count >= (size_t)count)
+ {
+ /* Consuming bytes from the receive buffer */
+ (void)memcpy(buffer, http_instance->received_bytes, count);
+ (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
+ http_instance->received_bytes_count -= count;
+
+ /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
+ if (http_instance->received_bytes_count == 0)
+ {
+ free(http_instance->received_bytes);
+ http_instance->received_bytes = NULL;
+ }
+
+ result = count;
+ break;
+ }
+
+ ThreadAPI_Sleep(1);
+ }
+ }
+
+ return result;
+}
+
+static void on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+ /* If a send is complete we'll simply signal this by changing the send all state */
+ HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+ if (send_result == IO_SEND_OK)
+ {
+ http_instance->send_all_result = SEND_ALL_RESULT_OK;
+ }
+ else
+ {
+ http_instance->send_all_result = SEND_ALL_RESULT_ERROR;
+ }
+}
+
+static int conn_send_all(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
+{
+ int result;
+
+ if (count < 0)
+ {
+ result = -1;
+ }
+ else
+ {
+ http_instance->send_all_result = SEND_ALL_RESULT_PENDING;
+ if (xio_send(http_instance->xio_handle, buffer, count, on_send_complete, http_instance) != 0)
+ {
+ result = -1;
+ }
+ else
+ {
+ /* We have to loop in here until all bytes are sent or we encounter an error. */
+ while (1)
+ {
+ xio_dowork(http_instance->xio_handle);
+
+ /* If we got an error signalled from the underlying IO we simply report it up */
+ if (http_instance->is_io_error)
+ {
+ http_instance->send_all_result = SEND_ALL_RESULT_ERROR;
+ break;
+ }
+
+ if (http_instance->send_all_result != SEND_ALL_RESULT_PENDING)
+ {
+ break;
+ }
+
+ /* We yield the CPU for a bit so others can do their work */
+ ThreadAPI_Sleep(1);
+ }
+
+ /* The send_all_result indicates what is the status for the send operation.
+ Not started - means nothing should happen since no send was started
+ Pending - a send was started, but it is still being carried out
+ Ok - Send complete
+ Error - error */
+ switch (http_instance->send_all_result)
+ {
+ default:
+ case SEND_ALL_RESULT_NOT_STARTED:
+ result = -1;
+ break;
+
+ case SEND_ALL_RESULT_OK:
+ result = count;
+ break;
+
+ case SEND_ALL_RESULT_ERROR:
+ result = -1;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+static int readLine(HTTP_HANDLE_DATA* http_instance, char* buf, const size_t size)
+{
+ // reads until \r\n is encountered. writes in buf all the characters
+ char* p = buf;
+ char c;
+ if (conn_receive(http_instance, &c, 1) < 0)
+ return -1;
+ while (c != '\r') {
+ if ((p - buf + 1) >= (int)size)
+ return -1;
+ *p++ = c;
+ if (conn_receive(http_instance, &c, 1) < 0)
+ return -1;
+ }
+ *p = 0;
+ if (conn_receive(http_instance, &c, 1) < 0 || c != '\n') // skip \n
+ return -1;
+ return p - buf;
+}
+
+static int readChunk(HTTP_HANDLE_DATA* http_instance, char* buf, size_t size)
+{
+ size_t cur, offset;
+
+ // read content with specified length, even if it is received
+ // only in chunks due to fragmentation in the networking layer.
+ // returns -1 in case of error.
+ offset = 0;
+ while (size > 0)
+ {
+ cur = conn_receive(http_instance, buf + offset, size);
+
+ // end of stream reached
+ if (cur == 0)
+ return offset;
+
+ // read cur bytes (might be less than requested)
+ size -= cur;
+ offset += cur;
+ }
+
+ return offset;
+}
+
+static int skipN(HTTP_HANDLE_DATA* http_instance, size_t n, char* buf, size_t size)
+{
+ size_t org = n;
+ // read and abandon response content with specified length
+ // returns -1 in case of error.
+ while (n > size)
+ {
+ if (readChunk(http_instance, (char*)buf, size) < 0)
+ return -1;
+
+ n -= size;
+ }
+
+ if (readChunk(http_instance, (char*)buf, n) < 0)
+ return -1;
+
+ return org;
+}
+
+//Note: This function assumes that "Host:" and "Content-Length:" headers are setup
+// by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c).
+HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
+ HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
+ size_t contentLength, unsigned int* statusCode,
+ HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
+{
+
+ HTTPAPI_RESULT result;
+ size_t headersCount;
+ char buf[TEMP_BUFFER_SIZE];
+ int ret;
+ size_t bodyLength = 0;
+ bool chunked = false;
+ const unsigned char* receivedContent;
+
+ const char* method = (requestType == HTTPAPI_REQUEST_GET) ? "GET"
+ : (requestType == HTTPAPI_REQUEST_POST) ? "POST"
+ : (requestType == HTTPAPI_REQUEST_PUT) ? "PUT"
+ : (requestType == HTTPAPI_REQUEST_DELETE) ? "DELETE"
+ : (requestType == HTTPAPI_REQUEST_PATCH) ? "PATCH"
+ : NULL;
+
+ if (handle == NULL ||
+ relativePath == NULL ||
+ httpHeadersHandle == NULL ||
+ method == NULL ||
+ HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
+ {
+ result = HTTPAPI_INVALID_ARG;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
+
+ if (handle->is_connected == 0)
+ {
+ // Load the certificate
+ if ((httpHandle->certificate != NULL) &&
+ (xio_setoption(httpHandle->xio_handle, "TrustedCerts", httpHandle->certificate) != 0))
+ {
+ result = HTTPAPI_ERROR;
+ LogError("Could not load certificate (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ // Make the connection
+ if (xio_open(httpHandle->xio_handle, on_io_open_complete, httpHandle, on_bytes_received, httpHandle, on_io_error, httpHandle) != 0)
+ {
+ result = HTTPAPI_ERROR;
+ LogError("Could not connect (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ while (1)
+ {
+ xio_dowork(httpHandle->xio_handle);
+ if ((handle->is_connected == 1) ||
+ (handle->is_io_error == 1))
+ {
+ break;
+ }
+
+ ThreadAPI_Sleep(1);
+ }
+ }
+
+ //Send request
+ if ((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, relativePath)) < 0
+ || ret >= sizeof(buf))
+ {
+ result = HTTPAPI_STRING_PROCESSING_ERROR;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ if (conn_send_all(httpHandle, buf, strlen(buf)) < 0)
+ {
+ result = HTTPAPI_SEND_REQUEST_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ //Send default headers
+ for (size_t i = 0; i < headersCount; i++)
+ {
+ char* header;
+ if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
+ {
+ result = HTTPAPI_HTTP_HEADERS_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ if (conn_send_all(httpHandle, header, strlen(header)) < 0)
+ {
+ result = HTTPAPI_SEND_REQUEST_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ free(header);
+ goto exit;
+ }
+ if (conn_send_all(httpHandle, "\r\n", 2) < 0)
+ {
+ result = HTTPAPI_SEND_REQUEST_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ free(header);
+ goto exit;
+ }
+ free(header);
+ }
+
+ //Close headers
+ if (conn_send_all(httpHandle, "\r\n", 2) < 0)
+ {
+ result = HTTPAPI_SEND_REQUEST_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ //Send data (if available)
+ if (content && contentLength > 0)
+ {
+ if (conn_send_all(httpHandle, (char*)content, contentLength) < 0)
+ {
+ result = HTTPAPI_SEND_REQUEST_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ }
+
+ //Receive response
+ if (readLine(httpHandle, buf, sizeof(buf)) < 0)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ //Parse HTTP response
+ if (sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) != 1)
+ {
+ //Cannot match string, error
+ LogInfo("HTTPAPI_ExecuteRequest::Not a correct HTTP answer=%s", buf);
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ if (statusCode)
+ *statusCode = ret;
+
+ //Read HTTP response headers
+ if (readLine(httpHandle, buf, sizeof(buf)) < 0)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ while (buf[0])
+ {
+ const char ContentLength[] = "content-length:";
+ const char TransferEncoding[] = "transfer-encoding:";
+
+ if (my_strnicmp(buf, ContentLength, CHAR_COUNT(ContentLength)) == 0)
+ {
+ if (sscanf(buf + CHAR_COUNT(ContentLength), " %d", &bodyLength) != 1)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ }
+ else if (my_strnicmp(buf, TransferEncoding, CHAR_COUNT(TransferEncoding)) == 0)
+ {
+ const char* p = buf + CHAR_COUNT(TransferEncoding);
+ while (isspace(*p)) p++;
+ if (my_stricmp(p, "chunked") == 0)
+ chunked = true;
+ }
+
+ char* whereIsColon = strchr((char*)buf, ':');
+ if (whereIsColon && responseHeadersHandle != NULL)
+ {
+ *whereIsColon = '\0';
+ HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
+ }
+
+ if (readLine(httpHandle, buf, sizeof(buf)) < 0)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ }
+
+ //Read HTTP response body
+ if (!chunked)
+ {
+ if (bodyLength)
+ {
+ if (responseContent != NULL)
+ {
+ if (BUFFER_pre_build(responseContent, bodyLength) != 0)
+ {
+ result = HTTPAPI_ALLOC_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ }
+ else if (BUFFER_content(responseContent, &receivedContent) != 0)
+ {
+ (void)BUFFER_unbuild(responseContent);
+
+ result = HTTPAPI_ALLOC_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ }
+
+ if (readChunk(httpHandle, (char*)receivedContent, bodyLength) < 0)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ else
+ {
+ result = HTTPAPI_OK;
+ }
+ }
+ else
+ {
+ (void)skipN(httpHandle, bodyLength, buf, sizeof(buf));
+ result = HTTPAPI_OK;
+ }
+ }
+ else
+ {
+ result = HTTPAPI_OK;
+ }
+ }
+ else
+ {
+ size_t size = 0;
+ result = HTTPAPI_OK;
+ for (;;)
+ {
+ int chunkSize;
+ if (readLine(httpHandle, buf, sizeof(buf)) < 0) // read [length in hex]/r/n
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ if (sscanf(buf, "%x", &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted)
+ {
+ //Cannot match string, error
+ result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+
+ if (chunkSize == 0)
+ {
+ // 0 length means next line is just '\r\n' and end of chunks
+ if (readChunk(httpHandle, (char*)buf, 2) < 0
+ || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+ {
+ (void)BUFFER_unbuild(responseContent);
+
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ break;
+ }
+ else
+ {
+ if (responseContent != NULL)
+ {
+ if (BUFFER_enlarge(responseContent, chunkSize) != 0)
+ {
+ (void)BUFFER_unbuild(responseContent);
+
+ result = HTTPAPI_ALLOC_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ }
+ else if (BUFFER_content(responseContent, &receivedContent) != 0)
+ {
+ (void)BUFFER_unbuild(responseContent);
+
+ result = HTTPAPI_ALLOC_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ }
+
+ if (readChunk(httpHandle, (char*)receivedContent + size, chunkSize) < 0)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ }
+ else
+ {
+ if (skipN(httpHandle, chunkSize, buf, sizeof(buf)) < 0)
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ }
+
+ if (readChunk(httpHandle, (char*)buf, 2) < 0
+ || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+ {
+ result = HTTPAPI_READ_DATA_FAILED;
+ LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+ goto exit;
+ }
+ size += chunkSize;
+ }
+ }
+
+ }
+
+exit:
+ if ((handle != NULL) &&
+ (handle->is_io_error != 0))
+ {
+ xio_close(handle->xio_handle, NULL, NULL);
+ handle->is_connected = 0;
+ }
+
+ return result;
+}
+
+HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
+{
+ HTTPAPI_RESULT result;
+ if (
+ (handle == NULL) ||
+ (optionName == NULL) ||
+ (value == NULL)
+ )
+ {
+ result = HTTPAPI_INVALID_ARG;
+ LogError("invalid parameter (NULL) passed to HTTPAPI_SetOption");
+ }
+ else if (strcmp("TrustedCerts", optionName) == 0)
+ {
+ HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
+ if (h->certificate)
+ {
+ free(h->certificate);
+ }
+
+ int len = strlen((char*)value);
+ h->certificate = (char*)malloc(len + 1);
+ if (h->certificate == NULL)
+ {
+ result = HTTPAPI_ERROR;
+ LogError("unable to allocate certificate memory in HTTPAPI_SetOption");
+ }
+ else
+ {
+ (void)strcpy(h->certificate, (const char*)value);
+ result = HTTPAPI_OK;
+ }
+ }
+ else
+ {
+ result = HTTPAPI_INVALID_ARG;
+ LogError("unknown option %s", optionName);
+ }
+ return result;
+}
+
+HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue)
+{
+ HTTPAPI_RESULT result;
+ if (
+ (optionName == NULL) ||
+ (value == NULL) ||
+ (savedValue == NULL)
+ )
+ {
+ result = HTTPAPI_INVALID_ARG;
+ LogError("invalid argument(NULL) passed to HTTPAPI_CloneOption");
+ }
+ else if (strcmp("TrustedCerts", optionName) == 0)
+ {
+ size_t certLen = strlen((const char*)value);
+ char* tempCert = (char*)malloc(certLen+1);
+ if (tempCert == NULL)
+ {
+ result = HTTPAPI_INVALID_ARG;
+ LogError("unable to allocate certificate memory in HTTPAPI_CloneOption");
+ }
+ else
+ {
+ (void)strcpy(tempCert, (const char*)value);
+ *savedValue = tempCert;
+ result = HTTPAPI_OK;
+ }
+ }
+ else
+ {
+ result = HTTPAPI_INVALID_ARG;
+ LogError("unknown option %s", optionName);
+ }
+ return result;
+}
--- a/httpapi_mbed.cpp Fri Jun 17 17:03:29 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,551 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-#include <cstdlib>
-#ifdef _CRTDBG_MAP_ALLOC
-#include <crtdbg.h>
-#endif
-
-#include <cstdio>
-#include <cstdlib>
-#include <cctype>
-#include "azure_c_shared_utility/httpapi.h"
-#include "azure_c_shared_utility/httpheaders.h"
-#include "azure_c_shared_utility/crt_abstractions.h"
-#include "mbed.h"
-#include "EthernetInterface.h"
-#include "azure_c_shared_utility/wolfssl_connection.h"
-#include "azure_c_shared_utility/iot_logging.h"
-#include <string.h>
-
-#define MAX_HOSTNAME 64
-#define TEMP_BUFFER_SIZE 4096
-
-#define CHAR_COUNT(A) (sizeof(A) - 1)
-
-DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
-
-class HTTP_HANDLE_DATA
-{
-public:
- char host[MAX_HOSTNAME];
- char* certificate;
- WolfSSLConnection con;
-};
-
-HTTPAPI_RESULT HTTPAPI_Init(void)
-{
- time_t ctTime;
- ctTime = time(NULL);
- HTTPAPI_RESULT result;
- LogInfo("HTTAPI_Init::Time is now (UTC) %s", ctime(&ctTime));
-
- result = HTTPAPI_OK;
-
- return result;
-}
-
-void HTTPAPI_Deinit(void)
-{
- ;
-}
-
-HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName)
-{
- HTTP_HANDLE_DATA* handle = NULL;
-
- if (hostName)
- {
- handle = new HTTP_HANDLE_DATA();
- if (strcpy_s(handle->host, MAX_HOSTNAME, hostName) != 0)
- {
- LogError("HTTPAPI_CreateConnection::Could not strcpy_s");
- delete handle;
- handle = NULL;
- }
- else
- {
- handle->certificate = NULL;
- }
- }
- else
- {
- LogInfo("HTTPAPI_CreateConnection:: null hostName parameter");
- }
-
- return (HTTP_HANDLE)handle;
-}
-
-void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
-{
- HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
-
- if (h)
- {
- if (h->con.is_connected())
- {
- LogInfo("HTTPAPI_CloseConnection h->con.close(); to %s", h->host);
- h->con.close();
- }
- if (h->certificate)
- {
- delete[] h->certificate;
- }
- delete h;
- }
-}
-
-static int readLine(WolfSSLConnection* con, char* buf, const size_t size)
-{
- // reads until \r\n is encountered. writes in buf all the characters
- // read until \r\n and returns the number of characters in the buffer.
- char* p = buf;
- char c;
- if (con->receive(&c, 1) < 0)
- return -1;
- while (c != '\r') {
- if ((p - buf + 1) >= (int)size)
- return -1;
- *p++ = c;
- if (con->receive(&c, 1) < 0)
- return -1;
- }
- *p = 0;
- if (con->receive(&c, 1) < 0 || c != '\n') // skip \n
- return -1;
- return p - buf;
-}
-
-static int readChunk(WolfSSLConnection* con, char* buf, size_t size)
-{
- size_t cur, offset;
-
- // read content with specified length, even if it is received
- // only in chunks due to fragmentation in the networking layer.
- // returns -1 in case of error.
- offset = 0;
- while (size > 0)
- {
- cur = con->receive(buf + offset, size);
-
- // end of stream reached
- if (cur == 0)
- return offset;
-
- // read cur bytes (might be less than requested)
- size -= cur;
- offset += cur;
- }
-
- return offset;
-}
-
-static int skipN(WolfSSLConnection* con, size_t n, char* buf, size_t size)
-{
- size_t org = n;
- // read and abandon response content with specified length
- // returns -1 in case of error.
- while (n > size)
- {
- if (readChunk(con, (char*)buf, size) < 0)
- return -1;
-
- n -= size;
- }
-
- if (readChunk(con, (char*)buf, n) < 0)
- return -1;
-
- return org;
-}
-
-//Note: This function assumes that "Host:" and "Content-Length:" headers are setup
-// by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c).
-HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
- HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
- size_t contentLength, unsigned int* statusCode,
- HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
-{
-
- HTTPAPI_RESULT result;
- size_t headersCount;
- char buf[TEMP_BUFFER_SIZE];
- int ret;
- WolfSSLConnection* con = NULL;
- size_t bodyLength = 0;
- bool chunked = false;
- const unsigned char* receivedContent;
-
- const char* method = (requestType == HTTPAPI_REQUEST_GET) ? "GET"
- : (requestType == HTTPAPI_REQUEST_POST) ? "POST"
- : (requestType == HTTPAPI_REQUEST_PUT) ? "PUT"
- : (requestType == HTTPAPI_REQUEST_DELETE) ? "DELETE"
- : (requestType == HTTPAPI_REQUEST_PATCH) ? "PATCH"
- : NULL;
-
- if (handle == NULL ||
- relativePath == NULL ||
- httpHeadersHandle == NULL ||
- method == NULL ||
- HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
- {
- result = HTTPAPI_INVALID_ARG;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
- con = &(httpHandle->con);
-
- if (!con->is_connected())
- {
- // Load the certificate
- if ((httpHandle->certificate != NULL) &&
- (!con->load_certificate((const unsigned char*)httpHandle->certificate, strlen(httpHandle->certificate) + 1)))
- {
- result = HTTPAPI_ERROR;
- LogError("Could not load certificate (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- // Make the connection
- if (con->connect(httpHandle->host, 443) != 0)
- {
- result = HTTPAPI_ERROR;
- LogError("Could not connect (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- }
-
- //Send request
- if ((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, relativePath)) < 0
- || ret >= sizeof(buf))
- {
- result = HTTPAPI_STRING_PROCESSING_ERROR;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- if (con->send_all(buf, strlen(buf)) < 0)
- {
- result = HTTPAPI_SEND_REQUEST_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- //Send default headers
- for (size_t i = 0; i < headersCount; i++)
- {
- char* header;
- if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
- {
- result = HTTPAPI_HTTP_HEADERS_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- if (con->send_all(header, strlen(header)) < 0)
- {
- result = HTTPAPI_SEND_REQUEST_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- free(header);
- goto exit;
- }
- if (con->send_all("\r\n", 2) < 0)
- {
- result = HTTPAPI_SEND_REQUEST_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- free(header);
- goto exit;
- }
- free(header);
- }
-
- //Close headers
- if (con->send_all("\r\n", 2) < 0)
- {
- result = HTTPAPI_SEND_REQUEST_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- //Send data (if available)
- if (content && contentLength > 0)
- {
- if (con->send_all((char*)content, contentLength) < 0)
- {
- result = HTTPAPI_SEND_REQUEST_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- }
-
- //Receive response
- if (readLine(con, buf, sizeof(buf)) < 0)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- //Parse HTTP response
- if (sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) != 1)
- {
- //Cannot match string, error
- LogInfo("HTTPAPI_ExecuteRequest::Not a correct HTTP answer=%s", buf);
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- if (statusCode)
- *statusCode = ret;
-
- //Read HTTP response headers
- if (readLine(con, buf, sizeof(buf)) < 0)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- while (buf[0])
- {
- const char ContentLength[] = "content-length:";
- const char TransferEncoding[] = "transfer-encoding:";
-
- if (strncasecmp(buf, ContentLength, CHAR_COUNT(ContentLength)) == 0)
- {
- if (sscanf(buf + CHAR_COUNT(ContentLength), " %d", &bodyLength) != 1)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- }
- else if (strncasecmp(buf, TransferEncoding, CHAR_COUNT(TransferEncoding)) == 0)
- {
- const char* p = buf + CHAR_COUNT(TransferEncoding);
- while (isspace(*p)) p++;
- if (strcasecmp(p, "chunked") == 0)
- chunked = true;
- }
-
- char* whereIsColon = strchr((char*)buf, ':');
- if (whereIsColon && responseHeadersHandle != NULL)
- {
- *whereIsColon = '\0';
- HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
- }
-
- if (readLine(con, buf, sizeof(buf)) < 0)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- }
-
- //Read HTTP response body
- if (!chunked)
- {
- if (bodyLength)
- {
- if (responseContent != NULL)
- {
- if (BUFFER_pre_build(responseContent, bodyLength) != 0)
- {
- result = HTTPAPI_ALLOC_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- }
- else if (BUFFER_content(responseContent, &receivedContent) != 0)
- {
- (void)BUFFER_unbuild(responseContent);
-
- result = HTTPAPI_ALLOC_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- }
-
- if (readChunk(con, (char*)receivedContent, bodyLength) < 0)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- else
- {
- result = HTTPAPI_OK;
- }
- }
- else
- {
- (void)skipN(con, bodyLength, buf, sizeof(buf));
- result = HTTPAPI_OK;
- }
- }
- else
- {
- result = HTTPAPI_OK;
- }
- }
- else
- {
- size_t size = 0;
- result = HTTPAPI_OK;
- for (;;)
- {
- int chunkSize;
- if (readLine(con, buf, sizeof(buf)) < 0) // read [length in hex]/r/n
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- if (sscanf(buf, "%x", &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted)
- {
- //Cannot match string, error
- result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
-
- if (chunkSize == 0)
- {
- // 0 length means next line is just '\r\n' and end of chunks
- if (readChunk(con, (char*)buf, 2) < 0
- || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
- {
- (void)BUFFER_unbuild(responseContent);
-
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- break;
- }
- else
- {
- if (responseContent != NULL)
- {
- if (BUFFER_enlarge(responseContent, chunkSize) != 0)
- {
- (void)BUFFER_unbuild(responseContent);
-
- result = HTTPAPI_ALLOC_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- }
- else if (BUFFER_content(responseContent, &receivedContent) != 0)
- {
- (void)BUFFER_unbuild(responseContent);
-
- result = HTTPAPI_ALLOC_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- }
-
- if (readChunk(con, (char*)receivedContent + size, chunkSize) < 0)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- }
- else
- {
- if (skipN(con, chunkSize, buf, sizeof(buf)) < 0)
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- }
-
- if (readChunk(con, (char*)buf, 2) < 0
- || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
- {
- result = HTTPAPI_READ_DATA_FAILED;
- LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
- goto exit;
- }
- size += chunkSize;
- }
- }
-
- }
-
-exit:
- return result;
-}
-
-HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
-{
- HTTPAPI_RESULT result;
- if (
- (handle == NULL) ||
- (optionName == NULL) ||
- (value == NULL)
- )
- {
- result = HTTPAPI_INVALID_ARG;
- LogError("invalid parameter (NULL) passed to HTTPAPI_SetOption");
- }
- else if (strcmp("TrustedCerts", optionName) == 0)
- {
- HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
- if (h->certificate)
- {
- delete[] h->certificate;
- }
-
- int len = strlen((char*)value);
- h->certificate = new char[len + 1];
- if (h->certificate == NULL)
- {
- result = HTTPAPI_ERROR;
- LogError("unable to allocate certificate memory in HTTPAPI_SetOption");
- }
- else
- {
- (void)strcpy(h->certificate, (const char*)value);
- result = HTTPAPI_OK;
- }
- }
- else
- {
- result = HTTPAPI_INVALID_ARG;
- LogError("unknown option %s", optionName);
- }
- return result;
-}
-
-HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue)
-{
- HTTPAPI_RESULT result;
- if (
- (optionName == NULL) ||
- (value == NULL) ||
- (savedValue == NULL)
- )
- {
- result = HTTPAPI_INVALID_ARG;
- LogError("invalid argument(NULL) passed to HTTPAPI_CloneOption");
- }
- else if (strcmp("TrustedCerts", optionName) == 0)
- {
- size_t certLen = strlen((const char*)value);
- char* tempCert = (char*)malloc(certLen+1);
- if (tempCert == NULL)
- {
- result = HTTPAPI_INVALID_ARG;
- LogError("unable to allocate certificate memory in HTTPAPI_CloneOption");
- }
- else
- {
- (void)strcpy(tempCert, (const char*)value);
- *savedValue = tempCert;
- result = HTTPAPI_OK;
- }
- }
- else
- {
- result = HTTPAPI_INVALID_ARG;
- LogError("unknown option %s", optionName);
- }
- return result;
-}
--- a/httpapiex.c Fri Jun 17 17:03:29 2016 -0700 +++ b/httpapiex.c Fri Jul 01 10:43:23 2016 -0700 @@ -8,7 +8,7 @@ #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/httpapiex.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/strings.h" #include "azure_c_shared_utility/crt_abstractions.h" #include "azure_c_shared_utility/vector.h"
--- a/httpapiexsas.c Fri Jun 17 17:03:29 2016 -0700
+++ b/httpapiexsas.c Fri Jul 01 10:43:23 2016 -0700
@@ -17,7 +17,7 @@
#include "azure_c_shared_utility/httpheaders.h"
#include "azure_c_shared_utility/httpapiex.h"
#include "azure_c_shared_utility/httpapiexsas.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
typedef struct HTTPAPIEX_SAS_STATE_TAG
{
--- a/httpheaders.c Fri Jun 17 17:03:29 2016 -0700
+++ b/httpheaders.c Fri Jul 01 10:43:23 2016 -0700
@@ -11,7 +11,7 @@
#include "azure_c_shared_utility/httpheaders.h"
#include <string.h>
#include "azure_c_shared_utility/crt_abstractions.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
static const char COLON_AND_SPACE[] = { ':', ' ', '\0' };
#define COLON_AND_SPACE_LENGTH ((sizeof(COLON_AND_SPACE)/sizeof(COLON_AND_SPACE[0]))-1)
--- a/lock_rtx_mbed.cpp Fri Jun 17 17:03:29 2016 -0700 +++ b/lock_rtx_mbed.cpp Fri Jul 01 10:43:23 2016 -0700 @@ -7,7 +7,7 @@ #endif #include "azure_c_shared_utility/lock.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include "rtos.h" DEFINE_ENUM_STRINGS(LOCK_RESULT, LOCK_RESULT_VALUES);
--- a/map.c Fri Jun 17 17:03:29 2016 -0700 +++ b/map.c Fri Jul 01 10:43:23 2016 -0700 @@ -8,7 +8,7 @@ #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/map.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/strings.h" DEFINE_ENUM_STRINGS(MAP_RESULT, MAP_RESULT_VALUES);
--- a/sastoken.c Fri Jun 17 17:03:29 2016 -0700
+++ b/sastoken.c Fri Jul 01 10:43:23 2016 -0700
@@ -18,7 +18,7 @@
#include "azure_c_shared_utility/agenttime.h"
#include "azure_c_shared_utility/strings.h"
#include "azure_c_shared_utility/buffer_.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, size_t expiry)
{
--- a/socketio_mbed.c Fri Jun 17 17:03:29 2016 -0700
+++ b/socketio_mbed.c Fri Jul 01 10:43:23 2016 -0700
@@ -12,7 +12,7 @@
#include "azure_c_shared_utility/socketio.h"
#include "azure_c_shared_utility/list.h"
#include "azure_c_shared_utility/tcpsocketconnection_c.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
#define UNABLE_TO_COMPLETE -2
#define MBED_RECEIVE_BYTES_VALUE 128
@@ -38,7 +38,6 @@
typedef struct SOCKET_IO_INSTANCE_TAG
{
TCPSOCKETCONNECTION_HANDLE tcp_socket_connection;
- LOGGER_LOG logger_log;
ON_BYTES_RECEIVED on_bytes_received;
ON_IO_ERROR on_io_error;
void* on_bytes_received_context;
@@ -108,7 +107,7 @@
return result;
}
-CONCRETE_IO_HANDLE socketio_create(void* io_create_parameters, LOGGER_LOG logger_log)
+CONCRETE_IO_HANDLE socketio_create(void* io_create_parameters)
{
SOCKETIO_CONFIG* socket_io_config = io_create_parameters;
SOCKET_IO_INSTANCE* result;
@@ -143,7 +142,6 @@
result->port = socket_io_config->port;
result->on_bytes_received = NULL;
result->on_io_error = NULL;
- result->logger_log = logger_log;
result->on_bytes_received_context = NULL;
result->on_io_error_context = NULL;
result->io_state = IO_STATE_CLOSED;
@@ -328,12 +326,6 @@
on_send_complete(callback_context, IO_SEND_OK);
}
- size_t i;
- for (i = 0; i < size; i++)
- {
- LOG(socket_io_instance->logger_log, 0, "%02x-> ", ((unsigned char*)buffer)[i]);
- }
-
result = 0;
}
}
--- a/string_tokenizer.c Fri Jun 17 17:03:29 2016 -0700 +++ b/string_tokenizer.c Fri Jul 01 10:43:23 2016 -0700 @@ -15,7 +15,7 @@ #include <stdbool.h> #include "azure_c_shared_utility/string_tokenizer.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/crt_abstractions.h" typedef struct STRING_TOKEN_TAG
--- a/strings.c Fri Jun 17 17:03:29 2016 -0700
+++ b/strings.c Fri Jul 01 10:43:23 2016 -0700
@@ -17,7 +17,7 @@
//
#include "azure_c_shared_utility/strings.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
static const char hexToASCII[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
--- a/threadapi_rtx_mbed.cpp Fri Jun 17 17:03:29 2016 -0700 +++ b/threadapi_rtx_mbed.cpp Fri Jul 01 10:43:23 2016 -0700 @@ -7,8 +7,8 @@ #endif #include "azure_c_shared_utility/threadapi.h" +#include "azure_c_shared_utility/xlogging.h" #include "rtos.h" -#include "azure_c_shared_utility/iot_logging.h" DEFINE_ENUM_STRINGS(THREADAPI_RESULT, THREADAPI_RESULT_VALUES);
--- a/tlsio_wolfssl.c Fri Jun 17 17:03:29 2016 -0700
+++ b/tlsio_wolfssl.c Fri Jul 01 10:43:23 2016 -0700
@@ -14,6 +14,8 @@
#include "azure_c_shared_utility/tlsio.h"
#include "azure_c_shared_utility/tlsio_wolfssl.h"
#include "azure_c_shared_utility/socketio.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/xlogging.h"
typedef enum TLSIO_STATE_ENUM_TAG
{
@@ -36,7 +38,6 @@
void* on_io_open_complete_context;
void* on_io_close_complete_context;
void* on_io_error_context;
- LOGGER_LOG logger_log;
WOLFSSL* ssl;
WOLFSSL_CTX* ssl_context;
TLSIO_STATE_ENUM tlsio_state;
@@ -44,6 +45,9 @@
size_t socket_io_read_byte_count;
ON_SEND_COMPLETE on_send_complete;
void* on_send_complete_callback_context;
+ char* certificate;
+ char* hostname;
+ int port;
} TLS_IO_INSTANCE;
static const IO_INTERFACE_DESCRIPTION tlsio_wolfssl_interface_description =
@@ -112,6 +116,7 @@
if (res != SSL_SUCCESS)
{
indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
+ tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
}
}
}
@@ -140,21 +145,21 @@
switch (tls_io_instance->tlsio_state)
{
- default:
- case TLSIO_STATE_NOT_OPEN:
- case TLSIO_STATE_ERROR:
- break;
+ default:
+ case TLSIO_STATE_NOT_OPEN:
+ case TLSIO_STATE_ERROR:
+ break;
- case TLSIO_STATE_OPENING_UNDERLYING_IO:
- case TLSIO_STATE_IN_HANDSHAKE:
- tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
- indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
- break;
+ case TLSIO_STATE_OPENING_UNDERLYING_IO:
+ case TLSIO_STATE_IN_HANDSHAKE:
+ tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+ indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
+ break;
- case TLSIO_STATE_OPEN:
- tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
- indicate_error(tls_io_instance);
- break;
+ case TLSIO_STATE_OPEN:
+ tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+ indicate_error(tls_io_instance);
+ break;
}
}
@@ -168,6 +173,7 @@
{
tls_io_instance->on_io_close_complete(tls_io_instance->on_io_close_complete_context);
}
+ tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
}
}
@@ -180,7 +186,7 @@
while (tls_io_instance->socket_io_read_byte_count == 0)
{
xio_dowork(tls_io_instance->socket_io);
- if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN)
+ if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
{
break;
}
@@ -216,6 +222,10 @@
{
result = WOLFSSL_CBIO_ERR_WANT_READ;
}
+ else if ((result == 0) && tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING)
+ {
+ result = WOLFSSL_CBIO_ERR_CONN_CLOSE;
+ }
return result;
}
@@ -251,6 +261,71 @@
return 0;
}
+static int add_certificate_to_store(TLS_IO_INSTANCE* tls_io_instance)
+{
+ int result;
+ if (tls_io_instance->certificate != NULL)
+ {
+ int res = wolfSSL_CTX_load_verify_buffer(tls_io_instance->ssl_context, (const unsigned char*)tls_io_instance->certificate, strlen(tls_io_instance->certificate)+1, SSL_FILETYPE_PEM);
+ if (res != SSL_SUCCESS)
+ {
+ result = __LINE__;
+ }
+ else
+ {
+ result = 0;
+ }
+ }
+ else
+ {
+ result = 0;
+ }
+ return result;
+}
+
+static int create_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
+{
+ int result;
+
+ if (add_certificate_to_store(tls_io_instance) != 0)
+ {
+ wolfSSL_CTX_free(tls_io_instance->ssl_context);
+ result = __LINE__;
+ }
+ else
+ {
+ tls_io_instance->ssl = wolfSSL_new(tls_io_instance->ssl_context);
+ if (tls_io_instance->ssl == NULL)
+ {
+ wolfSSL_CTX_free(tls_io_instance->ssl_context);
+ result = __LINE__;
+ }
+ else
+ {
+ tls_io_instance->socket_io_read_bytes = NULL;
+ tls_io_instance->socket_io_read_byte_count = 0;
+ tls_io_instance->on_send_complete = NULL;
+ tls_io_instance->on_send_complete_callback_context = NULL;
+
+ wolfSSL_set_using_nonblock(tls_io_instance->ssl, 1);
+ wolfSSL_SetIOSend(tls_io_instance->ssl_context, on_io_send);
+ wolfSSL_SetIORecv(tls_io_instance->ssl_context, on_io_recv);
+ wolfSSL_SetHsDoneCb(tls_io_instance->ssl, on_handshake_done, tls_io_instance);
+ wolfSSL_SetIOWriteCtx(tls_io_instance->ssl, tls_io_instance);
+ wolfSSL_SetIOReadCtx(tls_io_instance->ssl, tls_io_instance);
+
+ tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+ result = 0;
+ }
+ }
+ return result;
+}
+
+static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
+{
+ wolfSSL_free(tls_io_instance->ssl);
+}
+
int tlsio_wolfssl_init(void)
{
(void)wolfSSL_library_init();
@@ -263,7 +338,7 @@
{
}
-CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters, LOGGER_LOG logger_log)
+CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters)
{
TLSIO_CONFIG* tls_io_config = io_create_parameters;
TLS_IO_INSTANCE* result;
@@ -274,14 +349,20 @@
}
else
{
- result = malloc(sizeof(TLS_IO_INSTANCE));
+ result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
if (result != NULL)
{
- SOCKETIO_CONFIG socketio_config;
+ memset(result, 0, sizeof(TLS_IO_INSTANCE));
+ mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname);
+ result->port = tls_io_config->port;
- socketio_config.hostname = tls_io_config->hostname;
- socketio_config.port = tls_io_config->port;
- socketio_config.accepted_socket = NULL;
+ result->socket_io_read_bytes = 0;
+ result->socket_io_read_byte_count = 0;
+ result->socket_io = NULL;
+
+ result->ssl = NULL;
+ result->ssl_context = NULL;
+ result->certificate = NULL;
result->on_bytes_received = NULL;
result->on_bytes_received_context = NULL;
@@ -295,7 +376,7 @@
result->on_io_error = NULL;
result->on_io_error_context = NULL;
- result->logger_log = logger_log;
+ result->tlsio_state = TLSIO_STATE_NOT_OPEN;
result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_client_method());
if (result->ssl_context == NULL)
@@ -314,41 +395,23 @@
}
else
{
- result->socket_io = xio_create(socket_io_interface, &socketio_config, logger_log);
+ SOCKETIO_CONFIG socketio_config;
+ socketio_config.hostname = result->hostname;
+ socketio_config.port = result->port;
+ socketio_config.accepted_socket = NULL;
+
+ result->socket_io = xio_create(socket_io_interface, &socketio_config);
if (result->socket_io == NULL)
{
+ LogError("Failure connecting to underlying socket_io");
wolfSSL_CTX_free(result->ssl_context);
free(result);
result = NULL;
}
- else
- {
- result->ssl = wolfSSL_new(result->ssl_context);
- if (result->ssl == NULL)
- {
- wolfSSL_CTX_free(result->ssl_context);
- free(result);
- result = NULL;
- }
- else
- {
- result->socket_io_read_bytes = NULL;
- result->socket_io_read_byte_count = 0;
- result->on_send_complete = NULL;
- result->on_send_complete_callback_context = NULL;
-
- wolfSSL_set_using_nonblock(result->ssl, 1);
- wolfSSL_SetIOSend(result->ssl_context, on_io_send);
- wolfSSL_SetIORecv(result->ssl_context, on_io_recv);
- wolfSSL_SetHsDoneCb(result->ssl, on_handshake_done, result);
- wolfSSL_SetIOWriteCtx(result->ssl, result);
- wolfSSL_SetIOReadCtx(result->ssl, result);
-
- result->tlsio_state = TLSIO_STATE_NOT_OPEN;
- }
- }
}
}
+
+
}
}
@@ -360,14 +423,17 @@
if (tls_io != NULL)
{
TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
- wolfSSL_free(tls_io_instance->ssl);
- wolfSSL_CTX_free(tls_io_instance->ssl_context);
-
if (tls_io_instance->socket_io_read_bytes != NULL)
{
free(tls_io_instance->socket_io_read_bytes);
}
+ if (tls_io_instance->certificate != NULL)
+ {
+ free(tls_io_instance->certificate);
+ tls_io_instance->certificate = NULL;
+ }
+ wolfSSL_CTX_free(tls_io_instance->ssl_context);
xio_destroy(tls_io_instance->socket_io);
free(tls_io);
}
@@ -387,6 +453,7 @@
if (tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN)
{
+ LogError("Invalid state encountered.");
result = __LINE__;
}
else
@@ -402,24 +469,39 @@
tls_io_instance->tlsio_state = TLSIO_STATE_OPENING_UNDERLYING_IO;
- if (xio_open(tls_io_instance->socket_io, on_underlying_io_open_complete, tls_io_instance, on_underlying_io_bytes_received, tls_io_instance, on_underlying_io_error, tls_io_instance) != 0)
+ if (create_wolfssl_instance(tls_io_instance) != 0)
+ {
+ tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+ result = __LINE__;
+ }
+ else if (xio_open(tls_io_instance->socket_io, on_underlying_io_open_complete, tls_io_instance, on_underlying_io_bytes_received, tls_io_instance, on_underlying_io_error, tls_io_instance) != 0)
{
tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
result = __LINE__;
}
else
{
- int res;
- tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
-
- res = wolfSSL_connect(tls_io_instance->ssl);
- if (res != SSL_SUCCESS)
+ // The state can get changed in the on_underlying_io_open_complete
+ if (tls_io_instance->tlsio_state == TLSIO_STATE_ERROR)
{
+ LogError("Failed to connect to server. The certificates may not be correct.");
result = __LINE__;
}
else
{
- result = 0;
+ int res;
+ tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
+ res = wolfSSL_connect(tls_io_instance->ssl);
+ if (res != SSL_SUCCESS)
+ {
+ LogError("Failed to connect to server.");
+ tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
+ result = __LINE__;
+ }
+ else
+ {
+ result = 0;
+ }
}
}
}
@@ -457,6 +539,7 @@
}
else
{
+ destroy_wolfssl_instance(tls_io_instance);
result = 0;
}
}
@@ -535,13 +618,23 @@
if (strcmp("TrustedCerts", optionName) == 0)
{
- int res = wolfSSL_CTX_load_verify_buffer(tls_io_instance->ssl_context, (const unsigned char*)value, strlen(value) + 1, SSL_FILETYPE_PEM);
- if (res != SSL_SUCCESS)
+ const char* cert = (const char*)value;
+ if (tls_io_instance->certificate != NULL)
+ {
+ // Free the memory if it has been previously allocated
+ free(tls_io_instance->certificate);
+ }
+
+ // Store the certificate
+ size_t len = strlen(cert);
+ tls_io_instance->certificate = (const char*)malloc(len+1);
+ if (tls_io_instance->certificate == NULL)
{
result = __LINE__;
}
else
{
+ (void)strcpy(tls_io_instance->certificate, cert);
result = 0;
}
}
--- a/uniqueid_stub.c Fri Jun 17 17:03:29 2016 -0700 +++ b/uniqueid_stub.c Fri Jul 01 10:43:23 2016 -0700 @@ -4,7 +4,7 @@ #include <stdlib.h> #include <stdint.h> #include "azure_c_shared_utility/uniqueid.h" -#include "azure_c_shared_utility/iot_logging.h" +#include "azure_c_shared_utility/xlogging.h" #include <time.h> DEFINE_ENUM_STRINGS(UNIQUEID_RESULT, UNIQUEID_RESULT_VALUES);
--- a/urlencode.c Fri Jun 17 17:03:29 2016 -0700
+++ b/urlencode.c Fri Jul 01 10:43:23 2016 -0700
@@ -16,7 +16,7 @@
// PUT NO CLIENT LIBRARY INCLUDES BEFORE HERE !!!!
//
#include "azure_c_shared_utility/urlencode.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/strings.h"
static const struct {
--- a/wolfssl_connection.cpp Fri Jun 17 17:03:29 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-#include <memory.h>
-#include <time.h>
-#include "wolfssl/ssl.h"
-#include "wolfssl_connection.h"
-#include "azure_c_shared_utility/iot_logging.h"
-
-static timeval receiveTimeout = {0,1};
-static timeval sendTimeout = {0,1};
-
-
-WolfSSLConnection::WolfSSLConnection()
-{
- wolfSSL_Init();
-
- WOLFSSL_METHOD* method = wolfTLSv1_2_client_method();
- if(method != NULL)
- {
- sslContext = wolfSSL_CTX_new(method);
- }
- else
- {
- sslContext = NULL;
- }
-
- isConnected = false;
-}
-
-WolfSSLConnection::~WolfSSLConnection()
-{
- if (sslContext != NULL)
- {
- wolfSSL_CTX_free(sslContext);
- sslContext = NULL;
- }
-
- wolfSSL_Cleanup();
-}
-
-static int receiveCallback(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
- int fd = *(int*)ctx;
- int result;
-
- (void)ssl;
-
- fd_set rfds;
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
-
- if (lwip_select(FD_SETSIZE, &rfds, NULL, NULL, &receiveTimeout) < 0)
- {
- result = -1;
- }
- else
- {
- result = lwip_recv(fd, buf, sz, 0);
- }
-
- return result;
-}
-
-static int sendCallback(WOLFSSL* ssl, char *buf, int sz, void *ctx)
-{
- int fd = *(int*)ctx;
- int result;
-
- (void)ssl;
-
- fd_set wfds;
- FD_ZERO(&wfds);
- FD_SET(fd, &wfds);
-
- if (lwip_select(FD_SETSIZE, NULL, &wfds, NULL, &sendTimeout) < 0)
- {
- return -1;
- }
- else
- {
- result = lwip_send(fd, buf, sz, 0);
- }
-
- return result;
-}
-
-int WolfSSLConnection::connect(const char* host, const int port)
-{
- int result;
-
- if(sslContext == NULL)
- {
- LogError("NULL SSL context");
- result = __LINE__;
- }
- else
- {
- if (init_socket(SOCK_STREAM) < 0)
- {
- LogError("init_socket failed");
- result = __LINE__;
- }
- else
- {
- if (set_address(host, port) != 0)
- {
- LogError("set_address failed");
- result = __LINE__;
- }
- else if (lwip_connect(_sock_fd, (const struct sockaddr *) &_remoteHost, sizeof(_remoteHost)) < 0)
- {
- close();
- LogError("lwip_connect failed");
- result = __LINE__;
- }
- else
- {
- wolfSSL_SetIOSend(sslContext, &sendCallback);
- wolfSSL_SetIORecv(sslContext, &receiveCallback);
-
- ssl = wolfSSL_new(sslContext);
- if(ssl == NULL)
- {
- LogError("wolfssl new error");
- result = __LINE__;
- }
- else
- {
- wolfSSL_set_fd(ssl, _sock_fd);
-
- result = wolfSSL_connect(ssl);
- if (result != SSL_SUCCESS)
- {
- LogError("wolfssl connect error=%d", result);
- result = __LINE__;
- }
- else
- {
- result = 0;
- isConnected = true;
- }
- }
- }
- }
- }
-
- return result;
-};
-
-bool WolfSSLConnection::is_connected(void)
-{
- return isConnected;
-}
-
-int WolfSSLConnection::send(char* data, int length)
-{
- int result;
-
- if (!isConnected)
- {
- result = 0;
- }
- else
- {
- result = wolfSSL_write(ssl, data, length);
- }
-
- return result;
-}
-
-int WolfSSLConnection::send_all(char* data, int length)
-{
- return send(data, length);
-}
-
-int WolfSSLConnection::receive(char* data, int length)
-{
- int result;
-
- if (!isConnected)
- {
- result = 0;
- }
- else
- {
- result = wolfSSL_read(ssl, data, length);
- }
-
- return result;
-}
-
-int WolfSSLConnection::receive_all(char* data, int length)
-{
- return receive(data, length);
-}
-
-bool WolfSSLConnection::close(bool shutdown)
-{
- bool result;
-
- if (!isConnected)
- {
- result = true;
- }
- else
- {
- isConnected = false;
-
- wolfSSL_CTX_free(sslContext);
- result = Socket::close(shutdown) == 0;
- }
-
- return result;
-}
-
-bool WolfSSLConnection::load_certificate(const unsigned char* certificate, size_t size)
-{
- bool result;
-
- if (sslContext == NULL)
- {
- LogError("NULL SSL context");
- result = false;
- }
- else
- {
- result = (wolfSSL_CTX_load_verify_buffer(sslContext,(unsigned char*)certificate, size, SSL_FILETYPE_PEM) == SSL_SUCCESS);
- }
-
- return result;
-}
--- a/wolfssl_connection.h Fri Jun 17 17:03:29 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-#ifndef WOLFSSL_CONNECTION_H
-#define WOLFSSL_CONNECTION_H
-
-#include "wolfssl/ssl.h"
-#include "TCPSocketConnection.h"
-
-class WolfSSLConnection : public TCPSocketConnection
-{
-public:
- WolfSSLConnection();
- virtual ~WolfSSLConnection();
-
-public:
- int connect(const char* host, const int port);
- bool is_connected(void);
- int send(char* data, int length);
- int send_all(char* data, int length);
- int receive(char* data, int length);
- int receive_all(char* data, int length);
- bool close(bool shutdown = true);
- bool load_certificate(const unsigned char* certificate, size_t size);
-
-protected:
- WOLFSSL_CTX* sslContext;
- WOLFSSL* ssl;
- bool isConnected;
-};
-
-#endif /* WOLFSSL_CONNECTION_H */
--- a/xio.c Fri Jun 17 17:03:29 2016 -0700
+++ b/xio.c Fri Jul 01 10:43:23 2016 -0700
@@ -15,7 +15,7 @@
XIO_HANDLE concrete_xio_handle;
} XIO_INSTANCE;
-XIO_HANDLE xio_create(const IO_INTERFACE_DESCRIPTION* io_interface_description, const void* xio_create_parameters, LOGGER_LOG logger_log)
+XIO_HANDLE xio_create(const IO_INTERFACE_DESCRIPTION* io_interface_description, const void* xio_create_parameters)
{
XIO_INSTANCE* xio_instance;
/* Codes_SRS_XIO_01_003: [If the argument io_interface_description is NULL, xio_create shall return NULL.] */
@@ -41,8 +41,8 @@
/* Codes_SRS_XIO_01_001: [xio_create shall return on success a non-NULL handle to a new IO interface.] */
xio_instance->io_interface_description = io_interface_description;
- /* Codes_SRS_XIO_01_002: [In order to instantiate the concrete IO implementation the function concrete_io_create from the io_interface_description shall be called, passing the xio_create_parameters and logger_log arguments.] */
- xio_instance->concrete_xio_handle = xio_instance->io_interface_description->concrete_io_create((void*)xio_create_parameters, logger_log);
+ /* Codes_SRS_XIO_01_002: [In order to instantiate the concrete IO implementation the function concrete_io_create from the io_interface_description shall be called, passing the xio_create_parameters argument.] */
+ xio_instance->concrete_xio_handle = xio_instance->io_interface_description->concrete_io_create((void*)xio_create_parameters);
/* Codes_SRS_XIO_01_016: [If the underlying concrete_io_create call fails, xio_create shall return NULL.] */
if (xio_instance->concrete_xio_handle == NULL)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xlogging.c Fri Jul 01 10:43:23 2016 -0700
@@ -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.
+
+#include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/consolelogger.h"
+
+static LOGGER_LOG global_log_function = consolelogger_log;
+
+void xlogging_set_log_function(LOGGER_LOG log_function)
+{
+ global_log_function = log_function;
+}
+
+LOGGER_LOG xlogging_get_log_function(void)
+{
+ return global_log_function;
+}
