Bridge remapping refactoring and tests.
This commit is contained in:
parent
8463c33720
commit
fad184c9c2
1
.gitignore
vendored
1
.gitignore
vendored
@ -68,6 +68,7 @@ test/ssl/signingCA/
|
||||
test/lib/c/*.test
|
||||
test/lib/cpp/*.test
|
||||
|
||||
test/unit/bridge_topic_test
|
||||
test/unit/coverage.info
|
||||
test/unit/mosq_test
|
||||
test/unit/persist_read_test
|
||||
|
@ -11,6 +11,7 @@ endif
|
||||
OBJS= mosquitto.o \
|
||||
alias_mosq.o \
|
||||
bridge.o \
|
||||
bridge_topic.o \
|
||||
conf.o \
|
||||
conf_includedir.o \
|
||||
context.o \
|
||||
@ -83,6 +84,9 @@ alias_mosq.o : ../lib/alias_mosq.c ../lib/alias_mosq.h
|
||||
bridge.o : bridge.c mosquitto_broker_internal.h
|
||||
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
bridge_topic.o : bridge_topic.c mosquitto_broker_internal.h
|
||||
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
conf.o : conf.c mosquitto_broker_internal.h
|
||||
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
|
59
src/bridge.c
59
src/bridge.c
@ -760,63 +760,4 @@ void bridge_check(struct mosquitto_db *db, struct pollfd *pollfds, int *pollfd_i
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bridge__remap_topic(struct mosquitto *context, char **topic)
|
||||
{
|
||||
struct mosquitto__bridge_topic *cur_topic;
|
||||
char *topic_temp;
|
||||
int i;
|
||||
int len;
|
||||
int rc;
|
||||
bool match;
|
||||
|
||||
if(context->bridge && context->bridge->topics && context->bridge->topic_remapping){
|
||||
for(i=0; i<context->bridge->topic_count; i++){
|
||||
cur_topic = &context->bridge->topics[i];
|
||||
if((cur_topic->direction == bd_both || cur_topic->direction == bd_in)
|
||||
&& (cur_topic->remote_prefix || cur_topic->local_prefix)){
|
||||
|
||||
/* Topic mapping required on this topic if the message matches */
|
||||
|
||||
rc = mosquitto_topic_matches_sub(cur_topic->remote_topic, *topic, &match);
|
||||
if(rc){
|
||||
mosquitto__free(*topic);
|
||||
return rc;
|
||||
}
|
||||
if(match){
|
||||
if(cur_topic->remote_prefix){
|
||||
/* This prefix needs removing. */
|
||||
if(!strncmp(cur_topic->remote_prefix, *topic, strlen(cur_topic->remote_prefix))){
|
||||
topic_temp = mosquitto__strdup((*topic)+strlen(cur_topic->remote_prefix));
|
||||
if(!topic_temp){
|
||||
mosquitto__free(*topic);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
mosquitto__free(*topic);
|
||||
*topic = topic_temp;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_topic->local_prefix){
|
||||
/* This prefix needs adding. */
|
||||
len = strlen(*topic) + strlen(cur_topic->local_prefix)+1;
|
||||
topic_temp = mosquitto__malloc(len+1);
|
||||
if(!topic_temp){
|
||||
mosquitto__free(*topic);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(topic_temp, len, "%s%s", cur_topic->local_prefix, *topic);
|
||||
topic_temp[len] = '\0';
|
||||
|
||||
mosquitto__free(*topic);
|
||||
*topic = topic_temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
214
src/bridge_topic.c
Normal file
214
src/bridge_topic.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
Copyright (c) 2009-2019 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mosquitto.h"
|
||||
#include "mosquitto_broker_internal.h"
|
||||
#include "memory_mosq.h"
|
||||
|
||||
#ifdef WITH_BRIDGE
|
||||
|
||||
|
||||
/* topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix] */
|
||||
int bridge__add_topic(struct mosquitto__bridge *bridge, const char *topic, enum mosquitto__bridge_direction direction, int qos, const char *local_prefix, const char *remote_prefix)
|
||||
{
|
||||
struct mosquitto__bridge_topic *topics;
|
||||
struct mosquitto__bridge_topic *cur_topic;
|
||||
int len;
|
||||
|
||||
|
||||
if(bridge == NULL) return MOSQ_ERR_INVAL;
|
||||
if(direction != bd_out && direction != bd_in && direction != bd_both){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
if(qos < 0 || qos > 2){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
if(local_prefix && mosquitto_pub_topic_check(local_prefix)){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic local prefix '%s'.", local_prefix);
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
if(remote_prefix && mosquitto_pub_topic_check(remote_prefix)){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic remote prefix '%s'.", remote_prefix);
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
if((topic == NULL || !strcmp(topic, "\"\"")) &&
|
||||
(local_prefix == NULL || remote_prefix == NULL)){
|
||||
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge remapping.");
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
|
||||
|
||||
bridge->topic_count++;
|
||||
topics = mosquitto__realloc(bridge->topics,
|
||||
sizeof(struct mosquitto__bridge_topic)*bridge->topic_count);
|
||||
|
||||
if(topics == NULL){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
bridge->topics = topics;
|
||||
|
||||
cur_topic = &bridge->topics[bridge->topic_count-1];
|
||||
cur_topic->direction = direction;
|
||||
cur_topic->qos = qos;
|
||||
cur_topic->local_prefix = NULL;
|
||||
cur_topic->remote_prefix = NULL;
|
||||
|
||||
if(topic == NULL || !strcmp(topic, "\"\"")){
|
||||
cur_topic->topic = NULL;
|
||||
}else{
|
||||
cur_topic->topic = mosquitto__strdup(topic);
|
||||
if(cur_topic->topic == NULL){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if(local_prefix || remote_prefix){
|
||||
bridge->topic_remapping = true;
|
||||
if(local_prefix){
|
||||
cur_topic->local_prefix = mosquitto__strdup(local_prefix);
|
||||
if(cur_topic->local_prefix == NULL){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
if(remote_prefix){
|
||||
cur_topic->remote_prefix = mosquitto__strdup(remote_prefix);
|
||||
if(cur_topic->remote_prefix == NULL){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_topic->local_prefix){
|
||||
if(cur_topic->topic){
|
||||
len = strlen(cur_topic->topic) + strlen(cur_topic->local_prefix)+1;
|
||||
cur_topic->local_topic = mosquitto__malloc(len+1);
|
||||
if(!cur_topic->local_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(cur_topic->local_topic, len+1, "%s%s", cur_topic->local_prefix, cur_topic->topic);
|
||||
cur_topic->local_topic[len] = '\0';
|
||||
}else{
|
||||
cur_topic->local_topic = mosquitto__strdup(cur_topic->local_prefix);
|
||||
if(!cur_topic->local_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
cur_topic->local_topic = mosquitto__strdup(cur_topic->topic);
|
||||
if(!cur_topic->local_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_topic->remote_prefix){
|
||||
if(cur_topic->topic){
|
||||
len = strlen(cur_topic->topic) + strlen(cur_topic->remote_prefix)+1;
|
||||
cur_topic->remote_topic = mosquitto__malloc(len+1);
|
||||
if(!cur_topic->remote_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(cur_topic->remote_topic, len, "%s%s", cur_topic->remote_prefix, cur_topic->topic);
|
||||
cur_topic->remote_topic[len] = '\0';
|
||||
}else{
|
||||
cur_topic->remote_topic = mosquitto__strdup(cur_topic->remote_prefix);
|
||||
if(!cur_topic->remote_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
cur_topic->remote_topic = mosquitto__strdup(cur_topic->topic);
|
||||
if(!cur_topic->remote_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int bridge__remap_topic_in(struct mosquitto *context, char **topic)
|
||||
{
|
||||
struct mosquitto__bridge_topic *cur_topic;
|
||||
char *topic_temp;
|
||||
int i;
|
||||
int len;
|
||||
int rc;
|
||||
bool match;
|
||||
|
||||
if(context->bridge && context->bridge->topics && context->bridge->topic_remapping){
|
||||
for(i=0; i<context->bridge->topic_count; i++){
|
||||
cur_topic = &context->bridge->topics[i];
|
||||
if((cur_topic->direction == bd_both || cur_topic->direction == bd_in)
|
||||
&& (cur_topic->remote_prefix || cur_topic->local_prefix)){
|
||||
|
||||
/* Topic mapping required on this topic if the message matches */
|
||||
|
||||
rc = mosquitto_topic_matches_sub(cur_topic->remote_topic, *topic, &match);
|
||||
if(rc){
|
||||
mosquitto__free(*topic);
|
||||
return rc;
|
||||
}
|
||||
if(match){
|
||||
if(cur_topic->remote_prefix){
|
||||
/* This prefix needs removing. */
|
||||
if(!strncmp(cur_topic->remote_prefix, *topic, strlen(cur_topic->remote_prefix))){
|
||||
topic_temp = mosquitto__strdup((*topic)+strlen(cur_topic->remote_prefix));
|
||||
if(!topic_temp){
|
||||
mosquitto__free(*topic);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
mosquitto__free(*topic);
|
||||
*topic = topic_temp;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_topic->local_prefix){
|
||||
/* This prefix needs adding. */
|
||||
len = strlen(*topic) + strlen(cur_topic->local_prefix)+1;
|
||||
topic_temp = mosquitto__malloc(len+1);
|
||||
if(!topic_temp){
|
||||
mosquitto__free(*topic);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(topic_temp, len, "%s%s", cur_topic->local_prefix, *topic);
|
||||
topic_temp[len] = '\0';
|
||||
|
||||
mosquitto__free(*topic);
|
||||
*topic = topic_temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
118
src/conf.c
118
src/conf.c
@ -785,8 +785,6 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
|
||||
#ifdef WITH_BRIDGE
|
||||
char *tmp_char;
|
||||
struct mosquitto__bridge *cur_bridge = NULL;
|
||||
struct mosquitto__bridge_topic *cur_topic;
|
||||
int len;
|
||||
#endif
|
||||
struct mosquitto__auth_plugin_config *cur_auth_plugin_config = NULL;
|
||||
|
||||
@ -1973,29 +1971,14 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
char *topic = NULL;
|
||||
enum mosquitto__bridge_direction direction = bd_out;
|
||||
int qos = 0;
|
||||
char *local_prefix = NULL, *remote_prefix = NULL;
|
||||
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
if(token){
|
||||
cur_bridge->topic_count++;
|
||||
cur_bridge->topics = mosquitto__realloc(cur_bridge->topics,
|
||||
sizeof(struct mosquitto__bridge_topic)*cur_bridge->topic_count);
|
||||
if(!cur_bridge->topics){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
cur_topic = &cur_bridge->topics[cur_bridge->topic_count-1];
|
||||
if(!strcmp(token, "\"\"")){
|
||||
cur_topic->topic = NULL;
|
||||
}else{
|
||||
cur_topic->topic = mosquitto__strdup(token);
|
||||
if(!cur_topic->topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
cur_topic->direction = bd_out;
|
||||
cur_topic->qos = 0;
|
||||
cur_topic->local_prefix = NULL;
|
||||
cur_topic->remote_prefix = NULL;
|
||||
topic = token;
|
||||
}else{
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty topic value in configuration.");
|
||||
return MOSQ_ERR_INVAL;
|
||||
@ -2003,11 +1986,11 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
if(token){
|
||||
if(!strcasecmp(token, "out")){
|
||||
cur_topic->direction = bd_out;
|
||||
direction = bd_out;
|
||||
}else if(!strcasecmp(token, "in")){
|
||||
cur_topic->direction = bd_in;
|
||||
direction = bd_in;
|
||||
}else if(!strcasecmp(token, "both")){
|
||||
cur_topic->direction = bd_both;
|
||||
direction = bd_both;
|
||||
}else{
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic direction '%s'.", token);
|
||||
return MOSQ_ERR_INVAL;
|
||||
@ -2017,106 +2000,37 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
|
||||
if (token[0] == '#'){
|
||||
strtok_r(NULL, "", &saveptr);
|
||||
}
|
||||
cur_topic->qos = atoi(token);
|
||||
if(cur_topic->qos < 0 || cur_topic->qos > 2){
|
||||
qos = atoi(token);
|
||||
if(qos < 0 || qos > 2){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge QoS level '%s'.", token);
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
if(token){
|
||||
cur_bridge->topic_remapping = true;
|
||||
if(!strcmp(token, "\"\"") || token[0] == '#'){
|
||||
cur_topic->local_prefix = NULL;
|
||||
local_prefix = NULL;
|
||||
if (token[0] == '#'){
|
||||
strtok_r(NULL, "", &saveptr);
|
||||
}
|
||||
}else{
|
||||
if(mosquitto_pub_topic_check(token) != MOSQ_ERR_SUCCESS){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic local prefix '%s'.", token);
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
cur_topic->local_prefix = mosquitto__strdup(token);
|
||||
if(!cur_topic->local_prefix){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
local_prefix = token;
|
||||
}
|
||||
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
if(token){
|
||||
if(!strcmp(token, "\"\"") || token[0] == '#'){
|
||||
cur_topic->remote_prefix = NULL;
|
||||
remote_prefix = NULL;
|
||||
}else{
|
||||
if(mosquitto_pub_topic_check(token) != MOSQ_ERR_SUCCESS){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic remote prefix '%s'.", token);
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
cur_topic->remote_prefix = mosquitto__strdup(token);
|
||||
if(!cur_topic->remote_prefix){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
remote_prefix = mosquitto__strdup(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(cur_topic->topic == NULL &&
|
||||
(cur_topic->local_prefix == NULL || cur_topic->remote_prefix == NULL)){
|
||||
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge remapping.");
|
||||
if(bridge__add_topic(cur_bridge, topic, direction, qos, local_prefix, remote_prefix)){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
if(cur_topic->local_prefix){
|
||||
if(cur_topic->topic){
|
||||
len = strlen(cur_topic->topic) + strlen(cur_topic->local_prefix)+1;
|
||||
cur_topic->local_topic = mosquitto__malloc(len+1);
|
||||
if(!cur_topic->local_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(cur_topic->local_topic, len+1, "%s%s", cur_topic->local_prefix, cur_topic->topic);
|
||||
cur_topic->local_topic[len] = '\0';
|
||||
}else{
|
||||
cur_topic->local_topic = mosquitto__strdup(cur_topic->local_prefix);
|
||||
if(!cur_topic->local_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
cur_topic->local_topic = mosquitto__strdup(cur_topic->topic);
|
||||
if(!cur_topic->local_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_topic->remote_prefix){
|
||||
if(cur_topic->topic){
|
||||
len = strlen(cur_topic->topic) + strlen(cur_topic->remote_prefix)+1;
|
||||
cur_topic->remote_topic = mosquitto__malloc(len+1);
|
||||
if(!cur_topic->remote_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(cur_topic->remote_topic, len, "%s%s", cur_topic->remote_prefix, cur_topic->topic);
|
||||
cur_topic->remote_topic[len] = '\0';
|
||||
}else{
|
||||
cur_topic->remote_topic = mosquitto__strdup(cur_topic->remote_prefix);
|
||||
if(!cur_topic->remote_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
cur_topic->remote_topic = mosquitto__strdup(cur_topic->topic);
|
||||
if(!cur_topic->remote_topic){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
#else
|
||||
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
|
||||
#endif
|
||||
|
@ -184,7 +184,7 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
|
||||
}
|
||||
|
||||
#ifdef WITH_BRIDGE
|
||||
rc = bridge__remap_topic(context, &topic);
|
||||
rc = bridge__remap_topic_in(context, &topic);
|
||||
if(rc) return rc;
|
||||
|
||||
#endif
|
||||
|
@ -685,7 +685,8 @@ void bridge_check(struct mosquitto_db *db);
|
||||
void bridge_check(struct mosquitto_db *db, struct pollfd *pollfds, int *pollfd_index);
|
||||
#endif
|
||||
int bridge__register_local_connections(struct mosquitto_db *db);
|
||||
int bridge__remap_topic(struct mosquitto *context, char **topic);
|
||||
int bridge__add_topic(struct mosquitto__bridge *bridge, const char *topic, enum mosquitto__bridge_direction direction, int qos, const char *local_prefix, const char *remote_prefix);
|
||||
int bridge__remap_topic_in(struct mosquitto *context, char **topic);
|
||||
#endif
|
||||
|
||||
/* ============================================================
|
||||
|
@ -24,6 +24,15 @@ LIB_OBJS = memory_mosq.o \
|
||||
util_topic.o \
|
||||
utf8_mosq.o
|
||||
|
||||
BRIDGE_TOPIC_TEST_OBJS = \
|
||||
bridge_topic_test.o \
|
||||
stubs.o \
|
||||
|
||||
BRIDGE_TOPIC_OBJS = \
|
||||
bridge_topic.o \
|
||||
memory_mosq.o \
|
||||
util_topic.o \
|
||||
|
||||
PERSIST_READ_TEST_OBJS = \
|
||||
persist_read_test.o \
|
||||
persist_read_stubs.o
|
||||
@ -63,6 +72,9 @@ check : test
|
||||
mosq_test : ${TEST_OBJS} ${LIB_OBJS}
|
||||
$(CROSS_COMPILE)$(CC) $(LDFLAGS) -o $@ $^ $(LDADD)
|
||||
|
||||
bridge_topic_test : ${BRIDGE_TOPIC_TEST_OBJS} ${BRIDGE_TOPIC_OBJS}
|
||||
$(CROSS_COMPILE)$(CC) $(LDFLAGS) -o $@ $^ $(LDADD)
|
||||
|
||||
persist_read_test : ${PERSIST_READ_TEST_OBJS} ${PERSIST_READ_OBJS}
|
||||
$(CROSS_COMPILE)$(CC) $(LDFLAGS) -o $@ $^ $(LDADD)
|
||||
|
||||
@ -70,6 +82,9 @@ persist_write_test : ${PERSIST_WRITE_TEST_OBJS} ${PERSIST_WRITE_OBJS}
|
||||
$(CROSS_COMPILE)$(CC) $(LDFLAGS) -o $@ $^ $(LDADD)
|
||||
|
||||
|
||||
bridge_topic.o : ../../src/bridge_topic.c
|
||||
$(CROSS_COMPILE)$(CC) $(CPPFLAGS) $(CFLAGS) -DWITH_BROKER -DWITH_BRIDGE -c -o $@ $^
|
||||
|
||||
database.o : ../../src/database.c
|
||||
$(CROSS_COMPILE)$(CC) $(CPPFLAGS) $(CFLAGS) -DWITH_BROKER -DWITH_PERSISTENCE -c -o $@ $^
|
||||
|
||||
@ -112,14 +127,15 @@ utf8_mosq.o : ../../lib/utf8_mosq.c
|
||||
test-lib : mosq_test
|
||||
./mosq_test
|
||||
|
||||
test-broker : persist_read_test persist_write_test
|
||||
test-broker : bridge_topic_test persist_read_test persist_write_test
|
||||
./bridge_topic_test
|
||||
./persist_read_test
|
||||
./persist_write_test
|
||||
|
||||
test : test-broker test-lib
|
||||
|
||||
clean :
|
||||
-rm -rf mosq_test persist_read_test persist_write_test
|
||||
-rm -rf mosq_test bridge_topic_test persist_read_test persist_write_test
|
||||
-rm -rf *.o *.gcda *.gcno coverage.info out/
|
||||
|
||||
coverage :
|
||||
|
124
test/unit/bridge_topic_test.c
Normal file
124
test/unit/bridge_topic_test.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include <CUnit/Basic.h>
|
||||
|
||||
#define WITH_BRIDGE
|
||||
#define WITH_BROKER
|
||||
|
||||
#include "mosquitto_broker_internal.h"
|
||||
#include "property_mosq.h"
|
||||
#include "packet_mosq.h"
|
||||
|
||||
static void map_valid_helper(const char *topic, const char *local_prefix, const char *remote_prefix, const char *incoming, const char *expected)
|
||||
{
|
||||
struct mosquitto mosq;
|
||||
struct mosquitto__bridge bridge;
|
||||
char *map_topic;
|
||||
int rc;
|
||||
|
||||
memset(&mosq, 0, sizeof(struct mosquitto));
|
||||
memset(&bridge, 0, sizeof(struct mosquitto__bridge));
|
||||
|
||||
mosq.bridge = &bridge;
|
||||
|
||||
rc = bridge__add_topic(&bridge, topic, bd_in, 0, local_prefix, remote_prefix);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
map_topic = strdup(incoming);
|
||||
rc = bridge__remap_topic_in(&mosq, &map_topic);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
CU_ASSERT_PTR_NOT_NULL(map_topic);
|
||||
if(topic){
|
||||
CU_ASSERT_STRING_EQUAL(map_topic, expected);
|
||||
free(map_topic);
|
||||
}
|
||||
}
|
||||
|
||||
static void map_invalid_helper(const char *topic, const char *local_prefix, const char *remote_prefix)
|
||||
{
|
||||
struct mosquitto mosq;
|
||||
struct mosquitto__bridge bridge;
|
||||
int rc;
|
||||
|
||||
memset(&mosq, 0, sizeof(struct mosquitto));
|
||||
memset(&bridge, 0, sizeof(struct mosquitto__bridge));
|
||||
|
||||
mosq.bridge = &bridge;
|
||||
|
||||
rc = bridge__add_topic(&bridge, topic, bd_in, 0, local_prefix, remote_prefix);
|
||||
CU_ASSERT_NOT_EQUAL(rc, 0);
|
||||
}
|
||||
|
||||
|
||||
static void TEST_remap_valid(void)
|
||||
{
|
||||
/* Examples from man page */
|
||||
map_valid_helper("pattern", "L/", "R/", "R/pattern", "L/pattern");
|
||||
map_valid_helper("pattern", "L/", NULL, "pattern", "L/pattern");
|
||||
map_valid_helper("pattern", NULL, "R/", "R/pattern", "pattern");
|
||||
map_valid_helper("pattern", NULL, NULL, "pattern", "pattern");
|
||||
map_valid_helper(NULL, "local", "remote", "local", "remote");
|
||||
}
|
||||
|
||||
static void TEST_remap_invalid(void)
|
||||
{
|
||||
/* Examples from man page */
|
||||
map_invalid_helper(NULL, "L/", NULL);
|
||||
map_invalid_helper(NULL, NULL, "R/");
|
||||
map_invalid_helper(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
* TEST SUITE SETUP
|
||||
* ======================================================================== */
|
||||
|
||||
int init_bridge_tests(void)
|
||||
{
|
||||
CU_pSuite test_suite = NULL;
|
||||
|
||||
test_suite = CU_add_suite("Bridge remap", NULL, NULL);
|
||||
if(!test_suite){
|
||||
printf("Error adding CUnit Bridge remap test suite.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(0
|
||||
|| !CU_add_test(test_suite, "Remap valid", TEST_remap_valid)
|
||||
|| !CU_add_test(test_suite, "Remap invalid", TEST_remap_invalid)
|
||||
){
|
||||
|
||||
printf("Error adding Bridge remap CUnit tests.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int fails;
|
||||
|
||||
if(CU_initialize_registry() != CUE_SUCCESS){
|
||||
printf("Error initializing CUnit registry.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(0
|
||||
|| init_bridge_tests()
|
||||
){
|
||||
|
||||
CU_cleanup_registry();
|
||||
return 1;
|
||||
}
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
fails = CU_get_number_of_failures();
|
||||
CU_cleanup_registry();
|
||||
|
||||
return (int)fails;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user