Skip to content

Commit

Permalink
perf: add inline for check_topic_match
Browse files Browse the repository at this point in the history
  • Loading branch information
xukeawsl committed Sep 22, 2024
1 parent 4990f6c commit 2c5f469
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/MqttAcl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ MQTT_ACL_STATE MqttAcl::check_acl_detail(const mqtt_acl_rule_t& acl_rule,

// 对于发布控制来说需要进行通配符匹配
for (const auto& t : *(acl_rule.topics)) {
if (util::check_topic_match(topic, t)) {
if (utils::check_topic_match(topic, t)) {
return acl_rule.permission;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/MqttAcl.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "MqttCommon.h"
#include "MqttUtils.h"

class MqttAcl {
public:
Expand Down
29 changes: 1 addition & 28 deletions src/MqttCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ enum class MQTT_MSG_STATE: uint8_t {
WAIT_RECEIVE_PUBCOMP,
};


enum class MQTT_RC_CODE: uint8_t {
ERR_SUCCESS = 0,
ERR_SUCCESS_DISCONNECT,
Expand All @@ -66,7 +65,6 @@ enum class MQTT_RC_CODE: uint8_t {
ERR_REFUSED_NOT_AUTHORIZED,
};


struct MQTT_CMD {
static constexpr uint8_t CONNECT = 0x10U;
static constexpr uint8_t CONNACK = 0x20U;
Expand All @@ -84,7 +82,6 @@ struct MQTT_CMD {
static constexpr uint8_t DISCONNECT = 0xE0U;
};


struct MQTT_CONNACK {
static constexpr uint8_t ACCEPTED = 0x00U;
static constexpr uint8_t REFUSED_PROTOCOL_VERSION = 0x01U;
Expand All @@ -94,7 +91,6 @@ struct MQTT_CONNACK {
static constexpr uint8_t REFUSED_NOT_AUTHORIZED = 0x05U;
};


struct mqtt_packet_t {
struct {
uint8_t qos: 2;
Expand Down Expand Up @@ -186,27 +182,4 @@ struct mqtt_listener_cfg_t {
std::string address;
uint16_t port;
mqtt_ssl_cfg_t ssl_cfg;
};

namespace convert {

template <typename InternetProtocol>
std::string format_address(
const asio::ip::basic_endpoint<InternetProtocol>& endpoint) {
if (endpoint.address().is_v6()) {
return "[" + endpoint.address().to_string() + "]" + ":" +
std::to_string(endpoint.port());
}
return endpoint.address().to_string() + ":" +
std::to_string(endpoint.port());
}

}


namespace util {

bool check_topic_match(const std::string& pub_topic,
const std::string& sub_topic);

}
};
3 changes: 2 additions & 1 deletion src/MqttSession.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -2173,7 +2173,8 @@ asio::awaitable<void> MqttSession<SocketType>::handle_inflighting_packets() {
sub_topic != packet.specified_topic_name) {
continue;
}
if (util::check_topic_match(*(packet.topic_name), sub_topic)) {

if (utils::check_topic_match(*(packet.topic_name), sub_topic)) {
// Qos 等级取两者最小值
old_qos = packet.qos;

Expand Down
81 changes: 81 additions & 0 deletions src/MqttUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,85 @@ inline bool is_valid_utf8(unsigned char *s, size_t length) {
return true;
}

inline bool check_topic_match(const std::string& pub_topic,
const std::string& sub_topic) {
uint32_t pub_len = pub_topic.length();
uint32_t sub_len = sub_topic.length();
uint32_t i = 0, j = 0;

if (pub_len == 0 || sub_len == 0) {
return true;
}

while (i < pub_len && j < sub_len) {
if (pub_topic[i] == sub_topic[j]) {
i++;
j++;
continue;
}

if (sub_topic[j] == '+') {
if (pub_topic[i] == '/') {
if (j + 1 < sub_len) {
i++;
j += 2; // 后一位一定是 '/', 需要跨过
} else {
return false;
}
} else {
// 匹配一个层级
while (i < pub_len && pub_topic[i] != '/') {
i++;
}

if (i == pub_len) {
if (j == sub_len - 1) {
// 最后一个层级匹配
return true;
}

// example:
// pub("xx") sub("+/#")
if (j + 2 < sub_len && sub_topic[j + 2] == '#') {
return true;
}

return false;
}

// 本层匹配完成, 进入下一层
if (j + 1 < sub_len) {
i++;
j += 2;
}
}
} else if (sub_topic[j] == '#') {
return true;
} else {
return false;
}
}

// example:
// pub("xx/") sub("xx/#")
// pub("/") sub("#")
if (j < sub_len && sub_topic[j] == '#') {
return true;
}

// example:
// pub("xx") sub("xx/#")
if (j < sub_len && sub_topic[j] == '/') {
if (j + 1 < sub_len && sub_topic[j + 1] == '#') {
return true;
}
}

if (i == pub_len && j == sub_len) {
return true;
}

return false;
}

}

0 comments on commit 2c5f469

Please sign in to comment.