Skip to content

Commit

Permalink
Improve C dispatcher.
Browse files Browse the repository at this point in the history
Use interface to manipulate the dispatcher object.
So we improve backward compatibility better.

Signed-off-by: Erez Geva <ErezGeva2@gmail.com>
  • Loading branch information
erezgeva committed Feb 18, 2025
1 parent 5a433bd commit 149c734
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 49 deletions.
48 changes: 46 additions & 2 deletions pub/c/msgCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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
Expand Down
18 changes: 16 additions & 2 deletions src/callDef.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions src/msgCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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{\
Expand All @@ -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);
Expand All @@ -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));
}
Expand Down
107 changes: 62 additions & 45 deletions uctest/msgCall.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,27 @@ 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)
{
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];
Expand All @@ -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);
}

Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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);
}

0 comments on commit 149c734

Please sign in to comment.