1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-16 10:03:50 +01:00

net/asymcute: fix short and pre-defined topics

This commit is contained in:
Hauke Petersen 2020-12-16 17:51:53 +01:00
parent d5aa6c1311
commit 289688169e
2 changed files with 66 additions and 16 deletions

View File

@ -394,6 +394,34 @@ static inline bool asymcute_topic_is_reg(const asymcute_topic_t *topic)
return (topic->con != NULL); return (topic->con != NULL);
} }
/**
* @brief Check if a given topic is a short topic
*
* @param[in] topic topic to check
*
* @return true if topic is a short topic
* @return false if topic is not short topic
*/
static inline bool asymcute_topic_is_short(const asymcute_topic_t *topic)
{
assert(topic);
return ((topic->flags & MQTTSN_TIT_SHORT) != 0);
}
/**
* @brief Check if a given topic is a pre-defined topic
*
* @param[in] topic topic to check
*
* @return true if topic is pre-defined
* @return false if topic is not pre-defined
*/
static inline bool asymcute_topic_is_predef(const asymcute_topic_t *topic)
{
assert(topic);
return ((topic->flags & MQTTSN_TIT_PREDEF) != 0);
}
/** /**
* @brief Check if a given topic is initialized * @brief Check if a given topic is initialized
* *

View File

@ -165,7 +165,12 @@ static void _compile_sub_unsub(asymcute_req_t *req, asymcute_con_t *con,
req->data[pos] = type; req->data[pos] = type;
req->data[pos + 1] = sub->topic->flags; req->data[pos + 1] = sub->topic->flags;
byteorder_htobebufs(&req->data[pos + 2], req->msg_id); byteorder_htobebufs(&req->data[pos + 2], req->msg_id);
if (sub->topic->flags & MQTTSN_TIT_MASK) {
memcpy(&req->data[pos + 4], &sub->topic->id, 2);
}
else {
memcpy(&req->data[pos + 4], sub->topic->name, topic_len); memcpy(&req->data[pos + 4], sub->topic->name, topic_len);
}
req->data_len = (pos + 4 + topic_len); req->data_len = (pos + 4 + topic_len);
req->arg = sub; req->arg = sub;
} }
@ -474,20 +479,26 @@ static void _on_suback(asymcute_con_t *con, const uint8_t *data, size_t len)
} }
unsigned ret = ASYMCUTE_REJECTED; unsigned ret = ASYMCUTE_REJECTED;
if (data[7] == MQTTSN_ACCEPTED) {
/* parse and apply assigned topic id */ /* parse and apply assigned topic id */
asymcute_sub_t *sub = req->arg; asymcute_sub_t *sub = req->arg;
if (sub == NULL) { if (sub == NULL) {
return; return;
} }
if (data[7] == MQTTSN_ACCEPTED) {
/* do not assign a topic ID for short and predefined topics */
if (!(sub->topic->flags & MQTTSN_TIT_MASK)) {
sub->topic->id = byteorder_bebuftohs(&data[3]); sub->topic->id = byteorder_bebuftohs(&data[3]);
}
sub->topic->con = con; sub->topic->con = con;
/* insert subscription to connection context */ /* insert subscription to connection context */
sub->next = con->subscriptions; sub->next = con->subscriptions;
con->subscriptions = sub; con->subscriptions = sub;
ret = ASYMCUTE_SUBSCRIBED; ret = ASYMCUTE_SUBSCRIBED;
} }
else {
sub->topic = NULL;
}
/* notify the user */ /* notify the user */
mutex_unlock(&req->lock); mutex_unlock(&req->lock);
@ -668,12 +679,12 @@ int asymcute_topic_init(asymcute_topic_t *topic, const char *topic_name,
{ {
assert(topic); assert(topic);
size_t len = 0; size_t len = 0;
if (asymcute_topic_is_reg(topic)) { if (asymcute_topic_is_reg(topic)) {
return ASYMCUTE_REGERR; return ASYMCUTE_REGERR;
} }
if (topic_name == NULL) { if (topic_name == NULL) {
if ((topic_id == 0) || (topic_id == UINT16_MAX)) { if ((topic_id == 0) || (topic_id == UINT16_MAX)) {
return ASYMCUTE_OVERFLOW; return ASYMCUTE_OVERFLOW;
@ -692,8 +703,7 @@ int asymcute_topic_init(asymcute_topic_t *topic, const char *topic_name,
if (topic_name == NULL) { if (topic_name == NULL) {
topic->id = topic_id; topic->id = topic_id;
topic->flags = MQTTSN_TIT_PREDEF; topic->flags = MQTTSN_TIT_PREDEF;
memcpy(topic->name, &topic_id, 2); memcpy(topic->name, "..\0", 3);
topic->name[2] = '\0';
} }
else { else {
strncpy(topic->name, topic_name, sizeof(topic->name)); strncpy(topic->name, topic_name, sizeof(topic->name));
@ -823,6 +833,14 @@ int asymcute_register(asymcute_con_t *con, asymcute_req_t *req,
goto end; goto end;
} }
/* if we have a short or predefined topic, there is no need to send a
* registration message. We assign the connection right away */
if (topic->flags & MQTTSN_TIT_MASK) {
topic->con = con;
mutex_unlock(&req->lock);
goto end;
}
/* prepare topic */ /* prepare topic */
req->arg = topic; req->arg = topic;
size_t topic_len = strlen(topic->name); size_t topic_len = strlen(topic->name);
@ -936,13 +954,16 @@ int asymcute_subscribe(asymcute_con_t *con, asymcute_req_t *req,
ret = ASYMCUTE_GWERR; ret = ASYMCUTE_GWERR;
goto end; goto end;
} }
/* check if we are already subscribed to the given topic */ /* check if we are already subscribed to the given topic, but only if the
* topic was already registered */
if (asymcute_topic_is_reg(topic)) {
for (asymcute_sub_t *sub = con->subscriptions; sub; sub = sub->next) { for (asymcute_sub_t *sub = con->subscriptions; sub; sub = sub->next) {
if (asymcute_topic_equal(topic, sub->topic)) { if (asymcute_topic_equal(topic, sub->topic)) {
ret = ASYMCUTE_SUBERR; ret = ASYMCUTE_SUBERR;
goto end; goto end;
} }
} }
}
/* make sure request context is clear to be used */ /* make sure request context is clear to be used */
if (mutex_trylock(&req->lock) != 1) { if (mutex_trylock(&req->lock) != 1) {
ret = ASYMCUTE_BUSY; ret = ASYMCUTE_BUSY;
@ -953,6 +974,7 @@ int asymcute_subscribe(asymcute_con_t *con, asymcute_req_t *req,
sub->cb = callback; sub->cb = callback;
sub->arg = arg; sub->arg = arg;
sub->topic = topic; sub->topic = topic;
topic->flags |= flags;
/* send SUBSCRIBE message */ /* send SUBSCRIBE message */
_compile_sub_unsub(req, con, sub, MQTTSN_SUBSCRIBE); _compile_sub_unsub(req, con, sub, MQTTSN_SUBSCRIBE);