/* * Copyright (C) 2018 "IoT.bzh" * Author Jonathan Aillet * * 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. */ #define _GNU_SOURCE #include #include #include #include #include "4a-hal-utilities-data.h" #include "../4a-internals-hal/4a-internals-hal-cb.h" #include "4a-hal-manager-cb.h" /******************************************************************************* * HAL Manager event handler function * ******************************************************************************/ // TBD JAI : to implement void HalMgrDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ) { AFB_API_WARNING(apiHandle, "Not implemented yet"); // Use "4a-hal-manager-events.h" to handle events } /******************************************************************************* * HAL Manager verbs functions * ******************************************************************************/ void HalMgrLoaded(afb_req_t request) { int requestJsonErr = 0, allHal = 0, verbose = 0, wrapRet = 0; afb_api_t apiHandle; struct HalMgrData *halMgrData; struct HalData *currentHalData; json_object *requestJson, *requestAnswer, *dependenciesJ, *apiRequestedInfoJ; apiHandle = afb_req_get_api(request); if(! apiHandle) { afb_req_fail(request, "api_handle", "Can't get hal manager api handle"); return; } halMgrData = (struct HalMgrData *) afb_api_get_userdata(apiHandle); if(! halMgrData) { afb_req_fail(request, "hal_manager_data", "Can't get hal manager data"); return; } if(cds_list_empty(&halMgrData->halDataListHead)) { afb_req_success(request, NULL, "No Hal Api loaded"); return; } requestAnswer = json_object_new_array(); if(! requestAnswer) { afb_req_fail(request, "response_json_array", "Didn't succeed to allocate response json array"); return; } requestJson = afb_req_json(request); if(! requestJson) AFB_REQ_NOTICE(request, "Can't get request json"); else requestJsonErr = wrap_json_unpack(requestJson, "{s?:b s?:b}", "all", &allHal, "verbose", &verbose); cds_list_for_each_entry(currentHalData, &halMgrData->halDataListHead, node) { if(allHal || currentHalData->status == HAL_STATUS_READY) { // Case if request key is 'verbose' and value is bigger than 0 if(! requestJsonErr && verbose) { dependenciesJ = HalUtlGetJsonArrayForAllDependencies(apiHandle, ¤tHalData->internalHalData->probedDevicesListHead, DEPENDENCY_COMPACT_JSON); if(! dependenciesJ) AFB_REQ_WARNING(request, "Didn't succeed to generate all dependencies compact json array"); wrapRet = wrap_json_pack(&apiRequestedInfoJ, "{s:s s:i s:i s:s s:s s:s s:s s:s s?:o}", "api", currentHalData->apiName, "status", (int) currentHalData->status, "internal", (int) currentHalData->internal, "uid", currentHalData->uid, "info", currentHalData->info ? currentHalData->info : "", "author", currentHalData->author ? currentHalData->author : "", "version", currentHalData->version ? currentHalData->version : "", "date", currentHalData->date ? currentHalData->date : "", "dependencies", dependenciesJ); } // Case if request is empty or not handled else { apiRequestedInfoJ = json_object_new_string(currentHalData->apiName); } if(wrapRet || ! apiRequestedInfoJ) { afb_req_fail(request, "requestedinfo_json", "Didn't succeed to allocate api requested info json"); json_object_put(requestAnswer); return; } json_object_array_add(requestAnswer, apiRequestedInfoJ); } } afb_req_success(request, requestAnswer, "Requested data"); } void HalMgrInfo(afb_req_t request) { int err, wrapRet = 0; afb_api_t apiHandle; struct HalMgrData *halMgrData; struct HalData *currentHalData; json_object *requestJson, *toReturnJ, *returnedInfoJ, *transferredJson = NULL; apiHandle = afb_req_get_api(request); if(! apiHandle) { afb_req_fail(request, "api_handle", "Can't get hal manager api handle"); return; } halMgrData = (struct HalMgrData *) afb_api_get_userdata(apiHandle); if(! halMgrData) { afb_req_fail(request, "hal_manager_data", "Can't get hal manager data"); return; } if(cds_list_empty(&halMgrData->halDataListHead)) { afb_req_success(request, NULL, "No Hal Api loaded"); return; } requestJson = afb_req_json(request); if(! requestJson) { AFB_REQ_NOTICE(request, "Can't get request json, will use default verbose"); wrapRet = wrap_json_pack(&transferredJson, "{s:i}", "verbose", 0); if(wrapRet) { afb_req_fail(request, "json_request", "Didn't succeed to generate default json request"); return; } } else { AFB_REQ_DEBUG(request, "Received request json ('%s') will be transferred to each hal 'info' verb", json_object_get_string(requestJson)); transferredJson = requestJson; } toReturnJ = json_object_new_array(); if(! toReturnJ) { afb_req_fail(request, "response_json_array", "Didn't succeed to allocate response json array"); if(! requestJson) json_object_put(transferredJson); return; } cds_list_for_each_entry(currentHalData, &halMgrData->halDataListHead, node) { if(! currentHalData->internalHalData) { AFB_REQ_INFO(request, "'%s' hal is an external hal, will not be able to get info about it", currentHalData->apiName); continue; } err = GenerateInternalHalInfoJson(apiHandle, currentHalData, transferredJson, &returnedInfoJ); if(err){ AFB_REQ_INFO(request, "Error %i happened when tried to generate hal '%s' information json", err, currentHalData->apiName); json_object_put(toReturnJ); if(! requestJson) json_object_put(transferredJson); return; } json_object_array_add(toReturnJ, returnedInfoJ); } if(! requestJson) json_object_put(transferredJson); afb_req_success(request, toReturnJ, "Requested data"); } void HalMgrLoad(afb_req_t request) { char *apiName, *uid, *info = NULL, *author = NULL, *version = NULL, *date = NULL; afb_api_t apiHandle; struct HalMgrData *halMgrData; struct HalData *addedHal; json_object *requestJson, *apiReceivedMetadata; apiHandle = afb_req_get_api(request); if(! apiHandle) { afb_req_fail(request, "api_handle", "Can't get hal manager api handle"); return; } halMgrData = (struct HalMgrData *) afb_api_get_userdata(apiHandle); if(! halMgrData) { afb_req_fail(request, "hal_manager_data", "Can't get hal manager data"); return; } requestJson = afb_req_json(request); if(! requestJson) { afb_req_fail(request, "request_json", "Can't get request json"); return; } if(! json_object_object_get_ex(requestJson, "metadata", &apiReceivedMetadata)) { afb_req_fail(request, "api_metadata", "Can't get json metadata section to register external hal"); return; } if(wrap_json_unpack(apiReceivedMetadata, "{s:s s:s s?:s s?:s s?:s s?:s}", "api", &apiName, "uid", &uid, "info", &info, "author", &author, "version", &version, "date", &date)) { afb_req_fail(request, "api_metadata", "Can't metadata of api to register"); return; } addedHal = HalUtlAddHalToHalList(&halMgrData->halDataListHead); addedHal->internal = 0; // TBD JAI : initialize external to unavailable once event from external hal will be handled addedHal->status = HAL_STATUS_READY; addedHal->apiName = strdup(apiName); if(! addedHal->apiName) { afb_req_fail(request, "apiname_string_allocation", "Didn't succeed to store (allocate) 'apiName' string"); HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, addedHal); return; } addedHal->uid = strdup(uid); if(! addedHal->uid) { afb_req_fail(request, "sndcardpath_string_allocation", "Didn't succeed to store (allocate) 'uid' string"); HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, addedHal); return; } if(info) { addedHal->info = strdup(info); if(! addedHal->info) { afb_req_fail(request, "info_string_allocation", "Didn't succeed to store (allocate) 'info' string"); HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, addedHal); return; } } if(author) { addedHal->author = strdup(author); if(! addedHal->author) { afb_req_fail(request, "author_string_allocation", "Didn't succeed to store (allocate) 'author' string"); HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, addedHal); return; } } if(version) { addedHal->version = strdup(version); if(! addedHal->version) { afb_req_fail(request, "version_string_allocation", "Didn't succeed to store (allocate) 'version' string"); HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, addedHal); return; } } if(date) { addedHal->date = strdup(date); if(! addedHal->date) { afb_req_fail(request, "date_string_allocation", "Didn't succeed to store (allocate) 'date' string"); HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, addedHal); return; } } // TBD JAI: add subscription to this api status events, if subscription fails, remove hal from list afb_req_success(request, NULL, "Api successfully registered"); } void HalMgrUnload(afb_req_t request) { char *apiName; afb_api_t apiHandle; struct HalMgrData *halMgrData; struct HalData *halToRemove; json_object *requestJson; apiHandle = afb_req_get_api(request); if(! apiHandle) { afb_req_fail(request, "api_handle", "Can't get hal manager api handle"); return; } halMgrData = (struct HalMgrData *) afb_api_get_userdata(apiHandle); if(! halMgrData) { afb_req_fail(request, "hal_manager_data", "Can't get hal manager data"); return; } requestJson = afb_req_json(request); if(! requestJson) { afb_req_fail(request, "request_json", "Can't get request json"); return; } if(wrap_json_unpack(requestJson, "{s:s}", "api", &apiName)) { afb_req_fail(request, "requested_api", "Can't get api to remove"); return; } halToRemove = HalUtlSearchHalDataByApiName(&halMgrData->halDataListHead, apiName); if(! halToRemove) { afb_req_fail(request, "requested_api", "Can't find api to remove"); return; } if(halToRemove->internal) { afb_req_fail(request, "requested_api", "Can't remove an internal hal"); return; } if(HalUtlRemoveSelectedHalFromList(&halMgrData->halDataListHead, halToRemove)) { afb_req_fail(request, "unregister_error", "Didn't succeed to remove specified api"); return; } // TBD JAI: remove subscription to this api status events afb_req_success(request, NULL, "Api successfully unregistered"); } // TBD JAI : to implement void HalMgrSubscribeEvent(afb_req_t request) { AFB_REQ_WARNING(request, "Not implemented yet"); afb_req_success(request, NULL, NULL); } // TBD JAI : to implement void HalMgrUnsubscribeEvent(afb_req_t request) { AFB_REQ_WARNING(request, "Not implemented yet"); afb_req_success(request, NULL, NULL); }