mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-16 09:13:02 +08:00
Refactor TopicFilterComparer
This commit is contained in:
@@ -136,9 +136,9 @@ namespace MQTTnet.Server
|
||||
return Task.FromResult((IList<IMqttClientSessionStatus>)result);
|
||||
}
|
||||
|
||||
public Task StartDispatchApplicationMessage(MqttClientSession senderClientSession, MqttApplicationMessage applicationMessage)
|
||||
public void StartDispatchApplicationMessage(MqttClientSession senderClientSession, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
return DispatchApplicationMessageAsync(senderClientSession, applicationMessage);
|
||||
Task.Run(() => DispatchApplicationMessageAsync(senderClientSession, applicationMessage));
|
||||
}
|
||||
|
||||
public Task SubscribeAsync(string clientId, IList<TopicFilter> topicFilters)
|
||||
|
||||
@@ -4,114 +4,116 @@ namespace MQTTnet.Server
|
||||
{
|
||||
public static class MqttTopicFilterComparer
|
||||
{
|
||||
private const char LEVEL_SEPARATOR = '/';
|
||||
private const char WILDCARD_MULTI_LEVEL = '#';
|
||||
private const char WILDCARD_SINGLE_LEVEL = '+';
|
||||
private const char LevelSeparator = '/';
|
||||
private const char MultiLevelWildcard = '#';
|
||||
private const char SingleLevelWildcard = '+';
|
||||
|
||||
public static bool IsMatch(string topic, string filter)
|
||||
{
|
||||
if (string.IsNullOrEmpty(topic)) throw new ArgumentNullException(nameof(topic));
|
||||
if (string.IsNullOrEmpty(filter)) throw new ArgumentNullException(nameof(filter));
|
||||
|
||||
int spos = 0;
|
||||
int slen = filter.Length;
|
||||
int tpos = 0;
|
||||
int tlen = topic.Length;
|
||||
var sPos = 0;
|
||||
var sLen = filter.Length;
|
||||
var tPos = 0;
|
||||
var tLen = topic.Length;
|
||||
|
||||
while (spos < slen && tpos < tlen)
|
||||
while (sPos < sLen && tPos < tLen)
|
||||
{
|
||||
if (filter[spos] == topic[tpos])
|
||||
if (filter[sPos] == topic[tPos])
|
||||
{
|
||||
if (tpos == tlen - 1)
|
||||
if (tPos == tLen - 1)
|
||||
{
|
||||
/* Check for e.g. foo matching foo/# */
|
||||
if (spos == slen - 3
|
||||
&& filter[spos + 1] == LEVEL_SEPARATOR
|
||||
&& filter[spos + 2] == WILDCARD_MULTI_LEVEL)
|
||||
// Check for e.g. foo matching foo/#
|
||||
if (sPos == sLen - 3
|
||||
&& filter[sPos + 1] == LevelSeparator
|
||||
&& filter[sPos + 2] == MultiLevelWildcard)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
spos++;
|
||||
tpos++;
|
||||
if (spos == slen && tpos == tlen)
|
||||
|
||||
sPos++;
|
||||
tPos++;
|
||||
|
||||
if (sPos == sLen && tPos == tLen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (tpos == tlen && spos == slen - 1 && filter[spos] == WILDCARD_SINGLE_LEVEL)
|
||||
|
||||
if (tPos == tLen && sPos == sLen - 1 && filter[sPos] == SingleLevelWildcard)
|
||||
{
|
||||
if (spos > 0 && filter[spos - 1] != LEVEL_SEPARATOR)
|
||||
if (sPos > 0 && filter[sPos - 1] != LevelSeparator)
|
||||
{
|
||||
// Invalid filter string
|
||||
return false;
|
||||
}
|
||||
spos++;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filter[spos] == WILDCARD_SINGLE_LEVEL)
|
||||
if (filter[sPos] == SingleLevelWildcard)
|
||||
{
|
||||
/* Check for bad "+foo" or "a/+foo" subscription */
|
||||
if (spos > 0 && filter[spos - 1] != LEVEL_SEPARATOR)
|
||||
// Check for bad "+foo" or "a/+foo" subscription
|
||||
if (sPos > 0 && filter[sPos - 1] != LevelSeparator)
|
||||
{
|
||||
// Invalid filter string
|
||||
return false;
|
||||
}
|
||||
/* Check for bad "foo+" or "foo+/a" subscription */
|
||||
if (spos < slen - 1 && filter[spos + 1] != LEVEL_SEPARATOR)
|
||||
|
||||
// Check for bad "foo+" or "foo+/a" subscription
|
||||
if (sPos < sLen - 1 && filter[sPos + 1] != LevelSeparator)
|
||||
{
|
||||
// Invalid filter string
|
||||
return false;
|
||||
}
|
||||
spos++;
|
||||
while (tpos < tlen && topic[tpos] != LEVEL_SEPARATOR)
|
||||
|
||||
sPos++;
|
||||
while (tPos < tLen && topic[tPos] != LevelSeparator)
|
||||
{
|
||||
tpos++;
|
||||
tPos++;
|
||||
}
|
||||
if (tpos == tlen && spos == slen)
|
||||
|
||||
if (tPos == tLen && sPos == sLen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (filter[spos] == WILDCARD_MULTI_LEVEL)
|
||||
else if (filter[sPos] == MultiLevelWildcard)
|
||||
{
|
||||
if (spos > 0 && filter[spos - 1] != LEVEL_SEPARATOR)
|
||||
if (sPos > 0 && filter[sPos - 1] != LevelSeparator)
|
||||
{
|
||||
// Invalid filter string
|
||||
return false;
|
||||
}
|
||||
if (spos + 1 != slen)
|
||||
|
||||
if (sPos + 1 != sLen)
|
||||
{
|
||||
// Invalid filter string
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check for e.g. foo/bar matching foo/+/# */
|
||||
if (spos > 0
|
||||
&& spos + 2 == slen
|
||||
&& tpos == tlen
|
||||
&& filter[spos - 1] == WILDCARD_SINGLE_LEVEL
|
||||
&& filter[spos] == LEVEL_SEPARATOR
|
||||
&& filter[spos + 1] == WILDCARD_MULTI_LEVEL)
|
||||
// Check for e.g. foo/bar matching foo/+/#
|
||||
if (sPos > 0
|
||||
&& sPos + 2 == sLen
|
||||
&& tPos == tLen
|
||||
&& filter[sPos - 1] == SingleLevelWildcard
|
||||
&& filter[sPos] == LevelSeparator
|
||||
&& filter[sPos + 1] == MultiLevelWildcard)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tpos < tlen || spos < slen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user