diff --git a/pub/c/msgCall.h b/pub/c/msgCall.h index 4832e6fd..2b80f958 100644 --- a/pub/c/msgCall.h +++ b/pub/c/msgCall.h @@ -17,10 +17,54 @@ extern "C" { #endif +/** pointer to a ptpmgmt dispatcher structure callback */ +typedef void (*ptpmgmt_dispatcher_callback)(void *cookie, ptpmgmt_msg msg, + const void *tlv, const char *idStr); +/** pointer to ptpmgmt dispatcher structure noTlv callback */ +typedef void (*ptpmgmt_dispatcher_noTlv_callback)(void *cookie, + ptpmgmt_msg msg); +/** pointer to ptpmgmt dispatcher structure noTlvCallBack callback */ +typedef void (*ptpmgmt_dispatcher_noTlvCallBack_callback)(void *cookie, + ptpmgmt_msg msg, const char *idStr); + +/** + * Allocate new empty dispatcher object + * @return new dispatcher object or null on error + */ +ptpmgmt_dispatcher ptpmgmt_dispatcher_alloc(); +/** + * Assign tlv ID with callback function + * @param[in] d pointer to dispatcher object + * @param[in] tlv_id TLV ID + * @param[in] callback to use + * @return true on success + * @note the callback parameters must match the callback in the structure + */ +bool ptpmgmt_dispatcher_assign(ptpmgmt_dispatcher d, + enum ptpmgmt_mng_vals_e tlv_id, ptpmgmt_dispatcher_callback callback); +/** + * Assign noTlv callback function + * @param[in] d pointer to dispatcher object + * @param[in] callback to use + * @return true on success + * @note We call the noTlv callback in case the TLV ID is unknown + */ +bool ptpmgmt_dispatcher_assign_noTlv(ptpmgmt_dispatcher d, + ptpmgmt_dispatcher_noTlv_callback callback); +/** + * Assign noTlvCallBack callback function + * @param[in] d pointer to dispatcher object + * @param[in] callback to use + * @return true on success + * @note We call the noTlvCallBack callback in case + * we do not have a callback to a TLV ID + */ +bool ptpmgmt_dispatcher_assign_noTlvCallBack(ptpmgmt_dispatcher d, + ptpmgmt_dispatcher_noTlvCallBack_callback callback); /** * Call handler based on Message last received message * @param[in] cookie user cookie passed to user callback - * @param[in] d pointer to structure with the callbacks + * @param[in] d pointer to dispatcher object * @param[in] msg pointer to message object wrapper * @note Do not forget to null unused callbacks */ @@ -29,7 +73,7 @@ void ptpmgmt_callHadler(void *cookie, const_ptpmgmt_dispatcher d, /** * Call handler based on supplied TLV * @param[in] cookie user cookie passed to user callback - * @param[in] d pointer to structure with the callbacks + * @param[in] d pointer to dispatcher object * @param[in] msg pointer to message object wrapper * @param[in] tlv_id TLV ID * @param[in] tlv pointer to a TLV of TLV ID diff --git a/src/callDef.m4 b/src/callDef.m4 index f34a9e04..4786542d 100644 --- a/src/callDef.m4 +++ b/src/callDef.m4 @@ -31,10 +31,14 @@ incb(msg) ns_s() -c_cod(`/** pointer to ptpmgmt dispatcher structure */')dnl +c_cod(`/** pointer to constant ptpmgmt dispatcher structure */')dnl c_cod(`typedef const struct ptpmgmt_dispatcher_t *const_ptpmgmt_dispatcher;')dnl -c_cod(`/** pointer to ptpmgmt builder structure */')dnl +c_cod(`/** pointer to ptpmgmt dispatcher structure */')dnl +c_cod(`typedef struct ptpmgmt_dispatcher_t *ptpmgmt_dispatcher;')dnl +c_cod(`/** pointer to constant ptpmgmt builder structure */')dnl c_cod(`typedef const struct ptpmgmt_builder_t *const_ptpmgmt_builder;')dnl +c_cod(`/** pointer to ptpmgmt builder structure */')dnl +c_cod(`typedef struct ptpmgmt_builder_t *ptpmgmt_builder;')dnl c_cod(`')dnl /** * @brief Dispacher for management TLV @@ -60,6 +64,11 @@ cpp_cod(` /**< @endcond */')dnl cpp_cod(` public:')dnl cpp_cod(` BaseMngDispatchCallback() = default;')dnl cpp_cod(` virtual ~BaseMngDispatchCallback() = default;')dnl +c_cod(` /**')dnl +c_cod(` * Free this dispacher object')dnl +c_cod(` * @param[in, out] dispacher object to free')dnl +c_cod(` */')dnl +c_cod(` void (*free)(ptpmgmt_dispatcher dsp);')dnl define(D,` /** * Handle $1 management TLV c_cod(` * @param[in, out] cookie pointer to a user cookie')dnl @@ -112,6 +121,11 @@ c_cod(`struct ptpmgmt_builder_t {')dnl cpp_cod(` public:')dnl cpp_cod(` BaseMngBuildCallback() = default;')dnl cpp_cod(` virtual ~BaseMngBuildCallback() = default;')dnl +c_cod(` /**')dnl +c_cod(` * Free this builder object')dnl +c_cod(` * @param[in, out] builder object to free')dnl +c_cod(` */')dnl +c_cod(` void (*free)(ptpmgmt_builder dsp);')dnl define(B,` /** * Handle $1 management TLV * Set values in the new TLV diff --git a/src/msgCall.cpp b/src/msgCall.cpp index 277f287d..506b11fa 100644 --- a/src/msgCall.cpp +++ b/src/msgCall.cpp @@ -76,6 +76,55 @@ __PTPMGMT_NAMESPACE_END extern "C" { // C interfaces + static void ptpmgmt_dispatcher_free(ptpmgmt_dispatcher me) + { + free(me); + } + ptpmgmt_dispatcher ptpmgmt_dispatcher_alloc() + { + static const size_t sz = sizeof(ptpmgmt_dispatcher_t); + ptpmgmt_dispatcher me = (ptpmgmt_dispatcher)malloc(sz); + if(me == nullptr) + return nullptr; + memset(me, 0, sz); + me->free = ptpmgmt_dispatcher_free; + return me; + } +#define _ptpmCaseUF(n)\ +case PTPMGMT_##n:\ + d->n##_h = (void (*)(void*, ptpmgmt_msg,\ + const ptpmgmt_##n##_t*, const char*))callback;\ + return true; +#define A(n, v, sc, a, sz, f) _ptpmCase##f(n) + bool ptpmgmt_dispatcher_assign(ptpmgmt_dispatcher d, + enum ptpmgmt_mng_vals_e tlv_id, ptpmgmt_dispatcher_callback callback) + { + if(d == nullptr || callback == (ptpmgmt_dispatcher_callback)nullptr) + return false; + switch(tlv_id) { +#include "ids.h" + default: + break; + } + return false; + } + bool ptpmgmt_dispatcher_assign_noTlv(ptpmgmt_dispatcher d, + ptpmgmt_dispatcher_noTlv_callback callback) + { + if(d == nullptr || callback == (ptpmgmt_dispatcher_noTlv_callback)nullptr) + return false; + d->noTlv = callback; + return true; + } + bool ptpmgmt_dispatcher_assign_noTlvCallBack(ptpmgmt_dispatcher d, + ptpmgmt_dispatcher_noTlvCallBack_callback callback) + { + if(d == nullptr || + callback == (ptpmgmt_dispatcher_noTlvCallBack_callback)nullptr) + return false; + d->noTlvCallBack = callback; + return true; + } #define _ptpmCaseUF(n)\ case PTPMGMT_##n:if(d->n##_h != nullptr){\ d->n##_h(cookie, msg, (const ptpmgmt_##n##_t*)tlv, #n);}else{\ @@ -84,6 +133,8 @@ case PTPMGMT_##n:if(d->n##_h != nullptr){\ void ptpmgmt_callHadler_tlv(void *cookie, const_ptpmgmt_dispatcher d, ptpmgmt_msg msg, ptpmgmt_mng_vals_e tlv_id, const void *tlv) { + if(d == nullptr) + return; if(tlv == nullptr) { if(d->noTlv != nullptr) d->noTlv(cookie, msg); @@ -100,6 +151,8 @@ case PTPMGMT_##n:if(d->n##_h != nullptr){\ void ptpmgmt_callHadler(void *cookie, const_ptpmgmt_dispatcher d, ptpmgmt_msg msg) { + if(d == nullptr || msg == nullptr) + return; ptpmgmt_callHadler_tlv(cookie, d, msg, msg->getTlvId(msg), msg->getData(msg)); } diff --git a/uctest/msgCall.c b/uctest/msgCall.c index 6557c3a6..aff13243 100644 --- a/uctest/msgCall.c +++ b/uctest/msgCall.c @@ -37,6 +37,13 @@ static void noTlvCallBack(void *cookie, ptpmgmt_msg msg, const char *idStr) } // Tests callHadler method with paresed empty TLV +// ptpmgmt_dispatcher ptpmgmt_dispatcher_alloc() +// bool ptpmgmt_dispatcher_assign(ptpmgmt_dispatcher d, +// enum ptpmgmt_mng_vals_e tlv_id, ptpmgmt_dispatcher_callback callback) +// bool ptpmgmt_dispatcher_assign_noTlv(ptpmgmt_dispatcher d, +// ptpmgmt_dispatcher_noTlv_callback callback) +// bool ptpmgmt_dispatcher_assign_noTlvCallBack(ptpmgmt_dispatcher d, +// ptpmgmt_dispatcher_noTlvCallBack_callback callback) // void ptpmgmt_callHadler(void *cookie, const_ptpmgmt_dispatcher d, // ptpmgmt_msg msg) Test(MessageDispatcherTest, MethodParsedCallHadlerEmptyTLV) @@ -44,11 +51,13 @@ Test(MessageDispatcherTest, MethodParsedCallHadlerEmptyTLV) struct flags f; memset(&f, 0, sizeof f); ptpmgmt_msg msg = ptpmgmt_msg_alloc(); - struct ptpmgmt_dispatcher_t d; - memset(&d, 0, sizeof d); - d.PRIORITY1_h = PRIORITY1_h; - d.noTlv = noTlv; - d.noTlvCallBack = noTlvCallBack; + cr_assert(not(zero(ptr, msg))); + ptpmgmt_dispatcher d = ptpmgmt_dispatcher_alloc(); + cr_assert(not(zero(ptr, d))); + cr_assert(ptpmgmt_dispatcher_assign(d, PTPMGMT_PRIORITY1, + (ptpmgmt_dispatcher_callback)PRIORITY1_h)); + cr_assert(ptpmgmt_dispatcher_assign_noTlv(d, noTlv)); + cr_assert(ptpmgmt_dispatcher_assign_noTlvCallBack(d, noTlvCallBack)); cr_expect(msg->setAction(msg, PTPMGMT_COMMAND, PTPMGMT_ENABLE_PORT, NULL)); cr_expect(eq(int, msg->getBuildTlvId(msg), PTPMGMT_ENABLE_PORT)); uint8_t buf[70]; @@ -60,9 +69,10 @@ Test(MessageDispatcherTest, MethodParsedCallHadlerEmptyTLV) cr_expect(eq(int, msg->parse(msg, buf, 54), PTPMGMT_MNG_PARSE_ERROR_OK)); f.noTlvCalled = false; // Dispatch ENABLE_PORT - ptpmgmt_callHadler(&f, &d, msg); + ptpmgmt_callHadler(&f, d, msg); // ENABLE_PORT is an empty code, which do not have a TLV, so noTlv is called! cr_expect(f.noTlvCalled); + d->free(d); msg->free(msg); } @@ -74,37 +84,40 @@ Test(MessageDispatcherTest, MethodProvidedCallHadlerEmptyTLV) struct flags f; memset(&f, 0, sizeof f); ptpmgmt_msg msg = ptpmgmt_msg_alloc(); - struct ptpmgmt_dispatcher_t d; - memset(&d, 0, sizeof d); - d.PRIORITY1_h = PRIORITY1_h; - d.noTlv = noTlv; - d.noTlvCallBack = noTlvCallBack; + cr_assert(not(zero(ptr, msg))); + ptpmgmt_dispatcher d = ptpmgmt_dispatcher_alloc(); + cr_assert(not(zero(ptr, d))); + cr_assert(ptpmgmt_dispatcher_assign(d, PTPMGMT_PRIORITY1, + (ptpmgmt_dispatcher_callback)PRIORITY1_h)); + cr_assert(ptpmgmt_dispatcher_assign_noTlv(d, noTlv)); + cr_assert(ptpmgmt_dispatcher_assign_noTlvCallBack(d, noTlvCallBack)); f.noTlvCalled = false; // Dispatch ENABLE_PORT - ptpmgmt_callHadler_tlv(&f, &d, msg, PTPMGMT_ENABLE_PORT, NULL); + ptpmgmt_callHadler_tlv(&f, d, msg, PTPMGMT_ENABLE_PORT, NULL); // ENABLE_PORT is an empty code, which do not have a TLV, so noTlv is called! cr_expect(f.noTlvCalled); char dummy[2]; f.noTlvCalled = false; // Dispatch ENABLE_PORT - ptpmgmt_callHadler_tlv(&f, &d, msg, PTPMGMT_ENABLE_PORT, dummy); + ptpmgmt_callHadler_tlv(&f, d, msg, PTPMGMT_ENABLE_PORT, dummy); cr_expect(f.noTlvCalled); + d->free(d); msg->free(msg); } // Tests callHadler method with paresed TLV -// void ptpmgmt_callHadler(void *cookie, const_ptpmgmt_dispatcher d, -// ptpmgmt_msg msg) Test(MessageDispatcherTest, MethodParsedCallHadlerTLV) { struct flags f; memset(&f, 0, sizeof f); ptpmgmt_msg msg = ptpmgmt_msg_alloc(); - struct ptpmgmt_dispatcher_t d; - memset(&d, 0, sizeof d); - d.PRIORITY1_h = PRIORITY1_h; - d.noTlv = noTlv; - d.noTlvCallBack = noTlvCallBack; + cr_assert(not(zero(ptr, msg))); + ptpmgmt_dispatcher d = ptpmgmt_dispatcher_alloc(); + cr_assert(not(zero(ptr, d))); + cr_assert(ptpmgmt_dispatcher_assign(d, PTPMGMT_PRIORITY1, + (ptpmgmt_dispatcher_callback)PRIORITY1_h)); + cr_assert(ptpmgmt_dispatcher_assign_noTlv(d, noTlv)); + cr_assert(ptpmgmt_dispatcher_assign_noTlvCallBack(d, noTlvCallBack)); struct ptpmgmt_PRIORITY1_t p; p.priority1 = 137; f.noTlvCalled = false; @@ -118,52 +131,54 @@ Test(MessageDispatcherTest, MethodParsedCallHadlerTLV) buf[46] = PTPMGMT_RESPONSE; cr_expect(eq(int, msg->parse(msg, buf, 56), PTPMGMT_MNG_PARSE_ERROR_OK)); // Dispatch PRIORITY1 in parsed message - ptpmgmt_callHadler(&f, &d, msg); + ptpmgmt_callHadler(&f, d, msg); // PRIORITY1 have callback cr_expect(not(f.noTlvCalled)); cr_expect(eq(u8, f.tlv.priority1, p.priority1)); cr_expect(eq(str, (char *)f.idStr_PRIORITY1, "PRIORITY1")); + d->free(d); msg->free(msg); } // Tests callHadler with method with provided TLV -// void ptpmgmt_callHadler_tlv(void *cookie, const_ptpmgmt_dispatcher d, -// ptpmgmt_msg msg, enum ptpmgmt_mng_vals_e tlv_id, const void *tlv) Test(MessageDispatcherTest, MethodProvidedCallHadlerTLV) { struct flags f; memset(&f, 0, sizeof f); ptpmgmt_msg msg = ptpmgmt_msg_alloc(); - struct ptpmgmt_dispatcher_t d; - memset(&d, 0, sizeof d); - d.PRIORITY1_h = PRIORITY1_h; - d.noTlv = noTlv; - d.noTlvCallBack = noTlvCallBack; + cr_assert(not(zero(ptr, msg))); + ptpmgmt_dispatcher d = ptpmgmt_dispatcher_alloc(); + cr_assert(not(zero(ptr, d))); + cr_assert(ptpmgmt_dispatcher_assign(d, PTPMGMT_PRIORITY1, + (ptpmgmt_dispatcher_callback)PRIORITY1_h)); + cr_assert(ptpmgmt_dispatcher_assign_noTlv(d, noTlv)); + cr_assert(ptpmgmt_dispatcher_assign_noTlvCallBack(d, noTlvCallBack)); struct ptpmgmt_PRIORITY1_t p; p.priority1 = 137; f.noTlvCalled = false; // Dispatch PRIORITY1 - ptpmgmt_callHadler_tlv(&f, &d, msg, PTPMGMT_PRIORITY1, &p); + ptpmgmt_callHadler_tlv(&f, d, msg, PTPMGMT_PRIORITY1, &p); // PRIORITY1 have callback cr_expect(not(f.noTlvCalled)); cr_expect(eq(u8, f.tlv.priority1, p.priority1)); cr_expect(eq(str, (char *)f.idStr_PRIORITY1, "PRIORITY1")); + d->free(d); msg->free(msg); } // Tests callHadler method with paresed TLV without callback -// void ptpmgmt_callHadler(void *cookie, const_ptpmgmt_dispatcher d, -// ptpmgmt_msg msg) Test(MessageDispatcherTest, MethodParsedCallHadlerTLVNoCallback) { struct flags f; memset(&f, 0, sizeof f); ptpmgmt_msg msg = ptpmgmt_msg_alloc(); - struct ptpmgmt_dispatcher_t d; - memset(&d, 0, sizeof d); - d.PRIORITY1_h = PRIORITY1_h; - d.noTlv = noTlv; - d.noTlvCallBack = noTlvCallBack; + cr_assert(not(zero(ptr, msg))); + ptpmgmt_dispatcher d = ptpmgmt_dispatcher_alloc(); + cr_assert(not(zero(ptr, d))); + cr_assert(ptpmgmt_dispatcher_assign(d, PTPMGMT_PRIORITY1, + (ptpmgmt_dispatcher_callback)PRIORITY1_h)); + cr_assert(ptpmgmt_dispatcher_assign_noTlv(d, noTlv)); + cr_assert(ptpmgmt_dispatcher_assign_noTlvCallBack(d, noTlvCallBack)); struct ptpmgmt_PRIORITY2_t p; p.priority2 = 137; f.noTlvCalled = false; @@ -177,37 +192,39 @@ Test(MessageDispatcherTest, MethodParsedCallHadlerTLVNoCallback) buf[46] = PTPMGMT_RESPONSE; cr_expect(eq(int, msg->parse(msg, buf, 56), PTPMGMT_MNG_PARSE_ERROR_OK)); // Dispatch PRIORITY2 in parsed message - ptpmgmt_callHadler(&f, &d, msg); + ptpmgmt_callHadler(&f, d, msg); // PRIORITY2 do not have callback cr_expect(not(f.noTlvCalled)); cr_expect(eq(u8, f.tlv.priority1, 0)); cr_expect(zero(ptr, (char *)f.idStr_PRIORITY1)); cr_expect(eq(str, (char *)f.idStr_noTlvCallBack, "PRIORITY2")); + d->free(d); msg->free(msg); } // Tests callHadler with method with provided TLV without callback -// void ptpmgmt_callHadler_tlv(void *cookie, const_ptpmgmt_dispatcher d, -// ptpmgmt_msg msg, enum ptpmgmt_mng_vals_e tlv_id, const void *tlv) Test(MessageDispatcherTest, MethodProvidedCallHadlerTLVNoCallback) { struct flags f; memset(&f, 0, sizeof f); ptpmgmt_msg msg = ptpmgmt_msg_alloc(); - struct ptpmgmt_dispatcher_t d; - memset(&d, 0, sizeof d); - d.PRIORITY1_h = PRIORITY1_h; - d.noTlv = noTlv; - d.noTlvCallBack = noTlvCallBack; + cr_assert(not(zero(ptr, msg))); + ptpmgmt_dispatcher d = ptpmgmt_dispatcher_alloc(); + cr_assert(not(zero(ptr, d))); + cr_assert(ptpmgmt_dispatcher_assign(d, PTPMGMT_PRIORITY1, + (ptpmgmt_dispatcher_callback)PRIORITY1_h)); + cr_assert(ptpmgmt_dispatcher_assign_noTlv(d, noTlv)); + cr_assert(ptpmgmt_dispatcher_assign_noTlvCallBack(d, noTlvCallBack)); struct ptpmgmt_PRIORITY2_t p; p.priority2 = 137; f.noTlvCalled = false; // Dispatch PRIORITY2 - ptpmgmt_callHadler_tlv(&f, &d, msg, PTPMGMT_PRIORITY2, &p); + ptpmgmt_callHadler_tlv(&f, d, msg, PTPMGMT_PRIORITY2, &p); // PRIORITY2 do not have callback cr_expect(not(f.noTlvCalled)); cr_expect(eq(u8, f.tlv.priority1, 0)); cr_expect(zero(ptr, (char *)f.idStr_PRIORITY1)); cr_expect(eq(str, (char *)f.idStr_noTlvCallBack, "PRIORITY2")); + d->free(d); msg->free(msg); }