add topic matcher

This commit is contained in:
Wolfgang Hottgenroth 2020-06-17 18:26:49 +02:00
parent e1a8e7d63e
commit c48702db3a
Signed by: wn
GPG Key ID: 6C1E5E531E0D5D7F
4 changed files with 157 additions and 7 deletions

View File

@ -11,10 +11,10 @@ VERSION:=$(shell cat VERSION)
.PHONY: all .PHONY: all
all: mqttauditing all: mqttauditing
mqttauditing: mqttauditing.o mqttreceiver.o logging.o ringbuffer.o version.o mqttauditing: mqttauditing.o mqttreceiver.o mqtttopicmatcher.o logging.o ringbuffer.o version.o
$(CC) -o $@ $(LDFLAGS) $^ $(CC) -o $@ $(LDFLAGS) $^
tests: tests.o ringbuffer.o tests: tests.o ringbuffer.o mqtttopicmatcher.o
$(CC) -o $@ $(LDFLAGS) -lcunit $^ $(CC) -o $@ $(LDFLAGS) -lcunit $^
version.o: version.c VERSION version.o: version.c VERSION

117
mqtttopicmatcher.c Normal file
View File

@ -0,0 +1,117 @@
#include <stdint.h>
#include "mqtttopicmatcher.h"
int cmpTopicWithWildcard(char *subscribedTopic, char *receivedTopic) {
uint32_t s_idx = 0;
uint32_t r_idx = 0;
char s;
char r;
enum { e_START, e_PART, e_DELIMITER, e_WAIT_FOR_DELIMITER_IN_S, e_WAIT_FOR_DELIMITER_IN_R, e_OK, e_NOK } state;
state = e_START;
while (1) {
s = *(subscribedTopic + s_idx);
r = *(receivedTopic + r_idx);
if ((s == 0) && (r == 0) && (state == e_PART)) {
return 0;
}
switch (state) {
case e_START:
if (s == '#') {
state = e_OK;
break;
} else if (s == '+') {
state = e_WAIT_FOR_DELIMITER_IN_S;
s_idx++;
r_idx++;
break;
} else if (s == '/') {
state = e_DELIMITER;
s_idx++;
r_idx++;
break;
} else if (s == r) {
state = e_PART;
s_idx++;
r_idx++;
break;
} else {
state = e_NOK;
break;
}
case e_DELIMITER:
if (s == '#') {
state = e_OK;
break;
} else if (s == '+') {
state = e_WAIT_FOR_DELIMITER_IN_S;
s_idx++;
r_idx++;
break;
} else if (s == r) {
state = e_PART;
s_idx++;
r_idx++;
break;
} else {
state = e_NOK;
break;
}
case e_WAIT_FOR_DELIMITER_IN_S:
if (s != '/') {
state = e_NOK;
break;
} else if ((s == '/') && (r == '/')) {
state = e_PART;
s_idx++;
r_idx++;
break;
} else if ((s == '/') && (r != '/')) {
state = e_WAIT_FOR_DELIMITER_IN_R;
r_idx++;
break;
} else {
state = e_NOK;
break;
}
case e_WAIT_FOR_DELIMITER_IN_R:
if (r == '/') {
state = e_PART;
s_idx++;
r_idx++;
break;
} else {
r_idx++;
break;
}
case e_PART:
if (s == '#') {
state = e_OK;
break;
} else if (s == '+') {
state = e_WAIT_FOR_DELIMITER_IN_S;
s_idx++;
r_idx++;
break;
} else if (s == r) {
state = e_PART;
s_idx++;
r_idx++;
break;
} else {
state = e_NOK;
break;
}
}
if (state == e_OK) {
return 0;
} else if (state == e_NOK) {
return -1;
}
}
}

6
mqtttopicmatcher.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _MQTTTOPICMATCHER_H_
#define _MQTTTOPICMATCHER_H_
int cmpTopicWithWildcard(char *subscribedTopic, char *receivedTopic);
#endif // _MQTTTOPICMATCHER_H_

37
tests.c
View File

@ -4,9 +4,9 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "ringbuffer.h" #include "ringbuffer.h"
#include "mqtttopicmatcher.h"
ringbuffer_t rb;
t_ringbuffer rb;
int init_suite_ringbuffer(void) int init_suite_ringbuffer(void)
@ -123,6 +123,21 @@ void testRingbuffer4() {
} }
void testTopicMatcher1() {
CU_ASSERT(cmpTopicWithWildcard("#", "bla") == 0);
CU_ASSERT(cmpTopicWithWildcard("bla/#", "bla/blu") == 0);
CU_ASSERT(cmpTopicWithWildcard("bla/#", "blu/blu") == -1);
CU_ASSERT(cmpTopicWithWildcard("bla/+", "bla/blu") == -1);
CU_ASSERT(cmpTopicWithWildcard("bla/+/blo", "bla/blu/blo") == 0);
CU_ASSERT(cmpTopicWithWildcard("bla/+/blo", "bla/blu/ble") == -1);
CU_ASSERT(cmpTopicWithWildcard("bla/+/blo", "blo/blu/blo") == -1);
CU_ASSERT(cmpTopicWithWildcard("bla/blu/blo", "bla/blu/blo") == 0);
CU_ASSERT(cmpTopicWithWildcard("bla/blu/#", "bla/blu/blo") == 0);
CU_ASSERT(cmpTopicWithWildcard("bla", "") == -1);
CU_ASSERT(cmpTopicWithWildcard("#", "") == 0);
CU_ASSERT(cmpTopicWithWildcard("", "") == 0);
}
int main() int main()
{ {
@ -139,13 +154,25 @@ int main()
(NULL == CU_add_test(ringbufferSuite, "test 2 of ringbuffer", testRingbuffer2)) || (NULL == CU_add_test(ringbufferSuite, "test 2 of ringbuffer", testRingbuffer2)) ||
(NULL == CU_add_test(ringbufferSuite, "test 3 of ringbuffer", testRingbuffer3)) || (NULL == CU_add_test(ringbufferSuite, "test 3 of ringbuffer", testRingbuffer3)) ||
(NULL == CU_add_test(ringbufferSuite, "test 4 of ringbuffer", testRingbuffer4)) || (NULL == CU_add_test(ringbufferSuite, "test 4 of ringbuffer", testRingbuffer4)) ||
0 0 ) {
)
{
CU_cleanup_registry(); CU_cleanup_registry();
return CU_get_error(); return CU_get_error();
} }
CU_pSuite topicMatcherSuite = CU_add_suite("Suite_TopicMatcher", NULL, NULL);
if (NULL == topicMatcherSuite) {
CU_cleanup_registry();
return CU_get_error();
}
if ((NULL == CU_add_test(topicMatcherSuite, "test 1 of topicMatcher", testTopicMatcher1)) ||
0 ) {
CU_cleanup_registry();
return CU_get_error();
}
CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests(); CU_basic_run_tests();
CU_cleanup_registry(); CU_cleanup_registry();