Skip to content

Commit c719fae

Browse files
Improve the subscription API: return incumbent if exists
1 parent e7f7733 commit c719fae

9 files changed

Lines changed: 369 additions & 265 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ int main(void)
8989

9090
// Subscribe for messages.
9191
canard_subscription_t sub;
92-
if (!canard_subscribe_13b(&node, &sub, 7509U, 63U, CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_us, &sub_vtable)) {
92+
const canard_subscription_t* const installed =
93+
canard_subscribe_13b(&node, &sub, 7509U, 63U, CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_us, &sub_vtable);
94+
if (installed != &sub) { // NULL on invalid args, otherwise points to the incumbent subscription.
9395
canard_destroy(&node);
9496
return -1;
9597
}

demos/heartbeat_monitor.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,12 @@ int main(const int argc, const char* const argv[])
305305

306306
// Subscribe to Cyphal heartbeat (subject 7509, 13-bit subject-ID space).
307307
canard_subscription_t sub_cyphal;
308-
if (!canard_subscribe_13b(&ins,
309-
&sub_cyphal,
310-
CYPHAL_HEARTBEAT_SUBJECT_ID,
311-
CYPHAL_HEARTBEAT_EXTENT,
312-
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_us,
313-
&g_sub_vtable_cyphal)) {
308+
if (canard_subscribe_13b(&ins,
309+
&sub_cyphal,
310+
CYPHAL_HEARTBEAT_SUBJECT_ID,
311+
CYPHAL_HEARTBEAT_EXTENT,
312+
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_us,
313+
&g_sub_vtable_cyphal) != &sub_cyphal) {
314314
(void)fputs("canard_subscribe_13b failed\n", stderr);
315315
canard_destroy(&ins);
316316
(void)close(sock);
@@ -320,13 +320,13 @@ int main(const int argc, const char* const argv[])
320320
// Subscribe to DroneCAN NodeStatus (DTID 341).
321321
canard_subscription_t sub_dronecan;
322322
const uint16_t dronecan_crc_seed = canard_v0_crc_seed_from_data_type_signature(DRONECAN_NODE_STATUS_SIGNATURE);
323-
if (!canard_v0_subscribe(&ins,
324-
&sub_dronecan,
325-
DRONECAN_NODE_STATUS_DTID,
326-
dronecan_crc_seed,
327-
DRONECAN_NODE_STATUS_EXTENT,
328-
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_us,
329-
&g_sub_vtable_dronecan)) {
323+
if (canard_v0_subscribe(&ins,
324+
&sub_dronecan,
325+
DRONECAN_NODE_STATUS_DTID,
326+
dronecan_crc_seed,
327+
DRONECAN_NODE_STATUS_EXTENT,
328+
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_us,
329+
&g_sub_vtable_dronecan) != &sub_dronecan) {
330330
(void)fputs("canard_v0_subscribe failed\n", stderr);
331331
canard_unsubscribe(&ins, &sub_cyphal);
332332
canard_destroy(&ins);

libcanard/canard.c

Lines changed: 93 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,15 +1558,23 @@ static int32_t rx_subscription_cavl_compare(const void* const user, const canard
15581558
return ((int32_t)(*(const uint16_t*)user)) - ((int32_t)((const canard_subscription_t*)(const void*)node)->port_id);
15591559
}
15601560

1561+
static canard_subscription_t* rx_find_subscription(const canard_t* const self,
1562+
const canard_kind_t kind,
1563+
const uint16_t port_id)
1564+
{
1565+
CANARD_ASSERT((self != NULL) && ((size_t)kind < CANARD_KIND_COUNT));
1566+
return (canard_subscription_t*)(void*)cavl2_find(
1567+
self->rx.subscriptions[kind], &port_id, rx_subscription_cavl_compare);
1568+
}
1569+
15611570
// Locates the appropriate subscription if the destination is matching and there is a subscription.
15621571
static canard_subscription_t* rx_route(const canard_t* const self, const frame_t* const fr)
15631572
{
15641573
CANARD_ASSERT((self != NULL) && (fr != NULL));
15651574
if ((fr->dst != CANARD_NODE_ID_ANONYMOUS) && (fr->dst != self->node_id)) {
15661575
return NULL; // misfiltered
15671576
}
1568-
return (canard_subscription_t*)(void*)cavl2_find(
1569-
self->rx.subscriptions[fr->kind], &fr->port_id, rx_subscription_cavl_compare);
1577+
return rx_find_subscription(self, fr->kind, fr->port_id);
15701578
}
15711579

15721580
// Builds an acceptance filter that only admits frames matching the given kind and port-ID.
@@ -1729,105 +1737,118 @@ static bool rx_filter_configure(canard_t* const self)
17291737
}
17301738

17311739
// Common subscribe logic: validate, initialize, insert into tree, mark filters dirty.
1732-
static bool rx_subscribe(canard_t* const self,
1733-
canard_subscription_t* const subscription,
1734-
const canard_kind_t kind,
1735-
const uint16_t port_id,
1736-
const uint16_t crc_seed,
1737-
const size_t extent,
1738-
const canard_us_t transfer_id_timeout,
1739-
const canard_subscription_vtable_t* const vtable)
1740-
{
1741-
bool ok = (self != NULL) && (subscription != NULL) && (vtable != NULL) && (vtable->on_message != NULL) &&
1742-
(transfer_id_timeout >= 0);
1743-
if (ok) {
1740+
static canard_subscription_t* rx_subscribe(canard_t* const self,
1741+
canard_subscription_t* const subscription,
1742+
const canard_kind_t kind,
1743+
const uint16_t port_id,
1744+
const uint16_t crc_seed,
1745+
const size_t extent,
1746+
const canard_us_t transfer_id_timeout,
1747+
const canard_subscription_vtable_t* const vtable)
1748+
{
1749+
canard_subscription_t* out = NULL;
1750+
if ((self != NULL) && (subscription != NULL) && (vtable != NULL) && (vtable->on_message != NULL) &&
1751+
(transfer_id_timeout >= 0)) {
17441752
(void)memset(subscription, 0, sizeof(*subscription));
17451753
subscription->transfer_id_timeout = transfer_id_timeout;
17461754
subscription->extent = extent;
17471755
subscription->port_id = port_id;
17481756
subscription->crc_seed = crc_seed;
17491757
subscription->kind = kind;
17501758
subscription->owner = self;
1759+
subscription->sessions = NULL;
17511760
subscription->vtable = vtable;
1761+
subscription->user_context = NULL;
17521762
const canard_tree_t* const existing = cavl2_find_or_insert(&self->rx.subscriptions[kind],
17531763
&subscription->port_id,
17541764
rx_subscription_cavl_compare,
17551765
&subscription->index_port_id,
17561766
cavl2_trivial_factory);
1757-
if (existing != &subscription->index_port_id) {
1758-
(void)memset(subscription, 0, sizeof(*subscription)); // Undo partial init on duplicate.
1759-
ok = false;
1760-
} else {
1761-
self->rx.filters_dirty = true;
1762-
}
1767+
out = (canard_subscription_t*)(void*)existing;
1768+
self->rx.filters_dirty = (existing == &subscription->index_port_id);
17631769
}
1764-
return ok;
1770+
return out;
17651771
}
17661772

1767-
bool canard_subscribe_16b(canard_t* const self,
1768-
canard_subscription_t* const subscription,
1769-
const uint16_t subject_id,
1770-
const size_t extent,
1771-
const canard_us_t transfer_id_timeout,
1772-
const canard_subscription_vtable_t* const vtable)
1773+
canard_subscription_t* canard_subscribe_16b(canard_t* const self,
1774+
canard_subscription_t* const subscription,
1775+
const uint16_t subject_id,
1776+
const size_t extent,
1777+
const canard_us_t transfer_id_timeout,
1778+
const canard_subscription_vtable_t* const vtable)
17731779
{
17741780
return rx_subscribe(
17751781
self, subscription, canard_kind_message_16b, subject_id, CRC_INITIAL, extent, transfer_id_timeout, vtable);
17761782
}
17771783

1778-
bool canard_subscribe_13b(canard_t* const self,
1779-
canard_subscription_t* const subscription,
1780-
const uint16_t subject_id,
1781-
const size_t extent,
1782-
const canard_us_t transfer_id_timeout,
1783-
const canard_subscription_vtable_t* const vtable)
1784+
canard_subscription_t* canard_subscribe_13b(canard_t* const self,
1785+
canard_subscription_t* const subscription,
1786+
const uint16_t subject_id,
1787+
const size_t extent,
1788+
const canard_us_t transfer_id_timeout,
1789+
const canard_subscription_vtable_t* const vtable)
1790+
{
1791+
return (subject_id <= CANARD_SUBJECT_ID_MAX_13b) ? rx_subscribe(self,
1792+
subscription,
1793+
canard_kind_message_13b,
1794+
subject_id,
1795+
CRC_INITIAL,
1796+
extent,
1797+
transfer_id_timeout,
1798+
vtable)
1799+
: NULL;
1800+
}
1801+
1802+
canard_subscription_t* canard_subscribe_request(canard_t* const self,
1803+
canard_subscription_t* const subscription,
1804+
const uint16_t service_id,
1805+
const size_t extent,
1806+
const canard_us_t transfer_id_timeout,
1807+
const canard_subscription_vtable_t* const vtable)
17841808
{
1785-
return (subject_id <= CANARD_SUBJECT_ID_MAX_13b) &&
1786-
rx_subscribe(
1787-
self, subscription, canard_kind_message_13b, subject_id, CRC_INITIAL, extent, transfer_id_timeout, vtable);
1809+
return (service_id <= CANARD_SERVICE_ID_MAX)
1810+
? rx_subscribe(
1811+
self, subscription, canard_kind_request, service_id, CRC_INITIAL, extent, transfer_id_timeout, vtable)
1812+
: NULL;
17881813
}
17891814

1790-
bool canard_subscribe_request(canard_t* const self,
1791-
canard_subscription_t* const subscription,
1792-
const uint16_t service_id,
1793-
const size_t extent,
1794-
const canard_us_t transfer_id_timeout,
1795-
const canard_subscription_vtable_t* const vtable)
1815+
canard_subscription_t* canard_subscribe_response(canard_t* const self,
1816+
canard_subscription_t* const subscription,
1817+
const uint16_t service_id,
1818+
const size_t extent,
1819+
const canard_subscription_vtable_t* const vtable)
17961820
{
1797-
return (service_id <= CANARD_SERVICE_ID_MAX) &&
1798-
rx_subscribe(
1799-
self, subscription, canard_kind_request, service_id, CRC_INITIAL, extent, transfer_id_timeout, vtable);
1821+
return (service_id <= CANARD_SERVICE_ID_MAX)
1822+
? rx_subscribe(self, subscription, canard_kind_response, service_id, CRC_INITIAL, extent, 0, vtable)
1823+
: NULL;
18001824
}
18011825

1802-
bool canard_subscribe_response(canard_t* const self,
1803-
canard_subscription_t* const subscription,
1804-
const uint16_t service_id,
1805-
const size_t extent,
1806-
const canard_subscription_vtable_t* const vtable)
1826+
canard_subscription_t* canard_find_subscription(const canard_t* const self,
1827+
const canard_kind_t kind,
1828+
const uint16_t port_id)
18071829
{
1808-
return (service_id <= CANARD_SERVICE_ID_MAX) &&
1809-
rx_subscribe(self, subscription, canard_kind_response, service_id, CRC_INITIAL, extent, 0, vtable);
1830+
return ((self != NULL) && ((size_t)kind < CANARD_KIND_COUNT)) ? rx_find_subscription(self, kind, port_id) : NULL;
18101831
}
18111832

1812-
bool canard_v0_subscribe(canard_t* const self,
1813-
canard_subscription_t* const subscription,
1814-
const uint16_t data_type_id,
1815-
const uint16_t crc_seed,
1816-
const size_t extent,
1817-
const canard_us_t transfer_id_timeout,
1818-
const canard_subscription_vtable_t* const vtable)
1833+
canard_subscription_t* canard_v0_subscribe(canard_t* const self,
1834+
canard_subscription_t* const subscription,
1835+
const uint16_t data_type_id,
1836+
const uint16_t crc_seed,
1837+
const size_t extent,
1838+
const canard_us_t transfer_id_timeout,
1839+
const canard_subscription_vtable_t* const vtable)
18191840
{
18201841
return rx_subscribe(
18211842
self, subscription, canard_kind_v0_message, data_type_id, crc_seed, extent, transfer_id_timeout, vtable);
18221843
}
18231844

1824-
bool canard_v0_subscribe_request(canard_t* const self,
1825-
canard_subscription_t* const subscription,
1826-
const uint_least8_t data_type_id,
1827-
const uint16_t crc_seed,
1828-
const size_t extent,
1829-
const canard_us_t transfer_id_timeout,
1830-
const canard_subscription_vtable_t* const vtable)
1845+
canard_subscription_t* canard_v0_subscribe_request(canard_t* const self,
1846+
canard_subscription_t* const subscription,
1847+
const uint_least8_t data_type_id,
1848+
const uint16_t crc_seed,
1849+
const size_t extent,
1850+
const canard_us_t transfer_id_timeout,
1851+
const canard_subscription_vtable_t* const vtable)
18311852
{
18321853
return rx_subscribe(self,
18331854
subscription,
@@ -1839,12 +1860,12 @@ bool canard_v0_subscribe_request(canard_t* const self,
18391860
vtable);
18401861
}
18411862

1842-
bool canard_v0_subscribe_response(canard_t* const self,
1843-
canard_subscription_t* const subscription,
1844-
const uint_least8_t data_type_id,
1845-
const uint16_t crc_seed,
1846-
const size_t extent,
1847-
const canard_subscription_vtable_t* const vtable)
1863+
canard_subscription_t* canard_v0_subscribe_response(canard_t* const self,
1864+
canard_subscription_t* const subscription,
1865+
const uint_least8_t data_type_id,
1866+
const uint16_t crc_seed,
1867+
const size_t extent,
1868+
const canard_subscription_vtable_t* const vtable)
18481869
{
18491870
return rx_subscribe(
18501871
self, subscription, canard_kind_v0_response, (uint16_t)data_type_id, crc_seed, extent, 0, vtable);

0 commit comments

Comments
 (0)