Add local_clientid for bridges.

This commit is contained in:
Roger A. Light 2014-06-10 23:30:15 +01:00
parent aca67a2170
commit 11631d8d92
7 changed files with 87 additions and 22 deletions

View File

@ -1,9 +1,20 @@
1.4 - xxxxxxxx
==============
Important changes:
- Bridge behaviour on the local broker has changed due to the introduction of
the local_* options. This may affect you if you are using authentication
and/or ACLs with bridges.
- The default TLS behaviour has changed to accept all of TLS v1.2, v1.1 and
v1.0, rather than only only one version of the protocol. It is still
possible to restrict a listener to a single version of TLS.
- The Python client has been removed now that the Eclipse Paho Python client
has had a release.
Broker:
- Add local_username, local_password for bridge connections to authenticate to
the local broker.
- Add local_clientid, local_username, local_password for bridge connections to
authenticate to the local broker.
- Default TLS mode now accepts TLS v1.2, v1.1 and v1.0.
- Support for ECDHE-ECDSA family ciphers.
- Fix bug #1324411, which could have had unexpected consequences for delayed

View File

@ -37,14 +37,25 @@ int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool cle
uint8_t byte;
int rc;
uint8_t version = PROTOCOL_VERSION_v31;
char *clientid;
assert(mosq);
assert(mosq->id);
#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
if(mosq->bridge){
clientid = mosq->bridge->clientid;
}else{
clientid = mosq->id;
}
#else
clientid = mosq->id;
#endif
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
if(!packet) return MOSQ_ERR_NOMEM;
payloadlen = 2+strlen(mosq->id);
payloadlen = 2+strlen(clientid);
if(mosq->will){
will = 1;
assert(mosq->will->topic);
@ -89,7 +100,7 @@ int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool cle
_mosquitto_write_uint16(packet, keepalive);
/* Payload */
_mosquitto_write_string(packet, mosq->id, strlen(mosq->id));
_mosquitto_write_string(packet, clientid, strlen(clientid));
if(will){
_mosquitto_write_string(packet, mosq->will->topic, strlen(mosq->will->topic));
_mosquitto_write_string(packet, (const char *)mosq->will->payload, mosq->will->payloadlen);
@ -104,10 +115,10 @@ int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool cle
mosq->keepalive = keepalive;
#ifdef WITH_BROKER
# ifdef WITH_BRIDGE
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", mosq->id);
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", clientid);
# endif
#else
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", mosq->id);
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", clientid);
#endif
return _mosquitto_packet_queue(mosq, packet);
}

View File

@ -918,6 +918,16 @@
to 60 seconds.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>local_clientid</option> <replaceable>password</replaceable></term>
<listitem>
<para>Set the clientid to use on the local broker. If not
defined, this defaults to
<option>local.&lt;clientid&gt;</option>. If you are
bridging a broker to itself, it is important that
local_clientid and clientid do not match.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>local_password</option> <replaceable>password</replaceable></term>
<listitem>

View File

@ -603,11 +603,16 @@
# remain connected until it fails
#round_robin false
# Set the client id for this bridge connection. If not defined,
# this defaults to 'name.hostname' where name is the connection
# name and hostname is the hostname of this computer.
# Set the client id to use on the remote end of this bridge connection. If not
# defined, this defaults to 'name.hostname' where name is the connection name
# and hostname is the hostname of this computer.
#clientid
# Set the clientid to use on the local broker. If not defined, this defaults to
# 'local.<clientid>'. If you are bridging a broker to itself, it is important
# that local_clientid and clientid do not match.
#local_clientid
# Set the clean session variable for this bridge.
# When set to true, when the bridge disconnects for any reason, all
# messages and subscriptions will be cleaned up on the remote

View File

@ -50,14 +50,12 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge)
struct mosquitto **tmp_contexts;
char hostname[256];
int len;
char *id;
char *id, *local_id;
assert(db);
assert(bridge);
if(bridge->clientid){
id = _mosquitto_strdup(bridge->clientid);
}else{
if(!bridge->clientid){
if(!gethostname(hostname, 256)){
len = strlen(hostname) + strlen(bridge->name) + 2;
id = _mosquitto_malloc(len);
@ -68,16 +66,25 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge)
}else{
return 1;
}
bridge->clientid = id;
}
if(!id){
return MOSQ_ERR_NOMEM;
if(bridge->local_clientid){
local_id = bridge->local_clientid;
}else{
len = strlen(bridge->clientid) + strlen("local.") + 2;
local_id = _mosquitto_malloc(len);
if(!local_id){
return MOSQ_ERR_NOMEM;
}
snprintf(local_id, len, "local.%s", bridge->clientid);
bridge->local_clientid = local_id;
}
/* Search for existing id (possible from persistent db) and also look for a
* gap in the db->contexts[] array in case the id isn't found. */
for(i=0; i<db->context_count; i++){
if(db->contexts[i]){
if(!strcmp(db->contexts[i]->id, id)){
if(!strcmp(db->contexts[i]->id, local_id)){
new_context = db->contexts[i];
break;
}
@ -90,7 +97,6 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge)
/* id wasn't found, so generate a new context */
new_context = mqtt3_context_init(-1);
if(!new_context){
_mosquitto_free(id);
return MOSQ_ERR_NOMEM;
}
if(null_index == -1){
@ -101,17 +107,13 @@ int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge)
db->contexts = tmp_contexts;
db->contexts[db->context_count-1] = new_context;
}else{
_mosquitto_free(id);
_mosquitto_free(new_context);
return MOSQ_ERR_NOMEM;
}
}else{
db->contexts[null_index] = new_context;
}
new_context->id = id;
}else{
/* id was found, so context->id already in memory. */
_mosquitto_free(id);
new_context->id = local_id;
}
new_context->bridge = bridge;
new_context->is_bridge = true;

View File

@ -251,6 +251,7 @@ void mqtt3_config_cleanup(struct mqtt3_config *config)
if(config->bridges[i].clientid) _mosquitto_free(config->bridges[i].clientid);
if(config->bridges[i].username) _mosquitto_free(config->bridges[i].username);
if(config->bridges[i].password) _mosquitto_free(config->bridges[i].password);
if(config->bridges[i].local_clientid) _mosquitto_free(config->bridges[i].local_clientid);
if(config->bridges[i].local_username) _mosquitto_free(config->bridges[i].local_username);
if(config->bridges[i].local_password) _mosquitto_free(config->bridges[i].local_password);
if(config->bridges[i].topics){
@ -1140,6 +1141,30 @@ int _config_read_file_core(struct mqtt3_config *config, bool reload, const char
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty listener value in configuration.");
return MOSQ_ERR_INVAL;
}
}else if(!strcmp(token, "local_clientid")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME
if(!cur_bridge){
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
}
token = strtok_r(NULL, " ", &saveptr);
if(token){
if(cur_bridge->local_clientid){
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate local_clientid value in bridge configuration.");
return MOSQ_ERR_INVAL;
}
cur_bridge->local_clientid = _mosquitto_strdup(token);
if(!cur_bridge->local_clientid){
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory");
return MOSQ_ERR_NOMEM;
}
}else{
cur_bridge->local_clientid = NULL;
}
#else
_mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
#endif
}else if(!strcmp(token, "local_password")){
#ifdef WITH_BRIDGE
if(reload) continue; // FIXME

View File

@ -272,6 +272,7 @@ struct _mqtt3_bridge{
time_t restart_t;
char *username;
char *password;
char *local_clientid;
char *local_username;
char *local_password;
bool notifications;