From a62f961028f0cca3b4d3637e942f686c4f7144db Mon Sep 17 00:00:00 2001 From: Grigoris Pavlakis <grigpavl@ece.auth.gr> Date: Mon, 31 Dec 2018 17:18:33 +0200 Subject: [PATCH] Complete basic functionality (i.e. retrieval of function pointer and execution with arguments). Needs more testing and safeguarding against corrupted messages --- inc/Services/FunctionManagementService.hpp | 37 ++++++---- src/Services/FunctionManagementService.cpp | 83 ++++++++++++++-------- src/main.cpp | 8 +++ 3 files changed, 85 insertions(+), 43 deletions(-) diff --git a/inc/Services/FunctionManagementService.hpp b/inc/Services/FunctionManagementService.hpp index 49a69a0b..08f30c75 100644 --- a/inc/Services/FunctionManagementService.hpp +++ b/inc/Services/FunctionManagementService.hpp @@ -10,31 +10,42 @@ #include "etl/String.hpp" #include "Message.hpp" +#define FUNCMAPSIZE 128 // size of the function map in bytes (temporary, arbitrary) +#define MAXFUNCNAMELENGTH 32 // max length of the function name (temporary, arbitrary) +#define MAXARGLENGTH 32 // maximum argument byte string length + /** * Implementation of the ST[08] function management service * - * This class implements a basic framework for the ST[08] service as described in ECSS-E-ST-70-41C, - * pages 157-159. Final implementation is dependent on subsystem requirements which are, as of this - * writing, undefined yet. - * * + * This class implements a skeleton framework for the ST[08] service as described in + * ECSS-E-ST-70-41C, pages 157-159. Final implementation is dependent on subsystem requirements + * which are, as of this writing, undefined yet. + * + * WARNING! Any string handling in this class involves non-null-terminated strings! + * * @author Grigoris Pavlakis <grigpavl@ece.auth.gr> */ -#define FUNCMAPSIZE 5 // size of the function map (temporary, arbitrary) -#define MAXFUNCNAMELEN 128 // max length of the function (temporary, arbitrary) -#define MAXFUNCARGS 64 // maximum arguments that a function can hold -#define MAXARGLENGTH 32 // maximum argument name length - -typedef String<MAXFUNCNAMELEN> funcName; +typedef String<MAXFUNCNAMELENGTH> functionName; +typedef etl::map<functionName, void(*)(String<MAXARGLENGTH>), (const size_t) FUNCMAPSIZE> +PointerMap; class FunctionManagementService { - etl::map<funcName, void*, (const size_t) FUNCMAPSIZE> funcPtrIndex; - // map of function names to their pointers + /** + * Map of the function names to their respective pointers. Size controlled by FUNCMAPSIZE + */ + PointerMap funcPtrIndex; public: - //FunctionManagementService(); // dummy constructor (commented out to pacify clang-tidy) + /** + * Constructs the function pointer index. All functions to be included shall be visible to it. + * @param None + */ + FunctionManagementService(); + /** * Calls the function described in the TC[8,1] message *msg*, passing the arguments contained + * WARNING: Do not include any spaces in the arguments, they are ignored and replaced with NULL * @param msg A TC[8,1] message */ void call(Message msg); diff --git a/src/Services/FunctionManagementService.cpp b/src/Services/FunctionManagementService.cpp index 2294539c..313ee6d8 100644 --- a/src/Services/FunctionManagementService.cpp +++ b/src/Services/FunctionManagementService.cpp @@ -1,49 +1,72 @@ #include "Services/FunctionManagementService.hpp" -// Dummy functions which will populate the map -float dummy1(float a, int b) { - return a * b; +// Dummy functions which will populate the map. +// This one prints whatever bytes are contained in the argument. +void dummy1(const String<MAXARGLENGTH> a) { + std::cout << a.c_str() << std::endl; } -void dummy2(char c) { - std::cout << c << std::endl; -} -//FunctionManagementService::FunctionManagementService() { -// funcPtrIndex.insert(std::make_pair(String<MAXFUNCNAMELEN>("dummy1"), reinterpret_cast<void*> -// (&dummy1))); -// funcPtrIndex.insert(std::make_pair(String<MAXFUNCNAMELEN>("dummy2"), reinterpret_cast<void*> -// (&dummy2))); -// -// //reinterpret_cast<float(*)(float, int)>(funcPtrIndex["dummy1"])(3.14, 45); -// //reinterpret_cast<void(*)(char)>(funcPtrIndex["dummy2"])('h'); -//} +FunctionManagementService::FunctionManagementService() { + String<MAXFUNCNAMELENGTH> str(""); + str.append("dummy1"); + str.append(MAXFUNCNAMELENGTH - 6, '\0'); + void(*dummyPtr)(String<MAXARGLENGTH>) = &dummy1; + funcPtrIndex.insert(std::make_pair(str, dummyPtr)); +} void FunctionManagementService::call(Message msg){ - uint8_t funcName[MAXFUNCNAMELEN]; // the function's name + assert(msg.messageType == 1); + assert(msg.serviceType == 8); + + uint8_t funcName[MAXFUNCNAMELENGTH]; // the function's name + uint8_t funcArgs[MAXARGLENGTH]; // arguments for the function - // initialize the function name array - for (int i = 0; i < MAXFUNCNAMELEN; i++) { - funcName[i] = 0; + // initialize the function name and the argument arrays + for (int i = 0; i < MAXFUNCNAMELENGTH; i++) { + funcName[i] = '\0'; + funcArgs[i] = '\0'; } // isolate the function's name from the incoming message - for (int i = 0; i < MAXFUNCNAMELEN; i++) { + for (int i = 0; i < MAXFUNCNAMELENGTH; i++) { uint8_t currByte = msg.readByte(); - if (currByte == 0x00) { - funcName[i] = currByte; - break; + if (currByte == 0x20) { + continue; } funcName[i] = currByte; } - // isolate the number of args (currently an unsigned 32-bit number, the standard doesn't - // specify a maximum number) - uint32_t numOfArgs = msg.readUint32(); - for (int i = 0; i < numOfArgs; i++) { - // TODO: find a way to deduce the argument types as contained or store them somehow - // (finding a way to store them is better because it also solves the pointer casting - // problem) + // isolate the string containing the args (if string length exceeds max, the remaining bytes + // are silently ignored) + for (int i = 0; i < MAXARGLENGTH; i++) { + uint8_t currByte = msg.readByte(); + if (currByte == 0x20) { + continue; + } + funcArgs[i] = currByte; + } + + // locate the appropriate function pointer + String<MAXFUNCNAMELENGTH> name(funcName); + PointerMap::iterator iter = funcPtrIndex.find(name); + void(*selected)(String<MAXARGLENGTH>) = nullptr; + + if (iter == funcPtrIndex.end()) { + std::cout << "ERROR: Malformed query." << std::endl; + } + else { + selected = *iter->second; + } + + // send proper exec failure notification and terminate if name is incorrect + if (selected == nullptr) { + /** + * @todo Send failed start of execution + */ + return; } + // execute the function if there are no obvious flaws (defined in the standard, pg.158) + selected(funcArgs); } diff --git a/src/main.cpp b/src/main.cpp index 057c2313..37188eb7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -202,7 +202,15 @@ int main() { eventReportService.requestListOfDisabledEvents(eventMessage3); // ST[08] test + Message callMessage(8, 1, Message::TC, 1); + String<256> str = String<256>(""); + str.append("dummy1"); + str.append(MAXFUNCNAMELENGTH - 6, ' '); + str.append("THISSENTENCEISFALSE!"); + + callMessage.appendString<256>(str); FunctionManagementService fms; + fms.call(callMessage); return 0; } -- GitLab