diff --git a/pub/c/msg.h b/pub/c/msg.h index f32bac2..319ed35 100644 --- a/pub/c/msg.h +++ b/pub/c/msg.h @@ -504,8 +504,8 @@ struct ptpmgmt_msg_t { /** * Get send message dataField * @param[in] msg object - * @return pointer to send message dataField or null - * a pointer to the last setAction dataSend parameter. + * @return pointer to send message dataField or null. + * A pointer to the last setAction dataSend parameter. * @note You need to cast to proper structure depends on * management TLV ID. * @note In case you release this memory, @@ -797,6 +797,168 @@ ptpmgmt_msg ptpmgmt_msg_alloc(); */ ptpmgmt_msg ptpmgmt_msg_alloc_prms(ptpmgmt_cpMsgParams prms); +/** pointer to ptpmgmt TLV allocator structure */ +typedef struct ptpmgmt_tlv_mem_t *ptpmgmt_tlv_mem; +/** pointer to constant ptpmgmt message structure */ +typedef const struct ptpmgmt_tlv_mem_t *const_ptpmgmt_tlv_mem; + +/** + * Structure to track allocations for TLV objects and release all memory at once + */ +struct ptpmgmt_tlv_mem_t { + /**< @cond internal */ + void *_memHndl; /**< memory tracking */ + /**< @endcond */ + enum ptpmgmt_mng_vals_e id; /**< The TLV ID */ + void *tlv; /**< The TLV object */ + /** + * Free this tlv object and free all memory allocations + * @param[in, out] self memory object + */ + void (*free)(ptpmgmt_tlv_mem self); + /** + * clear the tlv and free all memory allocations + * @param[in, out] self memory object + */ + void (*clear)(ptpmgmt_tlv_mem self); + /** + * Allocate new empty tlv + * @param[in, out] self memory object + * @param[in] ID of tlv to allocate + * @return true on success + * @note On success this function will free any previous memory allocation + * and tlv allocated previously, same as calling clear() before. + */ + bool (*newTlv)(ptpmgmt_tlv_mem self, enum ptpmgmt_mng_vals_e ID); + /** + * Copy tlv + * @param[in, out] self memory object + * @param[in] other tlv to copy + * @return true on success + * @note On success this function will free any previous memory allocation + * and tlv allocated previously, same as calling clear() before. + */ + bool (*copy)(ptpmgmt_tlv_mem self, const_ptpmgmt_tlv_mem other); + /** + * Copy tlv + * @param[in, out] self memory object + * @param[in] ID of tlv to copy + * @param[in] tlv to copy + * @return true on success + * @note On success this function will free any previous memory allocation + * and tlv allocated previously, same as calling clear() before. + */ + bool (*copyTlv)(ptpmgmt_tlv_mem self, enum ptpmgmt_mng_vals_e ID, void *tlv); + /** + * get tlv ID + * @param[in] self memory object + * @return tlv ID + * @note On success this function will free any previous memory allocation + * and tlv allocated previously, same as calling clear() before. + */ + enum ptpmgmt_mng_vals_e(*getID)(const_ptpmgmt_tlv_mem self); + /** + * Get the tlv itsef + * @param[in] self memory object + * @return tlv + */ + void *(*getTLV)(const_ptpmgmt_tlv_mem self); + /** + * Allocate new memory to use with the tlv + * @param[in] self memory object + * @param[in] size for new allocation + * @return new memory + * @note memory will be free when freeing the tlv memory object + */ + void *(*allocMem)(ptpmgmt_tlv_mem self, size_t size); + /** + * Allocate new memory to use with the tlv + * @param[in] self memory object + * @param[in] number of elements + * @param[in] size of element + * @return new memory size of number of elements multuiple by size of element + * @note memory will be free when freeing the tlv memory object + */ + void *(*callocMem)(ptpmgmt_tlv_mem self, size_t number, size_t size); + /** + * Reallocate memory to use with the tlv + * @param[in] self memory object + * @param[in] memory pointer to reallocate + * @param[in] size for new allocation + * @return reallocated memory or null if fail + * @note memory will be free when freeing the tlv memory object + */ + void *(*reallocMem)(ptpmgmt_tlv_mem self, void *memory, size_t size); + /** + * Reallocate new memory to use with the tlv + * @param[in] self memory object + * @param[in] memory pointer to reallocate + * @param[in] number of elements + * @param[in] size of element + * @return new memory size of number of elements multuiple by size of element + * @note memory will be free when freeing the tlv memory object + */ + void *(*recallocMem)(ptpmgmt_tlv_mem self, void *memory, size_t number, + size_t size); + /** + * Allocate new PTPText with string + * @param[in] self memory object + * @param[in] str null terminated string used in new allocation + * @return PTPText with new allocated string or length zero if fail + */ + struct ptpmgmt_PTPText_t (*allocString)(ptpmgmt_tlv_mem self, const char *str); + /** + * Allocate new PTPText with string + * @param[in] self memory object + * @param[in] str string used in new allocation + * @param[in] len string length used in new allocation + * @return PTPText with new allocated string or length zero if fail + */ + struct ptpmgmt_PTPText_t (*allocStringLen)(ptpmgmt_tlv_mem self, + const char *str, size_t len); + /** + * reallocate new PTPText with string + * @param[in] self memory object + * @param[in] text object to reallocate + * @param[in] str null terminated string used in new allocation + * @return true on success + * @note The function relay on PTPText.lengthField value. + */ + bool (*reallocString)(ptpmgmt_tlv_mem self, struct ptpmgmt_PTPText_t *text, + const char *str); + /** + * reallocate new PTPText with string + * @param[in] self memory object + * @param[in] text object to reallocate + * @param[in] str string used in new allocation + * @param[in] len string length used in new allocation + * @return true on success + * @note The function relay on PTPText.lengthField value. + */ + bool (*reallocStringLen)(ptpmgmt_tlv_mem self, struct ptpmgmt_PTPText_t *text, + const char *str, size_t len); + /** + * Free memory use with the tlv + * @param[in] self memory object + * @param[in] mem to free + * @return true if memory belong to this memory tlv and successfuly released + */ + bool (*freeMem)(ptpmgmt_tlv_mem self, void *mem); + /** + * Free memory use in the PTPText + * @param[in] self memory object + * @param[in] mem to free + * @return true if memory belong to this memory tlv and successfuly released + */ + bool (*freeString)(ptpmgmt_tlv_mem self, struct ptpmgmt_PTPText_t *txt); +}; + +/** + * Alocate new tlv memory structure + * @return new tlv memory or null in case of error + */ +ptpmgmt_tlv_mem ptpmgmt_tlv_mem_alloc(); + #ifdef __cplusplus } #endif diff --git a/pub/msg.h b/pub/msg.h index f8d77d1..d3d6e0c 100644 --- a/pub/msg.h +++ b/pub/msg.h @@ -107,9 +107,6 @@ class Message managementErrorId_e m_errorId = (managementErrorId_e)0; PTPText_t m_errorDisplay; - /* Map to all management IDs */ - static const ManagementId_t mng_all_vals[]; - bool allowedAction(mng_vals_e id, actionField_e action); /* val in network order */ static bool findTlvId(uint16_t val, mng_vals_e &rid, implementSpecific_e spec); diff --git a/src/msg.cpp b/src/msg.cpp index 819b8a5..7e640c1 100644 --- a/src/msg.cpp +++ b/src/msg.cpp @@ -136,13 +136,29 @@ size_t MsgParams::countSigTlvs() const return allowSigTlvs.size(); } +/** Properties of a PTP management TLV */ +struct ManagementId_t { + uint16_t value; /**< managementId value */ + uint8_t scope; /**< Applies port or clock using scope_e */ + uint8_t allowed; /**< Allowed actions, bits from allowAction_e */ + /** + * TLV dataField size + * @li positive size of TLV dataField when it is fixed length + * @li 0 for TLV without dataField + * @li -1 TLV is not supported + * @li -2 The dataField length need calculation based on values + * @note the size might be even. Just pad another byte at the end. + */ + ssize_t size; +}; + // Shortcuts for the ids table #define use_GSC A_GET | A_SET | A_COMMAND #define use_GS A_GET | A_SET #define use_GL A_GET | A_USE_LINUXPTP #define use_GSL A_GET | A_SET | A_USE_LINUXPTP #define use_CL A_COMMAND | A_USE_LINUXPTP -const ManagementId_t Message::mng_all_vals[] = { +const static ManagementId_t mng_all_vals[] = { #define A(n, v, sc, a, sz, f)\ [n] = {.value = 0x##v, .scope = s_##sc, .allowed = a, .size = sz}, #include "ids.h" @@ -2010,4 +2026,431 @@ extern "C" { ptpmgmt_msg_asign_cb(m); return m; } + static const size_t tlv_c_size[] = { +#define _ptpmCaseNA(n) [PTPMGMT_##n] = 0, +#define _ptpmCaseUF(n) [PTPMGMT_##n] = sizeof(ptpmgmt_##n##_t), +#define A(n, v, sc, a, sz, f) _ptpmCase##f(n) +#include "ids.h" + }; + static void ptpmgmt_tlv_mem_free(ptpmgmt_tlv_mem self) + { + if(self != nullptr) { + free(self->tlv); + vector *n = (vector *)self->_memHndl; + if(n != nullptr) { + for(auto m : *n) + free(m); + delete n; + } + free(self); + } + } + static void _clearTlv(ptpmgmt_tlv_mem self) + { + free(self->tlv); + vector *n = (vector *)self->_memHndl; + if(n != nullptr) { + for(auto m : *n) + free(m); + n->clear(); + } + } + static void ptpmgmt_tlv_mem_clear(ptpmgmt_tlv_mem self) + { + if(self != nullptr) { + _clearTlv(self); + self->tlv = nullptr; + self->id = PTPMGMT_NULL_PTP_MANAGEMENT; + } + } + static void *_allocTLV(size_t &sz, ptpmgmt_mng_vals_e id) + { + if((mng_vals_e)id >= FIRST_MNG_ID && (mng_vals_e)id < LAST_MNG_ID) { + sz = tlv_c_size[id]; + if(sz > 0) + return malloc(sz); + } + return nullptr; + } + static bool ptpmgmt_tlv_mem_newTlv(ptpmgmt_tlv_mem self, ptpmgmt_mng_vals_e id) + { + if(self != nullptr) { + size_t sz; + void *tlv = _allocTLV(sz, id); + if(tlv != nullptr) { + _clearTlv(self); + memset(tlv, 0, sz); + self->tlv = tlv; + self->id = id; + return true; + } + } + return false; + } + static bool _copyText(vector &n, ptpmgmt_PTPText_t &t) + { + if(t.lengthField > 0 && t.textField != nullptr) { + size_t len = t.lengthField; + char *s = (char *)malloc(len + 1); + if(s == nullptr) + return false; + n.push_back(s); + memcpy(s, t.textField, len); + s[len] = 0; + t.textField = s; + return true; + } + return false; + } + static bool _copyBloc(vector &n, void *&p, size_t len) + { + if(len > 0 && p != nullptr) { + void *b = malloc(len); + if(b == nullptr) + return false; + n.push_back(b); + memcpy(b, p, len); + p = b; + return true; + } + return false; + } + static bool ptpmgmt_tlv_mem_copyTlv(ptpmgmt_tlv_mem self, ptpmgmt_mng_vals_e id, + void *tlv) + { + if(self == nullptr || tlv == nullptr) + return false; + vector *n = (vector *)self->_memHndl; + if(n == nullptr) + return false; + size_t sz; + void *ntlv = _allocTLV(sz, id); + if(ntlv == nullptr) + return false; + bool ret = true; + vector _nalc; + memcpy(ntlv, tlv, sz); + switch(id) { + case PTPMGMT_CLOCK_DESCRIPTION: { + auto *a = (ptpmgmt_CLOCK_DESCRIPTION_t *)ntlv; + void *n = a->physicalAddress; + void *n2 = a->protocolAddress.addressField; + ret = _copyText(_nalc, a->physicalLayerProtocol) && + _copyText(_nalc, a->productDescription) && + _copyText(_nalc, a->revisionData) && + _copyText(_nalc, a->userDescription) && + _copyBloc(_nalc, n, a->physicalAddressLength) && + _copyBloc(_nalc, n2, a->protocolAddress.addressLength); + a->physicalAddress = (uint8_t *)n; + a->protocolAddress.addressField = (uint8_t *)n2; + break; + } + case PTPMGMT_USER_DESCRIPTION: { + auto *a = (ptpmgmt_USER_DESCRIPTION_t *)ntlv; + ret = _copyText(_nalc, a->userDescription); + break; + } + case PTPMGMT_ALTERNATE_TIME_OFFSET_NAME: { + auto *a = (ptpmgmt_ALTERNATE_TIME_OFFSET_NAME_t *)ntlv; + ret = _copyText(_nalc, a->displayName); + break; + } + case PTPMGMT_PORT_PROPERTIES_NP: { + auto *a = (ptpmgmt_PORT_PROPERTIES_NP_t *)ntlv; + ret = _copyText(_nalc, a->interface); + break; + } + case PTPMGMT_FAULT_LOG: { + auto *a = (ptpmgmt_FAULT_LOG_t *)ntlv; + void *n = a->faultRecords; + ret = _copyBloc(_nalc, n, + a->numberOfFaultRecords * sizeof(ptpmgmt_FaultRecord_t)); + a->faultRecords = (ptpmgmt_FaultRecord_t *)n; + for(size_t i = 0; ret && i < a->numberOfFaultRecords; i++) + ret = _copyText(_nalc, a->faultRecords[i].faultName) && + _copyText(_nalc, a->faultRecords[i].faultValue) && + _copyText(_nalc, a->faultRecords[i].faultDescription); + break; + } + case PTPMGMT_PATH_TRACE_LIST: { + ptpmgmt_ClockIdentity_t nClock = { 0 }; + auto *a = (ptpmgmt_PATH_TRACE_LIST_t *)ntlv; + for(size_t sz = 0; memcmp(a->pathSequence[sz].v, nClock.v, + sizeof(nClock)); sz++); + void *n = a->pathSequence; + ret = _copyBloc(_nalc, n, sizeof(nClock) * sz); + a->pathSequence = (ptpmgmt_ClockIdentity_t *)n; + break; + } + case PTPMGMT_GRANDMASTER_CLUSTER_TABLE: { + auto *a = (ptpmgmt_GRANDMASTER_CLUSTER_TABLE_t *)ntlv; + void *n = a->PortAddress; + ret = _copyBloc(_nalc, n, + a->actualTableSize * sizeof(ptpmgmt_PortAddress_t)); + a->PortAddress = (ptpmgmt_PortAddress_t *)n; + for(size_t i = 0; ret && i < a->actualTableSize; i++) { + n = a->PortAddress[i].addressField; + ret = _copyBloc(_nalc, n, a->PortAddress[i].addressLength); + a->PortAddress[i].addressField = (uint8_t *)n; + } + break; + } + case PTPMGMT_UNICAST_MASTER_TABLE: { + auto *a = (ptpmgmt_UNICAST_MASTER_TABLE_t *)ntlv; + void *n = a->PortAddress; + ret = _copyBloc(_nalc, n, + a->actualTableSize * sizeof(ptpmgmt_PortAddress_t)); + a->PortAddress = (ptpmgmt_PortAddress_t *)n; + for(size_t i = 0; ret && i < a->actualTableSize; i++) { + n = a->PortAddress[i].addressField; + ret = _copyBloc(_nalc, n, a->PortAddress[i].addressLength); + a->PortAddress[i].addressField = (uint8_t *)n; + } + break; + } + case PTPMGMT_ACCEPTABLE_MASTER_TABLE: { + auto *a = (ptpmgmt_ACCEPTABLE_MASTER_TABLE_t *)ntlv; + void *n = a->list; + ret = _copyBloc(_nalc, n, + a->actualTableSize * sizeof(ptpmgmt_AcceptableMaster_t)); + a->list = (ptpmgmt_AcceptableMaster_t *)n; + break; + } + case PTPMGMT_UNICAST_MASTER_TABLE_NP: { + auto *a = (ptpmgmt_UNICAST_MASTER_TABLE_NP_t *)ntlv; + void *n = a->unicastMasters; + ret = _copyBloc(_nalc, n, a->actualTableSize * + sizeof(ptpmgmt_LinuxptpUnicastMaster_t)); + a->unicastMasters = (ptpmgmt_LinuxptpUnicastMaster_t *)n; + for(int i = 0; ret && i < a->actualTableSize; i++) { + n = a->unicastMasters[i].portAddress.addressField; + ret = _copyBloc(_nalc, n, + a->unicastMasters[i].portAddress.addressLength); + a->unicastMasters[i].portAddress.addressField = (uint8_t *)n; + } + break; + } + default: + break; + } + if(ret) { + _clearTlv(self); + self->tlv = ntlv; + self->id = id; + *n = _nalc; + } else { + for(auto m : _nalc) + free(m); + free(ntlv); + } + return ret; + } + static bool ptpmgmt_tlv_mem_copy(ptpmgmt_tlv_mem self, + const_ptpmgmt_tlv_mem other) + { + if(other != nullptr) + return ptpmgmt_tlv_mem_copyTlv(self, other->id, other->tlv); + return false; + } + static ptpmgmt_mng_vals_e ptpmgmt_tlv_mem_getID(const_ptpmgmt_tlv_mem self) + { + if(self != nullptr) + return self->id; + return PTPMGMT_NULL_PTP_MANAGEMENT; + } + static void *ptpmgmt_tlv_mem_getTLV(const_ptpmgmt_tlv_mem self) + { + if(self != nullptr) + return self->tlv; + return nullptr; + } + static void *ptpmgmt_tlv_mem_allocMem(ptpmgmt_tlv_mem self, size_t size) + { + if(self != nullptr && size > 0 && self->tlv != nullptr) { + vector *n = (vector *)self->_memHndl; + if(n != nullptr) { + void *m = malloc(size); + if(m != nullptr) { + memset(m, 0, size); + n->push_back(m); + return m; + } + } + } + return nullptr; + } + static void *ptpmgmt_tlv_mem_callocMem(ptpmgmt_tlv_mem self, size_t number, + size_t size) + { + if(self != nullptr && number > 0 && size > 0 && self->tlv != nullptr) + return ptpmgmt_tlv_mem_allocMem(self, number * size); + return nullptr; + } + void *_reallocMem(ptpmgmt_tlv_mem self, void *memory, size_t size) + { + vector *n = (vector *)self->_memHndl; + if(n != nullptr) { + auto it = n->begin(); + bool find = false; + for(; !find && it != n->end(); ++it) { + if(*it == memory) { + find = true; + break; + } + } + if(!find) + return nullptr; + void *nmem = realloc(memory, size); + if(nmem != nullptr) { + n->erase(it); + n->push_back(nmem); + } + return nmem; + } + return nullptr; + } + void *ptpmgmt_tlv_mem_reallocMem(ptpmgmt_tlv_mem self, void *memory, + size_t size) + { + if(self != nullptr && size > 0 && self->tlv != nullptr) { + if(memory == nullptr) + return ptpmgmt_tlv_mem_allocMem(self, size); + return _reallocMem(self, memory, size); + } + return nullptr; + } + void *ptpmgmt_tlv_mem_recallocMem(ptpmgmt_tlv_mem self, void *memory, + size_t number, size_t size) + { + if(self != nullptr && number > 0 && size > 0 && self->tlv != nullptr) + return ptpmgmt_tlv_mem_reallocMem(self, memory, number * size); + return nullptr; + } + static ptpmgmt_PTPText_t ptpmgmt_tlv_mem_allocStringLen(ptpmgmt_tlv_mem self, + const char *str, size_t len) + { + ptpmgmt_PTPText_t a; + if(self != nullptr && self->tlv != nullptr && str != nullptr && len > 0 && + len <= UINT8_MAX) { + vector *n = (vector *)self->_memHndl; + if(n != nullptr) { + char *s = (char *)malloc(len + 1); + if(s != nullptr) { + memcpy(s, str, len); + n->push_back(s); + a.lengthField = len; + a.textField = s; + s[len] = 0; + return a; + } + } + } + a.lengthField = 0; + a.textField = nullptr; + return a; + } + static ptpmgmt_PTPText_t ptpmgmt_tlv_mem_allocString(ptpmgmt_tlv_mem self, + const char *str) + { + if(self != nullptr && self->tlv != nullptr && str != nullptr) + return ptpmgmt_tlv_mem_allocStringLen(self, str, strlen(str)); + ptpmgmt_PTPText_t a; + a.lengthField = 0; + a.textField = nullptr; + return a; + } + bool ptpmgmt_tlv_mem_reallocStringLen(ptpmgmt_tlv_mem self, + struct ptpmgmt_PTPText_t *text, const char *str, size_t len) + { + if(self != nullptr && self->tlv != nullptr && text != nullptr && + str != nullptr && len > 0 && len <= UINT8_MAX) { + if(text->textField == nullptr || text->lengthField == 0) { + *text = ptpmgmt_tlv_mem_allocStringLen(self, str, len); + return text->lengthField > 0 && text->textField != nullptr ; + } + char *tgt = (char *)text->textField; + if(len > text->lengthField) { + tgt = (char *)_reallocMem(self, tgt, len); + if(tgt == nullptr) + return false; + text->textField = tgt; + } + memcpy(tgt, str, len); + tgt[len] = 0; + text->lengthField = len; + return true; + } + return false; + } + bool ptpmgmt_tlv_mem_reallocString(ptpmgmt_tlv_mem self, + struct ptpmgmt_PTPText_t *text, const char *str) + { + if(self != nullptr && self->tlv != nullptr && text != nullptr + && str != nullptr) + return ptpmgmt_tlv_mem_reallocStringLen(self, text, str, strlen(str)); + return false; + } + static bool _freeMem(ptpmgmt_tlv_mem self, const void *mem) + { + vector *n = (vector *)self->_memHndl; + if(n != nullptr) { + for(auto it = n->begin(); it != n->end(); ++it) + if(*it == mem) { + free(*it); + n->erase(it); + return true; + } + } + return false; + } + static bool ptpmgmt_tlv_mem_freeMem(ptpmgmt_tlv_mem self, void *mem) + { + if(self != nullptr && mem != nullptr) + return _freeMem(self, mem); + return false; + } + static bool ptpmgmt_tlv_mem_freeString(ptpmgmt_tlv_mem self, + ptpmgmt_PTPText_t *txt) + { + if(self != nullptr && txt != nullptr && txt->textField != nullptr && + _freeMem(self, txt->textField)) { + txt->lengthField = 0; + txt->textField = nullptr; + return true; + } + return false; + } + ptpmgmt_tlv_mem ptpmgmt_tlv_mem_alloc() + { + ptpmgmt_tlv_mem m = (ptpmgmt_tlv_mem)malloc(sizeof(ptpmgmt_tlv_mem_t)); + if(m == nullptr) + return nullptr; + vector *n = new vector; + if(n == nullptr) { + free(m); + return nullptr; + } + m->_memHndl = (void *)n; + m->id = PTPMGMT_NULL_PTP_MANAGEMENT; + m->tlv = nullptr; +#define T_ASGN(n) m->n = ptpmgmt_tlv_mem_##n + T_ASGN(free); + T_ASGN(clear); + T_ASGN(newTlv); + T_ASGN(copy); + T_ASGN(copyTlv); + T_ASGN(getID); + T_ASGN(getTLV); + T_ASGN(allocMem); + T_ASGN(callocMem); + T_ASGN(reallocMem); + T_ASGN(recallocMem); + T_ASGN(allocString); + T_ASGN(allocStringLen); + T_ASGN(reallocString); + T_ASGN(reallocStringLen); + T_ASGN(freeMem); + T_ASGN(freeString); + return m; + } } diff --git a/src/types.m4 b/src/types.m4 index 8b18030..72be7ca 100644 --- a/src/types.m4 +++ b/src/types.m4 @@ -895,21 +895,6 @@ cpp_cod(` static size_t size() {')dnl cpp_cod(` return PortIdentity_t::size() + sizeof alternatePriority1;')dnl cpp_cod(` }')dnl }; -/** Properties of a PTP management TLV */ -strc(ManagementId_t) { - uint16_t value; /**< managementId value */ - uint8_t scope; /**< Applies port or clock using scope_e */ - uint8_t allowed; /**< Allowed actions, bits from allowAction_e */ - /** - * TLV dataField size - * @li positive size of TLV dataField when it is fixed length - * @li 0 for TLV without dataField - * @li -1 TLV is not supported - * @li -2 The dataField length need calculation based on values - * @note the size might be even. Just pad another byte at the end. - */ - ssize_t size; -}; /** Receive Authentication modes */ enm(MsgParams_RcvAuth_e) sz(: uint8_t ){ diff --git a/uctest/msg.c b/uctest/msg.c index cd42fd9..a5dc507 100644 --- a/uctest/msg.c +++ b/uctest/msg.c @@ -1952,3 +1952,229 @@ Test(MessageTest, MethodGetSigMngTlvType) cr_expect(eq(int, p1->priority1, 137)); m->free(m); } + +// ptpmgmt_tlv_mem ptpmgmt_tlv_mem_alloc() +// enum ptpmgmt_mng_vals_e getID(const_ptpmgmt_tlv_mem self) +// enum ptpmgmt_mng_vals_e id +// void *getTLV(const_ptpmgmt_tlv_mem self) +// void *tlv +// bool newTlv(ptpmgmt_tlv_mem self, enum ptpmgmt_mng_vals_e ID) +// void free(ptpmgmt_tlv_mem self) +Test(TlvMem, newTlv) +{ + ptpmgmt_tlv_mem t = ptpmgmt_tlv_mem_alloc(); + cr_assert(not(zero(ptr, t))); + cr_expect(eq(int, t->getID(t), PTPMGMT_NULL_PTP_MANAGEMENT)); + cr_expect(eq(int, t->id, PTPMGMT_NULL_PTP_MANAGEMENT)); + cr_assert(zero(ptr, t->getTLV(t))); + cr_assert(zero(ptr, t->tlv)); + cr_expect(t->newTlv(t, PTPMGMT_USER_DESCRIPTION)); + cr_expect(eq(int, t->getID(t), PTPMGMT_USER_DESCRIPTION)); + cr_expect(eq(int, t->id, PTPMGMT_USER_DESCRIPTION)); + cr_assert(not(zero(ptr, t->getTLV(t)))); + cr_assert(not(zero(ptr, t->tlv))); + t->free(t); +} + +// bool copyTlv(ptpmgmt_tlv_mem self, enum ptpmgmt_mng_vals_e ID, void *tlv) +// void clear(ptpmgmt_tlv_mem self) +Test(TlvMem, copyTlv) +{ + ptpmgmt_tlv_mem t = ptpmgmt_tlv_mem_alloc(); + struct ptpmgmt_ALTERNATE_TIME_OFFSET_NAME_t v = { + .keyField = 54, + .displayName.lengthField = 4, + .displayName.textField = "AaBb" + }; + cr_expect(t->copyTlv(t, PTPMGMT_ALTERNATE_TIME_OFFSET_NAME, &v)); + cr_expect(eq(int, t->getID(t), PTPMGMT_ALTERNATE_TIME_OFFSET_NAME)); + void *p = t->getTLV(t); + cr_assert(not(zero(ptr, p))); + struct ptpmgmt_ALTERNATE_TIME_OFFSET_NAME_t *v2 = (struct + ptpmgmt_ALTERNATE_TIME_OFFSET_NAME_t *)p; + cr_assert(not(zero(ptr, v2))); + cr_expect(ne(ptr, v2, &v)); + cr_expect(ne(ptr, (char *)v2->displayName.textField, + (char *)v.displayName.textField)); + cr_expect(eq(int, v2->keyField, 54)); + cr_expect(eq(u8, v2->displayName.lengthField, 4)); + cr_expect(eq(str, (char *)v2->displayName.textField, "AaBb")); + t->clear(t); + cr_expect(eq(int, t->getID(t), PTPMGMT_NULL_PTP_MANAGEMENT)); + cr_assert(zero(ptr, t->getTLV(t))); + t->free(t); +} + +// bool copy(ptpmgmt_tlv_mem self, const_ptpmgmt_tlv_mem other) +// void *allocMem(ptpmgmt_tlv_mem self, size_t size) +// struct ptpmgmt_PTPText_t allocString(ptpmgmt_tlv_mem self, const char *str) +// struct ptpmgmt_PTPText_t allocStringLen(ptpmgmt_tlv_mem self, const char *str, +// size_t len) +Test(TlvMem, copy) +{ + ptpmgmt_tlv_mem t1 = ptpmgmt_tlv_mem_alloc(); + cr_expect(t1->newTlv(t1, PTPMGMT_CLOCK_DESCRIPTION)); + void *p = t1->getTLV(t1); + cr_assert(not(zero(ptr, p))); + struct ptpmgmt_CLOCK_DESCRIPTION_t *v = (struct ptpmgmt_CLOCK_DESCRIPTION_t *)p; + v->clockType = 1687; + v->physicalLayerProtocol = t1->allocString(t1, "test12"); + v->physicalAddressLength = 4; + v->physicalAddress = t1->allocMem(t1, 4); + memcpy(v->physicalAddress, "\x1\x2\x3\x4", 4); + v->protocolAddress.networkProtocol = ptpmgmt_UDP_IPv4; + v->protocolAddress.addressLength = 4; + v->protocolAddress.addressField = (uint8_t *)"\x12\x0\x0\x31"; + v->manufacturerIdentity[0] = 0x24; + v->manufacturerIdentity[1] = 0x35; + v->manufacturerIdentity[2] = 0x78; + v->productDescription = t1->allocStringLen(t1, "Description", 4); + v->revisionData = t1->allocString(t1, "rev"); + v->userDescription = t1->allocString(t1, "des123"); + v->profileIdentity[0] = 0x32; + v->profileIdentity[1] = 0x25; + v->profileIdentity[2] = 0x12; + v->profileIdentity[3] = 0x63; + v->profileIdentity[4] = 0x4d; + v->profileIdentity[5] = 0x27; + ptpmgmt_tlv_mem t2 = ptpmgmt_tlv_mem_alloc(); + cr_expect(t2->copy(t2, t1)); + t1->clear(t1); + struct ptpmgmt_CLOCK_DESCRIPTION_t *v2 = (struct ptpmgmt_CLOCK_DESCRIPTION_t *) + t2->getTLV(t2); + cr_assert(not(zero(ptr, v2))); + cr_expect(eq(int, t2->getID(t2), PTPMGMT_CLOCK_DESCRIPTION)); + cr_expect(eq(u16, v2->clockType, 1687)); + cr_expect(eq(u8, v2->physicalLayerProtocol.lengthField, 6)); + cr_expect(eq(str, (char *)v2->physicalLayerProtocol.textField, "test12")); + cr_expect(eq(u16, v2->physicalAddressLength, 4)); + cr_expect(zero(memcmp(v2->physicalAddress, "\x1\x2\x3\x4", 4))); + cr_expect(eq(int, v2->protocolAddress.networkProtocol, ptpmgmt_UDP_IPv4)); + cr_expect(eq(u16, v2->protocolAddress.addressLength, 4)); + cr_expect(zero(memcmp(v2->protocolAddress.addressField, "\x12\x0\x0\x31", 4))); + cr_expect(zero(memcmp(v2->manufacturerIdentity, "\x24\x35\x78", 3))); + cr_expect(eq(u8, v2->productDescription.lengthField, 4)); + cr_expect(eq(str, (char *)v2->productDescription.textField, "Desc")); + cr_expect(eq(u8, v2->revisionData.lengthField, 3)); + cr_expect(eq(str, (char *)v2->revisionData.textField, "rev")); + cr_expect(eq(u8, v2->userDescription.lengthField, 6)); + cr_expect(eq(str, (char *)v2->userDescription.textField, "des123")); + cr_expect(zero(memcmp(v2->profileIdentity, "\x32\x25\x12\x63\x4d\x27", 6))); + t1->free(t1); + t2->free(t2); +} + +// void *callocMem(ptpmgmt_tlv_mem self, size_t number, size_t size) +// void *recallocMem(ptpmgmt_tlv_mem self, void *memory, size_t number, size_t size) +Test(TlvMem, callocMem) +{ + ptpmgmt_tlv_mem t = ptpmgmt_tlv_mem_alloc(); + cr_expect(t->newTlv(t, PTPMGMT_ACCEPTABLE_MASTER_TABLE)); + void *p = t->getTLV(t); + cr_assert(not(zero(ptr, p))); + struct ptpmgmt_ACCEPTABLE_MASTER_TABLE_t *v = (struct + ptpmgmt_ACCEPTABLE_MASTER_TABLE_t *)p; + v->actualTableSize = 3; + v->list = t->callocMem(t, 3, sizeof(struct ptpmgmt_AcceptableMaster_t)); + v->list[0].alternatePriority1 = 1; + memcpy(v->list[0].acceptablePortIdentity.clockIdentity.v, + "\x1\x0\x1\x0\x1\x0\x1\x0", 8); + v->list[0].acceptablePortIdentity.portNumber = 1; + v->list[1].alternatePriority1 = 2; + memcpy(v->list[1].acceptablePortIdentity.clockIdentity.v, + "\x2\x0\x2\x0\x2\x0\x2\x0", 8); + v->list[1].acceptablePortIdentity.portNumber = 2; + v->list[2].alternatePriority1 = 3; + memcpy(v->list[2].acceptablePortIdentity.clockIdentity.v, + "\x3\x0\x3\x0\x3\x0\x3\x0", 8); + v->list[2].acceptablePortIdentity.portNumber = 3; + void *n = t->recallocMem(t, v->list, 4, + sizeof(struct ptpmgmt_AcceptableMaster_t)); + cr_assert(not(zero(ptr, n))); + v->actualTableSize = 4; + v->list = n; + v->list[3].alternatePriority1 = 4; + memcpy(v->list[3].acceptablePortIdentity.clockIdentity.v, + "\x4\x0\x4\x0\x4\x0\x4\x0", 8); + v->list[3].acceptablePortIdentity.portNumber = 4; + ptpmgmt_tlv_mem t2 = ptpmgmt_tlv_mem_alloc(); + cr_expect(t2->copy(t2, t)); + struct ptpmgmt_ACCEPTABLE_MASTER_TABLE_t *v2 = (struct + ptpmgmt_ACCEPTABLE_MASTER_TABLE_t *)t2->getTLV(t2); + cr_assert(not(zero(ptr, v2))); + cr_expect(eq(int, t2->getID(t2), PTPMGMT_ACCEPTABLE_MASTER_TABLE)); + cr_expect(eq(i16, v->actualTableSize, 4)); + cr_expect(eq(u8, v->list[0].alternatePriority1, 1)); + cr_expect(zero(memcmp(v->list[0].acceptablePortIdentity.clockIdentity.v, + "\x1\x0\x1\x0\x1\x0\x1\x0", 8))); + cr_expect(eq(u16, v->list[0].acceptablePortIdentity.portNumber, 1)); + cr_expect(eq(u8, v->list[1].alternatePriority1, 2)); + cr_expect(zero(memcmp(v->list[1].acceptablePortIdentity.clockIdentity.v, + "\x2\x0\x2\x0\x2\x0\x2\x0", 8))); + cr_expect(eq(u16, v->list[1].acceptablePortIdentity.portNumber, 2)); + cr_expect(eq(u8, v->list[2].alternatePriority1, 3)); + cr_expect(zero(memcmp(v->list[2].acceptablePortIdentity.clockIdentity.v, + "\x3\x0\x3\x0\x3\x0\x3\x0", 8))); + cr_expect(eq(u16, v->list[2].acceptablePortIdentity.portNumber, 3)); + cr_expect(eq(u8, v->list[3].alternatePriority1, 4)); + cr_expect(zero(memcmp(v->list[3].acceptablePortIdentity.clockIdentity.v, + "\x4\x0\x4\x0\x4\x0\x4\x0", 8))); + cr_expect(eq(u16, v->list[3].acceptablePortIdentity.portNumber, 4)); + t->free(t); + t2->free(t2); +} + +// bool reallocString(ptpmgmt_tlv_mem self, struct ptpmgmt_PTPText_t *text, +// const char *str) +// bool reallocStringLen(ptpmgmt_tlv_mem self, struct ptpmgmt_PTPText_t *text, +// const char *str, size_t len) +// bool freeString(ptpmgmt_tlv_mem self, struct ptpmgmt_PTPText_t *txt) +Test(TlvMem, reallocString) +{ + ptpmgmt_tlv_mem t = ptpmgmt_tlv_mem_alloc(); + cr_expect(t->newTlv(t, PTPMGMT_USER_DESCRIPTION)); + void *p = t->getTLV(t); + cr_assert(not(zero(ptr, p))); + struct ptpmgmt_USER_DESCRIPTION_t *v = (struct ptpmgmt_USER_DESCRIPTION_t *)p; + cr_expect(t->reallocString(t, &v->userDescription, "desc 12")); + cr_expect(eq(u8, v->userDescription.lengthField, 7)); + cr_expect(eq(str, (char *)v->userDescription.textField, "desc 12")); + char *a1 = (char *)v->userDescription.textField; + cr_expect(t->reallocStringLen(t, &v->userDescription, "123456", 4)); + cr_expect(eq(ptr, a1, (char *)v->userDescription.textField)); + cr_expect(eq(u8, v->userDescription.lengthField, 4)); + cr_expect(eq(str, (char *)v->userDescription.textField, "1234")); + cr_expect(t->reallocStringLen(t, &v->userDescription, "1234567890", 10)); + cr_expect(eq(u8, v->userDescription.lengthField, 10)); + cr_expect(eq(str, (char *)v->userDescription.textField, "1234567890")); + cr_expect(t->freeString(t, &v->userDescription)); + cr_expect(eq(u8, v->userDescription.lengthField, 0)); + cr_expect(zero(ptr, (char *)v->userDescription.textField)); + t->free(t); +} + +// void *reallocMem(ptpmgmt_tlv_mem self, void *memory, size_t size) +// bool freeMem(ptpmgmt_tlv_mem self, void *mem) +Test(TlvMem, reallocMem) +{ + ptpmgmt_tlv_mem t = ptpmgmt_tlv_mem_alloc(); + cr_expect(t->newTlv(t, PTPMGMT_UNICAST_MASTER_TABLE)); + struct ptpmgmt_UNICAST_MASTER_TABLE_t *v = (struct + ptpmgmt_UNICAST_MASTER_TABLE_t *)t->getTLV(t); + cr_assert(not(zero(ptr, v))); + v->logQueryInterval = 5; //Integer8_t + v->actualTableSize = 2; // UInteger16_t + v->PortAddress = t->callocMem(t, 2, sizeof(struct ptpmgmt_PortAddress_t)); + v->PortAddress[0].networkProtocol = ptpmgmt_UDP_IPv4; + v->PortAddress[0].addressLength = 4; // UInteger16_t + v->PortAddress[0].addressField = t->reallocMem(t, + v->PortAddress[0].addressField, 4); + cr_expect(not(zero(ptr, v->PortAddress[0].addressField))); + v->PortAddress[1].networkProtocol = ptpmgmt_UDP_IPv6; + v->PortAddress[1].addressLength = 6; + v->PortAddress[1].addressField = t->reallocMem(t, + v->PortAddress[0].addressField, 6); + cr_expect(not(zero(ptr, v->PortAddress[1].addressField))); + cr_expect(t->freeMem(t, v->PortAddress)); + t->free(t); +}