aboutsummaryrefslogtreecommitdiffstats
path: root/src/cloudproxy-bindings.cpp
diff options
context:
space:
mode:
authorAndrey Shamanin <andrei.shamanin@orioninc.com>2020-10-16 11:17:53 +0300
committerAndrey Shamanin <andrei.shamanin@orioninc.com>2020-10-16 11:21:30 +0300
commit87c68a6bc0d655e796484d110fa5336322b171d0 (patch)
tree98891fb8c0090e59f7a9b6904a9d59f04e5b0e02 /src/cloudproxy-bindings.cpp
parent329d8ba3fb46b8afc803ad4a9b286cd26141f2f8 (diff)
Bug-AGL: SPEC-3481 Signed-off-by: Andrey Shamanin <andrei.shamanin@orioninc.com> Change-Id: I071d94a9dc2e1f455119124c1185bf135f4c5b78
Diffstat (limited to 'src/cloudproxy-bindings.cpp')
-rwxr-xr-xsrc/cloudproxy-bindings.cpp329
1 files changed, 80 insertions, 249 deletions
diff --git a/src/cloudproxy-bindings.cpp b/src/cloudproxy-bindings.cpp
index 1a40730..c69e9c7 100755
--- a/src/cloudproxy-bindings.cpp
+++ b/src/cloudproxy-bindings.cpp
@@ -20,37 +20,20 @@
#include <memory>
#include <algorithm>
-#include <iothub.h>
-#include <iothub_device_client.h>
-#include <iothub_client_options.h>
-#include <iothub_message.h>
-#include <iothubtransportmqtt.h>
-#include <azure_c_shared_utility/threadapi.h> // ThreadAPI_Sleep()
-#include <azure_c_shared_utility/tickcounter.h> // tickcounter_ms_t
-
-#include "hmi-debug.h"
#include "utils.h"
#include "ClientManager.h"
+#include "CloudType.h"
+#include "AwsClient.h"
+#include "AzureClient.h"
#include <glib.h>
-static const char* API_name{"cloudproxy"};
-
-static std::string g_connectionString;
-static IOTHUB_DEVICE_CLIENT_HANDLE g_device_handle{nullptr};
-static bool g_iot_inited{false};
-
-
+namespace
+{
-static utils::scope_exit g_destroy([]{
- if (g_iot_inited)
- {
- if (g_device_handle)
- IoTHubDeviceClient_Destroy(g_device_handle);
+std::map<std::string, std::unique_ptr<CloudClient>> g_clouds;
- IoTHub_Deinit();
- }
-});
+}
static bool loadConf()
@@ -60,7 +43,7 @@ static bool loadConf()
const char *p = getenv("AFM_APP_INSTALL_DIR");
if(!p)
{
- HMI_ERROR("cloudproxy-service", "AFM_APP_INSTALL_DIR is not set, try to find conf in %s", DEFAULT_ETC_PATH);
+ AFB_ERROR("AFM_APP_INSTALL_DIR is not set, try to find conf in %s", DEFAULT_ETC_PATH);
p = DEFAULT_ETC_PATH;
}
@@ -70,273 +53,127 @@ static bool loadConf()
g_autoptr(GKeyFile) conf_file = g_key_file_new();
g_autoptr(GError) error = nullptr;
+ AFB_DEBUG("Load config file: %s", conf_path.c_str());
if (!conf_file || !g_key_file_load_from_file(conf_file, conf_path.c_str(), G_KEY_FILE_NONE, &error))
{
- HMI_ERROR("cloudproxy-service", "can't load file %s", conf_path.c_str());
- return false;
- }
-
- g_autofree gchar *value = g_key_file_get_string(conf_file, "AzureCloudConnection", "DeviceConnectionString", &error);
- if (value == nullptr)
- {
- HMI_ERROR("cloudproxy-service", "can't read DeviceConnectionString from config %d", conf_path.c_str());
- return false;
- }
-
- g_connectionString = value;
- if (g_connectionString.empty())
- {
- HMI_ERROR("cloudproxy-service", "DeviceConnectionString is empty");
+ AFB_ERROR("Can't load file %s", conf_path.c_str());
return false;
}
- return true;
-}
-
-
-//-------------- Iot callbacks
-static void connection_status_callback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* user_context)
-{
- HMI_NOTICE("cloudproxy-service", "%s called: result %d, reason %d", __FUNCTION__, result, reason);
-
- (void)reason;
- (void)user_context;
- // This sample DOES NOT take into consideration network outages.
- if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED && reason == IOTHUB_CLIENT_CONNECTION_OK)
- {
- HMI_NOTICE("cloudproxy-service", "The device client is connected to iothub");
- }
- else
- {
- HMI_NOTICE("cloudproxy-service", "The device client has been disconnected");
- }
-}
-
-static IOTHUBMESSAGE_DISPOSITION_RESULT receive_msg_callback(IOTHUB_MESSAGE_HANDLE message, void* user_context)
-{
- HMI_NOTICE("cloudproxy-service", "%s called", __FUNCTION__);
- (void)user_context;
- const char* messageId;
- const char* correlationId;
-
- IOTHUBMESSAGE_CONTENT_TYPE content_type = IoTHubMessage_GetContentType(message);
-
- if (content_type == IOTHUBMESSAGE_BYTEARRAY)
+ //-- Azure parameters:
{
- const unsigned char* buff_msg;
- size_t buff_len;
+ std::unique_ptr<CloudClient> azure{new AzureClient};
+ if (!azure->loadConf(conf_file))
+ return false;
- if (IoTHubMessage_GetByteArray(message, &buff_msg, &buff_len) != IOTHUB_MESSAGE_OK)
- {
- HMI_ERROR("cloudproxy-service", "Failure retrieving byte array message");
- }
- else
- {
- HMI_NOTICE("cloudproxy-service", "Received Binary message, size %d, data '%.*s'", (int)buff_len, (int)buff_len, buff_msg);
- }
-
- const char* app_id = IoTHubMessage_GetProperty(message, "application_id");
- HMI_NOTICE("cloudproxy-service", "Received property 'application_id': %s", (app_id ? app_id : "<unavailable>"));
-
- if (app_id && app_id[0])
- ClientManager::instance().emitReceivedMessage(app_id, std::string((const char*)buff_msg, buff_len));
- else
- HMI_ERROR("cloudproxy-service", "Can't emit SendMessageConfirmation: appid is not valid");
- }
- else if (content_type == IOTHUBMESSAGE_STRING)
- {
- const char* string_msg = IoTHubMessage_GetString(message);
- if (string_msg == nullptr)
- {
- HMI_NOTICE("cloudproxy-service", "Failure retrieving String message");
- }
- else
- {
- HMI_NOTICE("cloudproxy-service", "Received String message, size %d, data '%s'", strlen(string_msg), string_msg);
- }
-
- const char* app_id = IoTHubMessage_GetProperty(message, "application_id");
- HMI_NOTICE("cloudproxy-service", "Received property 'application_id': %s", (app_id ? app_id : "<unavailable>"));
-
- if (app_id && app_id[0])
- ClientManager::instance().emitReceivedMessage(app_id, string_msg);
+ if (azure->enabled())
+ g_clouds[CloudType::Azure] = std::move(azure);
else
- HMI_ERROR("cloudproxy-service", "Can't emit SendMessageConfirmation: appid is not valid");
- }
- else
- {
- HMI_ERROR("cloudproxy-service", "Unsupported message content type");
- }
-
- return IOTHUBMESSAGE_ACCEPTED;
-}
-
-
-static int device_method_callback(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* resp_size, void* userContextCallback)
-{
- HMI_NOTICE("cloudproxy-service", "%s called, method_name %s", __FUNCTION__, method_name);
-
- const char* device_id = (const char*)userContextCallback;
- char* end = nullptr;
- int newInterval;
-
- int status = 501;
- const char* RESPONSE_STRING = "{ \"Response\": \"Unknown method requested.\" }";
-
- HMI_NOTICE("cloudproxy-service", "Device Method called for device %s", device_id);
- HMI_NOTICE("cloudproxy-service", "Device Method name: %s", method_name);
- HMI_NOTICE("cloudproxy-service", "Device Method payload: %.*s", (int)size, (const char*)payload);
-
- HMI_NOTICE("cloudproxy-service", "Response status: %d", status);
- HMI_NOTICE("cloudproxy-service", "Response payload: %s", RESPONSE_STRING);
-
- *resp_size = strlen(RESPONSE_STRING);
- if ((*response = (unsigned char*)malloc(*resp_size)) == NULL)
- {
- status = -1;
- }
- else
- {
- memcpy(*response, RESPONSE_STRING, *resp_size);
+ g_clouds[CloudType::Azure].reset();
}
- return status;
-}
-
-
-static void send_confirm_callback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
-{
- HMI_NOTICE("cloudproxy-service", "%s called, result %d", __FUNCTION__, result);
- (void)userContextCallback;
- // When a message is sent this callback will get invoked
-
- HMI_NOTICE("cloudproxy-service", "Confirmation callback result %s", MU_ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));
-
- const char* appid = (const char*)userContextCallback;
- if (!appid || !appid[0])
+ //-- AWS parameters:
{
- HMI_ERROR("cloudproxy-service", "Confirmation callback: appid is not set");
-
- if (userContextCallback)
- free(userContextCallback);
+ std::unique_ptr<CloudClient> aws{new AwsClient};
+ if (!aws->loadConf(conf_file))
+ return false;
- return;
- }
-
- ClientManager::instance().emitSendMessageConfirmation(appid, result == IOTHUB_CLIENT_CONFIRMATION_OK);
- free(userContextCallback);
-}
-//--------------
-
-//-------------- help functions
-static bool createConnection()
-{
- HMI_NOTICE("cloudproxy-service", "%s called", __FUNCTION__);
-
- if (g_device_handle)
- {
- HMI_WARNING("cloudproxy-service", "connection already created");
- return true;
+ if (aws->enabled())
+ g_clouds[CloudType::Aws] = std::move(aws);
+ else
+ g_clouds[CloudType::Aws].reset();
}
- g_device_handle = IoTHubDeviceClient_CreateFromConnectionString(g_connectionString.c_str(), MQTT_Protocol);
- if (!g_device_handle)
+ if (!std::any_of(g_clouds.begin(), g_clouds.end(), [](const auto& c){ return !!c.second; }))
{
- HMI_ERROR("cloudproxy-service", "Failure creating IoTHubDeviceClient device");
+ AFB_ERROR("All cloud connection types are disabled by configuration");
return false;
}
- bool traceOn = false;
- IoTHubDeviceClient_SetOption(g_device_handle, OPTION_LOG_TRACE, &traceOn);
- IoTHubDeviceClient_SetConnectionStatusCallback(g_device_handle, connection_status_callback, nullptr);
- IoTHubDeviceClient_SetMessageCallback(g_device_handle, receive_msg_callback, nullptr);
- IoTHubDeviceClient_SetDeviceMethodCallback(g_device_handle, device_method_callback, nullptr);
-
- tickcounter_ms_t ms_delay = 10;
- IoTHubDeviceClient_SetOption(g_device_handle, OPTION_DO_WORK_FREQUENCY_IN_MS, &ms_delay); // DoWork multithread
-
return true;
}
-//--------------
-
static void pingSample(afb_req_t request)
{
static int pingcount = 0;
afb_req_success_f(request, json_object_new_int(pingcount), "Ping count = %d", pingcount);
- HMI_NOTICE("cloudproxy-service", "Verbosity macro at level notice invoked at ping invocation count = %d", pingcount);
+ AFB_NOTICE("Verbosity macro at level notice invoked at ping invocation count = %d", pingcount);
pingcount++;
}
-static bool initAzureSdk()
-{
- //Allow program to try to establish connection several times
- if (!g_iot_inited)
- {
- if(IoTHub_Init())
- {
- HMI_ERROR("cloudproxy-service","Azure IoTHub_Init() failed");
- }
- else
- {
- g_iot_inited = true;
- }
- }
-
- return g_iot_inited;
-}
-
static void sendMessage(afb_req_t request)
{
- HMI_NOTICE("cloudproxy-service", "%s called", __FUNCTION__);
+ AFB_NOTICE("%s called", __FUNCTION__);
json_object* object = afb_req_json(request);
if (!object)
{
- HMI_ERROR("cloudproxy-service", "Can't parse request");
+ AFB_ERROR("Can't parse request");
afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
return;
}
const std::string appid{utils::get_application_id(request)};
- std::string data;
- json_object *obj_data;
- if(!json_object_object_get_ex(object, "data", &obj_data))
+ if (appid.empty())
{
- HMI_ERROR("cloudproxy-service", "can't obtain application_id or data from request");
+ AFB_ERROR("can't obtain application_id from request");
+ afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
return;
}
- data = json_object_get_string(obj_data);
- if (!g_device_handle && !createConnection())
+ auto read_string = [object](const char* tag, std::string& read_to)
+ {
+ json_object* jobj{nullptr};
+ if (!json_object_object_get_ex(object, tag, &jobj))
+ {
+ AFB_ERROR("can't obtain %s from request", tag);
+ return false;
+ }
+ read_to = json_object_get_string(jobj);
+ return true;
+ };
+
+ std::string cloud_type;
+ if (!read_string("cloud_type", cloud_type))
{
- HMI_ERROR("cloudproxy-service", "Can't create connection to cloud");
afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
return;
}
- IOTHUB_MESSAGE_HANDLE message_handle = IoTHubMessage_CreateFromString(data.c_str());
+ std::string data;
+ if (!read_string("data", data))
+ {
+ afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
+ return;
+ }
- utils::scope_exit message_handle_destroy([&message_handle](){
- // The message is copied to the sdk, so the we can destroy it
- if (message_handle)
- IoTHubMessage_Destroy(message_handle);
- });
+ if (!CloudType::isSupported(cloud_type))
+ {
+ AFB_ERROR("Unsupported cloud type is requested: '%s'", cloud_type.c_str());
+ afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
+ return;
+ }
- if (!message_handle)
+ if (!g_clouds[cloud_type])
{
- HMI_ERROR("cloudproxy-service", "Can't create IoTHubMessage message");
+ AFB_ERROR("%s cloud connection is disabled by config", cloud_type.c_str());
afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
return;
}
- IoTHubMessage_SetProperty(message_handle, "application_id", appid.c_str());
+ CloudClient* client{g_clouds[cloud_type.c_str()].get()};
+ if (!client->connected() && !client->createConnection())
+ {
+ AFB_ERROR("Can't create connection to %s cloud", cloud_type.c_str());
+ afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
+ return;
+ }
- if (IoTHubDeviceClient_SendEventAsync(g_device_handle, message_handle, send_confirm_callback, strdup(appid.c_str())))
+ if (!client->sendMessage(appid, data))
{
- HMI_ERROR("cloudproxy-service", "Can't send IoTHubMessage message");
+ AFB_ERROR("Can't send message to %s cloud", cloud_type.c_str());
afb_req_fail_f(request, "failed", "called %s", __FUNCTION__);
return;
}
@@ -347,19 +184,19 @@ static void sendMessage(afb_req_t request)
static void subscribe(afb_req_t request)
{
- HMI_NOTICE("cloudproxy-service", "%s called", __FUNCTION__);
+ AFB_NOTICE("%s called", __FUNCTION__);
std::string req_appid{utils::get_application_id(request)};
if(req_appid.empty())
{
- HMI_ERROR("cloudproxy-service", "Can't subscribe: empty appid");
+ AFB_ERROR("Can't subscribe: empty appid");
afb_req_fail_f(request, "%s failed: application_id is not defined in request", __FUNCTION__);
return;
}
if (!ClientManager::instance().handleRequest(request, __FUNCTION__, req_appid))
{
- HMI_ERROR("cloudproxy-service", "%s failed in handleRequest", __FUNCTION__);
+ AFB_ERROR("%s failed in handleRequest", __FUNCTION__);
afb_req_fail_f(request, "%s failed", __FUNCTION__);
}
else
@@ -370,19 +207,19 @@ static void subscribe(afb_req_t request)
static void unsubscribe(afb_req_t request)
{
- HMI_NOTICE("cloudproxy-service", "%s called", __FUNCTION__);
+ AFB_NOTICE("%s called", __FUNCTION__);
std::string req_appid{utils::get_application_id(request)};
if(req_appid.empty())
{
- HMI_ERROR("cloudproxy-service", "Can't unsubscribe: empty appid");
+ AFB_ERROR("Can't unsubscribe: empty appid");
afb_req_fail_f(request, "%s failed: application_id is not defined in request", __FUNCTION__);
return;
}
if (!ClientManager::instance().handleRequest(request, __FUNCTION__, req_appid))
{
- HMI_ERROR("cloudproxy-service", "%s failedin handleRequest", __FUNCTION__);
+ AFB_ERROR("%s failedin handleRequest", __FUNCTION__);
afb_req_fail_f(request, "%s failed", __FUNCTION__);
}
else
@@ -406,17 +243,11 @@ static const afb_verb_t verbs[]= {
static int preinit(afb_api_t api)
{
- HMI_NOTICE("cloudproxy-service", "binding preinit (was register)");
+ AFB_NOTICE("binding preinit (was register)");
if (!loadConf())
{
- HMI_ERROR("cloudproxy-service", "Can't load configuration file or configuration is wrong");
- return -1;
- }
-
- if (!initAzureSdk())
- {
- HMI_ERROR("cloudproxy-service", "Can't initialize Azure SDK");
+ AFB_ERROR("Can't load configuration file or configuration is wrong");
return -1;
}
@@ -426,8 +257,8 @@ static int preinit(afb_api_t api)
static int init(afb_api_t api)
{
- HMI_NOTICE("cloudproxy-service","binding init");
- return (g_iot_inited ? 0 : -1);
+ AFB_NOTICE("binding init");
+ return 0;
}
const afb_binding_t afbBindingExport = {