55
66#include "udpard.h"
77#include "_udpard_cavl.h"
8+
89#include <string.h>
910
1011// --------------------------------------------- BUILD CONFIGURATION ---------------------------------------------
@@ -280,9 +281,6 @@ typedef struct
280281{
281282 struct UdpardTxItem base ;
282283 enum UdpardPriority priority ; ///< Do we need this exposed in the public structure? We already have DSCP there.
283- // The MISRA violation here is hard to get rid of without having to allocate a separate memory block for the
284- // payload, which is much more costly risk-wise.
285- byte_t payload_buffer []; // NOSONAR MISRA C 18.7 Flexible array member.
286284} TxItem ;
287285
288286/// Chain of TX frames prepared for insertion into a TX queue.
@@ -293,15 +291,21 @@ typedef struct
293291 size_t count ;
294292} TxChain ;
295293
296- static inline TxItem * txNewItem (const struct UdpardMemoryResource memory ,
297- const uint_least8_t dscp_value_per_priority [UDPARD_PRIORITY_MAX + 1U ],
298- const UdpardMicrosecond deadline_usec ,
299- const enum UdpardPriority priority ,
300- const struct UdpardUDPIPEndpoint endpoint ,
301- const size_t datagram_payload_size ,
302- void * const user_transfer_reference )
294+ static inline bool txValidateMemoryResources (const struct UdpardTxMemoryResources memory )
295+ {
296+ return (memory .fragment .allocate != NULL ) && (memory .fragment .deallocate != NULL ) &&
297+ (memory .payload .allocate != NULL ) && (memory .payload .deallocate != NULL );
298+ }
299+
300+ static inline TxItem * txNewItem (const struct UdpardTxMemoryResources memory ,
301+ const uint_least8_t dscp_value_per_priority [UDPARD_PRIORITY_MAX + 1U ],
302+ const UdpardMicrosecond deadline_usec ,
303+ const enum UdpardPriority priority ,
304+ const struct UdpardUDPIPEndpoint endpoint ,
305+ const size_t datagram_payload_size ,
306+ void * const user_transfer_reference )
303307{
304- TxItem * const out = ( TxItem * ) memAlloc (memory , sizeof (TxItem ) + datagram_payload_size );
308+ TxItem * out = memAlloc (memory . fragment , sizeof (TxItem ));
305309 if (out != NULL )
306310 {
307311 // No tree linkage by default.
@@ -317,9 +321,18 @@ static inline TxItem* txNewItem(const struct UdpardMemoryResource memory,
317321 out -> base .dscp = dscp_value_per_priority [priority ];
318322 out -> base .destination = endpoint ;
319323 out -> base .user_transfer_reference = user_transfer_reference ;
320- // The payload points to the buffer already allocated.
321- out -> base .datagram_payload .size = datagram_payload_size ;
322- out -> base .datagram_payload .data = & out -> payload_buffer [0 ];
324+
325+ void * const payload_data = memAlloc (memory .payload , datagram_payload_size );
326+ if (NULL != payload_data )
327+ {
328+ out -> base .datagram_payload .data = payload_data ;
329+ out -> base .datagram_payload .size = datagram_payload_size ;
330+ }
331+ else
332+ {
333+ memFree (memory .fragment , sizeof (TxItem ), out );
334+ out = NULL ;
335+ }
323336 }
324337 return out ;
325338}
@@ -390,14 +403,14 @@ static inline byte_t* txSerializeHeader(byte_t* const destination_buffe
390403
391404/// Produces a chain of Tx queue items for later insertion into the Tx queue. The tail is NULL if OOM.
392405/// The caller is responsible for freeing the memory allocated for the chain.
393- static inline TxChain txMakeChain (const struct UdpardMemoryResource memory ,
394- const uint_least8_t dscp_value_per_priority [UDPARD_PRIORITY_MAX + 1U ],
395- const size_t mtu ,
396- const UdpardMicrosecond deadline_usec ,
397- const TransferMetadata meta ,
398- const struct UdpardUDPIPEndpoint endpoint ,
399- const struct UdpardPayload payload ,
400- void * const user_transfer_reference )
406+ static inline TxChain txMakeChain (const struct UdpardTxMemoryResources memory ,
407+ const uint_least8_t dscp_value_per_priority [UDPARD_PRIORITY_MAX + 1U ],
408+ const size_t mtu ,
409+ const UdpardMicrosecond deadline_usec ,
410+ const TransferMetadata meta ,
411+ const struct UdpardUDPIPEndpoint endpoint ,
412+ const struct UdpardPayload payload ,
413+ void * const user_transfer_reference )
401414{
402415 UDPARD_ASSERT (mtu > 0 );
403416 UDPARD_ASSERT ((payload .data != NULL ) || (payload .size == 0U ));
@@ -430,8 +443,9 @@ static inline TxChain txMakeChain(const struct UdpardMemoryResource memory,
430443 {
431444 break ;
432445 }
433- const bool last = (payload_size_with_crc - offset ) <= mtu ;
434- byte_t * write_ptr = txSerializeHeader (& item -> payload_buffer [0 ], meta , (uint32_t ) out .count , last );
446+ const bool last = (payload_size_with_crc - offset ) <= mtu ;
447+ byte_t * const dst_buffer = item -> base .datagram_payload .data ;
448+ byte_t * write_ptr = txSerializeHeader (dst_buffer , meta , (uint32_t ) out .count , last );
435449 if (offset < payload .size )
436450 {
437451 const size_t progress = smaller (payload .size - offset , mtu );
@@ -446,7 +460,7 @@ static inline TxChain txMakeChain(const struct UdpardMemoryResource memory,
446460 {
447461 const size_t crc_offset = offset - payload .size ;
448462 UDPARD_ASSERT (crc_offset < TRANSFER_CRC_SIZE_BYTES );
449- const size_t available = item -> base .datagram_payload .size - (size_t ) (write_ptr - & item -> payload_buffer [ 0 ] );
463+ const size_t available = item -> base .datagram_payload .size - (size_t ) (write_ptr - dst_buffer );
450464 UDPARD_ASSERT (available <= TRANSFER_CRC_SIZE_BYTES );
451465 const size_t write_size = smaller (TRANSFER_CRC_SIZE_BYTES - crc_offset , available );
452466 // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
@@ -517,7 +531,7 @@ static inline int32_t txPush(struct UdpardTx* const tx,
517531 while (head != NULL )
518532 {
519533 struct UdpardTxItem * const next = head -> next_in_transfer ;
520- memFree (tx -> memory , sizeof ( TxItem ) + head -> datagram_payload . size , head );
534+ udpardTxFree (tx -> memory , head );
521535 head = next ;
522536 }
523537 }
@@ -526,13 +540,13 @@ static inline int32_t txPush(struct UdpardTx* const tx,
526540 return out ;
527541}
528542
529- int_fast8_t udpardTxInit (struct UdpardTx * const self ,
530- const UdpardNodeID * const local_node_id ,
531- const size_t queue_capacity ,
532- const struct UdpardMemoryResource memory )
543+ int_fast8_t udpardTxInit (struct UdpardTx * const self ,
544+ const UdpardNodeID * const local_node_id ,
545+ const size_t queue_capacity ,
546+ const struct UdpardTxMemoryResources memory )
533547{
534548 int_fast8_t ret = - UDPARD_ERROR_ARGUMENT ;
535- if ((NULL != self ) && (NULL != local_node_id ) && (memory . allocate != NULL ) && ( memory . deallocate != NULL ))
549+ if ((NULL != self ) && (NULL != local_node_id ) && txValidateMemoryResources (memory ))
536550 {
537551 ret = 0 ;
538552 memZero (sizeof (* self ), self );
@@ -639,14 +653,14 @@ int32_t udpardTxRespond(struct UdpardTx* const self,
639653 return out ;
640654}
641655
642- const struct UdpardTxItem * udpardTxPeek (const struct UdpardTx * const self )
656+ struct UdpardTxItem * udpardTxPeek (const struct UdpardTx * const self )
643657{
644- const struct UdpardTxItem * out = NULL ;
658+ struct UdpardTxItem * out = NULL ;
645659 if (self != NULL )
646660 {
647661 // Paragraph 6.7.2.1.15 of the C standard says:
648662 // A pointer to a structure object, suitably converted, points to its initial member, and vice versa.
649- out = (const struct UdpardTxItem * ) (void * ) cavlFindExtremum (self -> root , false);
663+ out = (struct UdpardTxItem * ) (void * ) cavlFindExtremum (self -> root , false);
650664 }
651665 return out ;
652666}
@@ -671,11 +685,16 @@ struct UdpardTxItem* udpardTxPop(struct UdpardTx* const self, const struct Udpar
671685 return out ;
672686}
673687
674- void udpardTxFree (const struct UdpardMemoryResource memory , struct UdpardTxItem * const item )
688+ void udpardTxFree (const struct UdpardTxMemoryResources memory , struct UdpardTxItem * const item )
675689{
676690 if (item != NULL )
677691 {
678- memFree (memory , sizeof (TxItem ) + item -> datagram_payload .size , item );
692+ if (item -> datagram_payload .data != NULL )
693+ {
694+ memFree (memory .payload , item -> datagram_payload .size , item -> datagram_payload .data );
695+ }
696+
697+ memFree (memory .fragment , sizeof (TxItem ), item );
679698 }
680699}
681700
0 commit comments