Skip to content

Commit

Permalink
Add RPC tests #sonar
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-kirienko committed Aug 11, 2023
1 parent 277a0f3 commit 73d82c7
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 39 deletions.
61 changes: 32 additions & 29 deletions libudpard/udpard.c
Original file line number Diff line number Diff line change
Expand Up @@ -1643,16 +1643,16 @@ static inline int_fast8_t rxRPCSearch(void* const user_reference, // NOSONAR Ca
const struct UdpardTreeNode* node)
{
UDPARD_ASSERT((user_reference != NULL) && (node != NULL));
return compare32(((const struct UdpardRxRPC*) user_reference)->service_id,
((const struct UdpardRxRPC*) (const void*) node)->service_id);
return compare32(((const struct UdpardRxRPCPort*) user_reference)->service_id,
((const struct UdpardRxRPCPort*) (const void*) node)->service_id);
}

static inline int_fast8_t rxRPCSearchByServiceID(void* const user_reference, // NOSONAR Cavl API requires non-const.
const struct UdpardTreeNode* node)
{
UDPARD_ASSERT((user_reference != NULL) && (node != NULL));
return compare32(*(const UdpardPortID*) user_reference,
((const struct UdpardRxRPC*) (const void*) node)->service_id);
((const struct UdpardRxRPCPort*) (const void*) node)->service_id);
}

// -------------------------------------------------- RX API --------------------------------------------------
Expand Down Expand Up @@ -1726,6 +1726,7 @@ int_fast8_t udpardRxRPCDispatcherInit(struct UdpardRxRPCDispatcher* const self,
if ((self != NULL) && (local_node_id <= UDPARD_NODE_ID_MAX) && rxValidateMemoryResources(memory))
{
memZero(sizeof(*self), self);
self->local_node_id = local_node_id;
self->udp_ip_endpoint = makeServiceUDPIPEndpoint(local_node_id);
self->memory = memory;
self->request_ports = NULL;
Expand All @@ -1736,27 +1737,27 @@ int_fast8_t udpardRxRPCDispatcherInit(struct UdpardRxRPCDispatcher* const self,
}

int_fast8_t udpardRxRPCDispatcherListen(struct UdpardRxRPCDispatcher* const self,
struct UdpardRxRPC* const service,
struct UdpardRxRPCPort* const port,
const UdpardPortID service_id,
const bool is_request,
const size_t extent)
{
int_fast8_t result = -UDPARD_ERROR_ARGUMENT;
if ((self != NULL) && (service != NULL) && (service_id <= UDPARD_SERVICE_ID_MAX))
if ((self != NULL) && (port != NULL) && (service_id <= UDPARD_SERVICE_ID_MAX))
{
const int_fast8_t cancel_result = udpardRxRPCDispatcherCancel(self, service_id, is_request);
UDPARD_ASSERT((cancel_result == 0) || (cancel_result == 1)); // We already checked the arguments.
memZero(sizeof(*service), service);
service->service_id = service_id;
rxPortInit(&service->port);
service->port.extent = extent;
service->user_reference = NULL;
memZero(sizeof(*port), port);
port->service_id = service_id;
rxPortInit(&port->port);
port->port.extent = extent;
port->user_reference = NULL;
// Insert the newly initialized service into the tree.
const struct UdpardTreeNode* const item = cavlSearch(is_request ? &self->request_ports : &self->response_ports,
service,
port,
&rxRPCSearch,
&avlTrivialFactory);
UDPARD_ASSERT((item != NULL) && (item == &service->base));
UDPARD_ASSERT((item != NULL) && (item == &port->base));
(void) item;
result = (cancel_result > 0) ? 0 : 1;
}
Expand All @@ -1772,8 +1773,8 @@ int_fast8_t udpardRxRPCDispatcherCancel(struct UdpardRxRPCDispatcher* const self
{
UdpardPortID service_id_mutable = service_id;
struct UdpardTreeNode** const root = is_request ? &self->request_ports : &self->response_ports;
struct UdpardRxRPC* const item =
(struct UdpardRxRPC*) (void*) cavlSearch(root, &service_id_mutable, &rxRPCSearchByServiceID, NULL);
struct UdpardRxRPCPort* const item =
(struct UdpardRxRPCPort*) (void*) cavlSearch(root, &service_id_mutable, &rxRPCSearchByServiceID, NULL);
if (item != NULL)
{
cavlRemove(root, &item->base);
Expand All @@ -1788,32 +1789,34 @@ int_fast8_t udpardRxRPCDispatcherReceive(struct UdpardRxRPCDispatcher* const sel
const UdpardMicrosecond timestamp_usec,
const struct UdpardMutablePayload datagram_payload,
const uint_fast8_t redundant_iface_index,
struct UdpardRxRPC** const out_service,
struct UdpardRxRPCPort** const out_port,
struct UdpardRxRPCTransfer* const out_transfer)
{
bool release = true;
int_fast8_t result = -UDPARD_ERROR_ARGUMENT;
if ((self != NULL) && (timestamp_usec != TIMESTAMP_UNSET) && (datagram_payload.data != NULL) &&
(redundant_iface_index < UDPARD_NETWORK_INTERFACE_COUNT_MAX) && (out_transfer != NULL))
{
result = 0; // Invalid frames cannot complete a transfer, so zero is the new default.
RxFrame frame = {0};
if (rxParseFrame(datagram_payload, &frame) &&
((frame.meta.data_specifier & DATA_SPECIFIER_SERVICE_NOT_MESSAGE_MASK) != 0))
result = 0; // Invalid frames cannot complete a transfer, so zero is the new default.
RxFrame frame = {0};
const bool accept = rxParseFrame(datagram_payload, &frame) &&
((frame.meta.data_specifier & DATA_SPECIFIER_SERVICE_NOT_MESSAGE_MASK) != 0) &&
(frame.meta.dst_node_id == self->local_node_id);
if (accept)
{
// Service transfers cannot be anonymous. This is enforced by the rxParseFrame function; we re-check this.
UDPARD_ASSERT(frame.meta.src_node_id != UDPARD_NODE_ID_UNSET);
// Extract the data specifier from the frame. Update the transfer object even if no transfer is completed.
// Parse the data specifier in the frame.
out_transfer->is_request =
(frame.meta.data_specifier & DATA_SPECIFIER_SERVICE_REQUEST_NOT_RESPONSE_MASK) != 0;
out_transfer->service_id = frame.meta.data_specifier & DATA_SPECIFIER_SERVICE_ID_MASK;
// Search for the RPC-port that is registered for this service transfer in the tree.
struct UdpardRxRPC* const item =
(struct UdpardRxRPC*) (void*) cavlSearch(out_transfer->is_request ? &self->request_ports
: &self->response_ports,
&out_transfer->service_id,
&rxRPCSearchByServiceID,
NULL);
struct UdpardRxRPCPort* const item =
(struct UdpardRxRPCPort*) (void*) cavlSearch(out_transfer->is_request ? &self->request_ports
: &self->response_ports,
&out_transfer->service_id,
&rxRPCSearchByServiceID,
NULL);
// If such a port is found, accept the frame on it.
if (item != NULL)
{
Expand All @@ -1825,10 +1828,10 @@ int_fast8_t udpardRxRPCDispatcherReceive(struct UdpardRxRPCDispatcher* const sel
&out_transfer->base);
release = false;
}
// Expose the RPC-service instance to the caller if requested.
if (out_service != NULL)
// Expose the port instance to the caller if requested.
if (out_port != NULL)
{
*out_service = item;
*out_port = item;
}
}
}
Expand Down
26 changes: 16 additions & 10 deletions libudpard/udpard.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@
///
/// Graphically, the service dispatcher pipeline is arranged as shown below.
///
/// REDUNDANT INTERFACE A ---> UDP SOCKET ---+ +---> RPC-SERVICE X ---> SERIALIZED TRANSFERS
/// REDUNDANT INTERFACE A ---> UDP SOCKET ---+ +---> RPC PORT X ---> SERIALIZED TRANSFERS
/// | |
/// REDUNDANT INTERFACE B ---> UDP SOCKET ---+---> SERVICE DISPATCHER ---+---> RPC-SERVICE Y ---> SERIALIZED TRANSFERS
/// REDUNDANT INTERFACE B ---> UDP SOCKET ---+---> SERVICE DISPATCHER ---+---> RPC PORT Y ---> SERIALIZED TRANSFERS
/// | |
/// ... ---+ +---> ...
///
Expand Down Expand Up @@ -886,7 +886,7 @@ int_fast8_t udpardRxSubscriptionReceive(struct UdpardRxSubscription* const self,

/// An RPC-service RX port models the interest of the application in receiving RPC-service transfers of
/// a particular kind (request or response) and a particular service-ID.
struct UdpardRxRPC
struct UdpardRxRPCPort
{
/// READ-ONLY
struct UdpardTreeNode base;
Expand Down Expand Up @@ -916,6 +916,12 @@ struct UdpardRxRPC
/// Anonymous nodes (nodes without a node-ID of their own) cannot use RPC-services.
struct UdpardRxRPCDispatcher
{
/// The local node-ID has to be stored to facilitate correctness checking of incoming transfers.
/// This value shall not be modified after initialization. If the local node needs to change its node-ID,
/// this dispatcher instance must be destroyed and a new one created instead.
/// READ-ONLY
UdpardNodeID local_node_id;

/// The IP address and UDP port number where UDP/IP datagrams carrying RPC-service transfers destined to this node
/// will be sent.
/// READ-ONLY
Expand Down Expand Up @@ -947,7 +953,7 @@ struct UdpardRxRPCTransfer
///
/// 3. Per redundant network interface:
/// - Create a new socket bound to the IP multicast group address and UDP port number specified in the
/// udp_ip_endpoint field of the initialized service dispatcher instance. The library will determine the
/// udp_ip_endpoint field of the initialized RPC dispatcher instance. The library will determine the
/// endpoint to use based on the node-ID.
///
/// 4. Announce its interest in specific RPC-services (requests and/or responses) by calling
Expand All @@ -970,7 +976,7 @@ int_fast8_t udpardRxRPCDispatcherInit(struct UdpardRxRPCDispatcher* const self,
const struct UdpardRxMemoryResources memory);

/// This function lets the application register its interest in a particular service-ID and kind (request/response)
/// by creating an RPC-service RX port. The service pointer shall retain validity until its unregistration or until
/// by creating an RPC-service RX port. The port pointer shall retain validity until its unregistration or until
/// the dispatcher is destroyed. The service instance shall not be moved or destroyed.
///
/// If such registration already exists, it will be unregistered first as if udpardRxRPCDispatcherCancel was
Expand All @@ -991,7 +997,7 @@ int_fast8_t udpardRxRPCDispatcherInit(struct UdpardRxRPCDispatcher* const self,
/// This function does not allocate new memory. The function may deallocate memory if such registration already
/// existed; the deallocation behavior is specified in the documentation for udpardRxRPCDispatcherCancel.
int_fast8_t udpardRxRPCDispatcherListen(struct UdpardRxRPCDispatcher* const self,
struct UdpardRxRPC* const service,
struct UdpardRxRPCPort* const port,
const UdpardPortID service_id,
const bool is_request,
const size_t extent);
Expand All @@ -1010,12 +1016,12 @@ int_fast8_t udpardRxRPCDispatcherCancel(struct UdpardRxRPCDispatcher* const self
const UdpardPortID service_id,
const bool is_request);

/// Datagrams received from the sockets of this service dispatcher are fed into this function.
/// Datagrams received from the sockets of this RPC service dispatcher are fed into this function.
/// It is the analog of udpardRxSubscriptionReceive for RPC-service transfers.
/// Please refer to the documentation of udpardRxSubscriptionReceive for the usage information.
///
/// The "out_service" pointer-to-pointer can be used to retrieve the specific UdpardRxRPC instance that was used to
/// process the received transfer. Remember that each UdpardRxRPC instance has a user reference field,
/// The "out_port" pointer-to-pointer can be used to retrieve the specific UdpardRxRPCPort instance that was used to
/// process the received transfer. Remember that each UdpardRxRPCPort instance has a user reference field,
/// which in combination with this feature can be used to construct OOP interfaces on top of the library.
/// If this is not needed, the pointer-to-pointer can be NULL.
///
Expand All @@ -1024,7 +1030,7 @@ int_fast8_t udpardRxRPCDispatcherReceive(struct UdpardRxRPCDispatcher* const sel
const UdpardMicrosecond timestamp_usec,
const struct UdpardMutablePayload datagram_payload,
const uint_fast8_t redundant_iface_index,
struct UdpardRxRPC** const out_service,
struct UdpardRxRPCPort** const out_port,
struct UdpardRxRPCTransfer* const out_transfer);

// =====================================================================================================================
Expand Down
Loading

0 comments on commit 73d82c7

Please sign in to comment.