/* * Copyright (C) 2020 MERA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "utils.h" #include "ClientManager.h" #include "CloudType.h" #include "AwsClient.h" #include "AzureClient.h" #include namespace { std::map> g_clouds; } static bool loadConf() { const char* CONF_FILE_PATH{"/etc/config.ini"}; const char* DEFAULT_ETC_PATH{"/etc/cloudproxy-service"}; const char *p = getenv("AFM_APP_INSTALL_DIR"); if(!p) { AFB_ERROR("AFM_APP_INSTALL_DIR is not set, try to find conf in %s", DEFAULT_ETC_PATH); p = DEFAULT_ETC_PATH; } std::string conf_path = p; conf_path += CONF_FILE_PATH; 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)) { AFB_ERROR("Can't load file %s", conf_path.c_str()); return false; } //-- Azure parameters: { std::unique_ptr azure{new AzureClient}; if (!azure->loadConf(conf_file)) return false; if (azure->enabled()) g_clouds[CloudType::Azure] = std::move(azure); else g_clouds[CloudType::Azure].reset(); } //-- AWS parameters: { std::unique_ptr aws{new AwsClient}; if (!aws->loadConf(conf_file)) return false; if (aws->enabled()) g_clouds[CloudType::Aws] = std::move(aws); else g_clouds[CloudType::Aws].reset(); } if (!std::any_of(g_clouds.begin(), g_clouds.end(), [](const auto& c){ return !!c.second; })) { AFB_ERROR("All cloud connection types are disabled by configuration"); return false; } 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); AFB_NOTICE("Verbosity macro at level notice invoked at ping invocation count = %d", pingcount); pingcount++; } static void sendMessage(afb_req_t request) { AFB_NOTICE("%s called", __FUNCTION__); json_object* object = afb_req_json(request); if (!object) { 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)}; if (appid.empty()) { AFB_ERROR("can't obtain application_id from request"); afb_req_fail_f(request, "failed", "called %s", __FUNCTION__); return; } 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)) { afb_req_fail_f(request, "failed", "called %s", __FUNCTION__); return; } std::string data; if (!read_string("data", data)) { afb_req_fail_f(request, "failed", "called %s", __FUNCTION__); return; } 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 (!g_clouds[cloud_type]) { AFB_ERROR("%s cloud connection is disabled by config", cloud_type.c_str()); afb_req_fail_f(request, "failed", "called %s", __FUNCTION__); return; } 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 (!client->sendMessage(appid, data)) { AFB_ERROR("Can't send message to %s cloud", cloud_type.c_str()); afb_req_fail_f(request, "failed", "called %s", __FUNCTION__); return; } afb_req_success(request, json_object_new_object(), __FUNCTION__); } static void subscribe(afb_req_t request) { AFB_NOTICE("%s called", __FUNCTION__); std::string req_appid{utils::get_application_id(request)}; if(req_appid.empty()) { 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)) { AFB_ERROR("%s failed in handleRequest", __FUNCTION__); afb_req_fail_f(request, "%s failed", __FUNCTION__); } else { afb_req_success(request, json_object_new_object(), __FUNCTION__); } } static void unsubscribe(afb_req_t request) { AFB_NOTICE("%s called", __FUNCTION__); std::string req_appid{utils::get_application_id(request)}; if(req_appid.empty()) { 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)) { AFB_ERROR("%s failedin handleRequest", __FUNCTION__); afb_req_fail_f(request, "%s failed", __FUNCTION__); } else { afb_req_success(request, json_object_new_object(), __FUNCTION__); } } /* * array of the verbs exported to afb-daemon */ static const afb_verb_t verbs[]= { /* VERB'S NAME FUNCTION TO CALL */ { .verb="ping", .callback=pingSample }, { .verb="sendMessage", .callback=sendMessage }, { .verb="subscribe", .callback=subscribe }, { .verb="unsubscribe", .callback=unsubscribe }, {nullptr } /* marker for end of the array */ }; static int preinit(afb_api_t api) { AFB_NOTICE("binding preinit (was register)"); if (!loadConf()) { AFB_ERROR("Can't load configuration file or configuration is wrong"); return -1; } return 0; } static int init(afb_api_t api) { AFB_NOTICE("binding init"); return 0; } const afb_binding_t afbBindingExport = { .api = "cloudproxy", .specification = nullptr, .info = nullptr, .verbs = verbs, .preinit = preinit, .init = init, .onevent = nullptr };