Commit 39429149 authored by Dmitry Frank's avatar Dmitry Frank Committed by Cesanta Bot

Fix subscription to wildcard topics

`mg_mqtt_match_topic_expression()` and friends are public now.

So far, only `#` is supported.

PUBLISHED_FROM=20c031bcf34be84771c4a9c456318634eb9a517c
parent 60c16bbb
...@@ -5,6 +5,7 @@ decl_name: "mqtt.h" ...@@ -5,6 +5,7 @@ decl_name: "mqtt.h"
items: items:
- { name: mg_mqtt_connack.md } - { name: mg_mqtt_connack.md }
- { name: mg_mqtt_disconnect.md } - { name: mg_mqtt_disconnect.md }
- { name: mg_mqtt_match_topic_expression.md }
- { name: mg_mqtt_next_subscribe_topic.md } - { name: mg_mqtt_next_subscribe_topic.md }
- { name: mg_mqtt_ping.md } - { name: mg_mqtt_ping.md }
- { name: mg_mqtt_pong.md } - { name: mg_mqtt_pong.md }
...@@ -17,6 +18,7 @@ items: ...@@ -17,6 +18,7 @@ items:
- { name: mg_mqtt_subscribe.md } - { name: mg_mqtt_subscribe.md }
- { name: mg_mqtt_unsuback.md } - { name: mg_mqtt_unsuback.md }
- { name: mg_mqtt_unsubscribe.md } - { name: mg_mqtt_unsubscribe.md }
- { name: mg_mqtt_vmatch_topic_expression.md }
- { name: mg_send_mqtt_handshake.md } - { name: mg_send_mqtt_handshake.md }
- { name: mg_send_mqtt_handshake_opt.md } - { name: mg_send_mqtt_handshake_opt.md }
- { name: mg_set_protocol_mqtt.md } - { name: mg_set_protocol_mqtt.md }
......
---
title: "mg_mqtt_match_topic_expression()"
decl_name: "mg_mqtt_match_topic_expression"
symbol_kind: "func"
signature: |
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic);
---
Matches a topic against a topic expression
Returns 1 if it matches; 0 otherwise.
---
title: "mg_mqtt_vmatch_topic_expression()"
decl_name: "mg_mqtt_vmatch_topic_expression"
symbol_kind: "func"
signature: |
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic);
---
Same as `mg_mqtt_match_topic_expression()`, but takes `exp` as a
NULL-terminated string.
...@@ -9703,6 +9703,21 @@ static void mg_mqtt_proto_data_destructor(void *proto_data) { ...@@ -9703,6 +9703,21 @@ static void mg_mqtt_proto_data_destructor(void *proto_data) {
MG_FREE(proto_data); MG_FREE(proto_data);
} }
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic) {
/* TODO(mkm): implement real matching */
if (memchr(exp.p, '#', exp.len)) {
exp.len -= 2;
if (topic.len < exp.len) {
exp.len = topic.len;
}
}
return strncmp(topic.p, exp.p, exp.len) == 0;
}
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic) {
return mg_mqtt_match_topic_expression(mg_mk_str(exp), topic);
}
void mg_set_protocol_mqtt(struct mg_connection *nc) { void mg_set_protocol_mqtt(struct mg_connection *nc) {
nc->proto_handler = mqtt_handler; nc->proto_handler = mqtt_handler;
nc->proto_data = MG_CALLOC(1, sizeof(struct mg_mqtt_proto_data)); nc->proto_data = MG_CALLOC(1, sizeof(struct mg_mqtt_proto_data));
...@@ -10040,26 +10055,6 @@ static void mg_mqtt_broker_handle_subscribe(struct mg_connection *nc, ...@@ -10040,26 +10055,6 @@ static void mg_mqtt_broker_handle_subscribe(struct mg_connection *nc,
mg_mqtt_suback(nc, qoss, qoss_len, msg->message_id); mg_mqtt_suback(nc, qoss, qoss_len, msg->message_id);
} }
/*
* Matches a topic against a topic expression
*
* See http://goo.gl/iWk21X
*
* Returns 1 if it matches; 0 otherwise.
*/
static int mg_mqtt_match_topic_expression(const char *exp,
const struct mg_str *topic) {
/* TODO(mkm): implement real matching */
size_t len = strlen(exp);
if (strchr(exp, '#')) {
len -= 2;
if (topic->len < len) {
len = topic->len;
}
}
return strncmp(topic->p, exp, len) == 0;
}
static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk, static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk,
struct mg_mqtt_message *msg) { struct mg_mqtt_message *msg) {
struct mg_mqtt_session *s; struct mg_mqtt_session *s;
...@@ -10067,8 +10062,8 @@ static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk, ...@@ -10067,8 +10062,8 @@ static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk,
for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) { for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
for (i = 0; i < s->num_subscriptions; i++) { for (i = 0; i < s->num_subscriptions; i++) {
if (mg_mqtt_match_topic_expression(s->subscriptions[i].topic, if (mg_mqtt_vmatch_topic_expression(s->subscriptions[i].topic,
&msg->topic)) { msg->topic)) {
char buf[100], *p = buf; char buf[100], *p = buf;
mg_asprintf(&p, sizeof(buf), "%.*s", (int) msg->topic.len, mg_asprintf(&p, sizeof(buf), "%.*s", (int) msg->topic.len,
msg->topic.p); msg->topic.p);
......
...@@ -5152,6 +5152,19 @@ void mg_mqtt_pong(struct mg_connection *nc); ...@@ -5152,6 +5152,19 @@ void mg_mqtt_pong(struct mg_connection *nc);
int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg, int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
struct mg_str *topic, uint8_t *qos, int pos); struct mg_str *topic, uint8_t *qos, int pos);
/*
* Matches a topic against a topic expression
*
* Returns 1 if it matches; 0 otherwise.
*/
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic);
/*
* Same as `mg_mqtt_match_topic_expression()`, but takes `exp` as a
* NULL-terminated string.
*/
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment