Add max_keepalive, for limiting keepalives of MQTT v5 clients.

This commit is contained in:
Roger A. Light 2018-12-06 08:49:02 +00:00
parent 29846d282d
commit 6ef2c79e9a
10 changed files with 102 additions and 2 deletions

View File

@ -5,6 +5,8 @@ Broker features:
- Improved general support for broker generated client ids. Removed libuuid
dependency.
- auto_id_prefix now defaults to 'auto-'.
- Add max_keepalive option, to allow a maximum keepalive value to be set for
MQTT v5 clients only.
Client library features:
- Add mosquitto_subscribe_multiple() for sending subscriptions to multiple

View File

@ -62,6 +62,16 @@ int handle__connack(struct mosquitto *mosq)
}
}
}
prop = mosquitto_property_get_property(properties, MQTT_PROP_SERVER_KEEP_ALIVE, false);
if(prop){
rc = mosquitto_property_read_int16(prop, &mosq->keepalive);
if(rc){
mosquitto_property_free_all(&properties);
return rc;
}
}
log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK (%d)", mosq->id, reason_code);
pthread_mutex_lock(&mosq->callback_mutex);
if(mosq->on_connect){

View File

@ -435,6 +435,25 @@
<para>Reloaded on reload signal.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>max_keepalive</option> <replaceable>value</replaceable></term>
<listitem>
<para>For MQTT v5 clients, it is possible to have the
server send a "server keepalive" value that will
override the keepalive value set by the client. This
is intended to be used as a mechanism to say that the
server will disconnect the client earlier than it
anticipated, and that the client should use the new
keepalive value. The max_keepalive option allows you to
specify that clients may only connect with keepalive
less than or equal to this value, otherwise they will
be sent a server keepalive telling them to use
max_keepalive. This only applies to MQTT v5 clients.
The maximum value allowable, and default value, is
65535. Do not set below 10 seconds.</para>
<para>Reloaded on reload signal.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>max_queued_bytes</option> <replaceable>count</replaceable></term>
<listitem>

View File

@ -155,6 +155,16 @@
# false.
#retain_available true
# For MQTT v5 clients, it is possible to have the server send a "server
# keepalive" value that will override the keepalive value set by the client.
# This is intended to be used as a mechanism to say that the server will
# disconnect the client earlier than it anticipated, and that the client should
# use the new keepalive value. The max_keepalive option allows you to specify
# that clients may only connect with keepalive less than or equal to this
# value, otherwise they will be sent a server keepalive telling them to use
# max_keepalive. This only applies to MQTT v5 clients. The maximum value
# allowable is 65535. Do not set below 10.
#max_keepalive 65535
# =================================================================
# Default listener

View File

@ -212,6 +212,7 @@ static void config__init_reload(struct mosquitto_db *db, struct mosquitto__confi
}
#endif
config->log_timestamp = true;
config->max_keepalive = 65535;
config->persistence = false;
mosquitto__free(config->persistence_location);
config->persistence_location = NULL;
@ -1513,6 +1514,13 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, struct
}else{
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty max_inflight_messages value in configuration.");
}
}else if(!strcmp(token, "max_keepalive")){
if(conf__parse_int(&token, "max_keepalive", &tmp_int, saveptr)) return MOSQ_ERR_INVAL;
if(tmp_int < 10 || tmp_int > 65535){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid max_keepalive value (%d).", tmp_int);
return MOSQ_ERR_INVAL;
}
config->max_keepalive = tmp_int;
}else if(!strcmp(token, "max_queued_bytes")){
token = strtok_r(NULL, " ", &saveptr);
if(token){

View File

@ -297,11 +297,17 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
rc = 1;
goto handle_connect_error;
}
if(protocol_version == PROTOCOL_VERSION_v5 && context->keepalive > db->config->max_keepalive){
context->keepalive = db->config->max_keepalive;
if(mosquitto_property_add_int16(&connack_props, MQTT_PROP_SERVER_KEEP_ALIVE, context->keepalive)){
rc = MOSQ_ERR_NOMEM;
goto handle_connect_error;
}
}
if(protocol_version == PROTOCOL_VERSION_v5){
rc = property__read_all(CMD_CONNECT, &context->in_packet, &properties);
if(rc) return rc;
mosquitto_property_free_all(&properties);
if(rc) goto handle_connect_error;
}
property__process_connect(context, properties);

View File

@ -259,6 +259,7 @@ struct mosquitto__config {
bool log_timestamp;
char *log_file;
FILE *log_fptr;
uint16_t max_keepalive;
uint32_t message_size_limit;
bool persistence;
char *persistence_location;

View File

@ -0,0 +1,42 @@
#!/usr/bin/env python
# Test whether sending a non zero session expiry interval in DISCONNECT after
# having sent a zero session expiry interval is treated correctly in MQTT v5.
from mosq_test_helper import *
def write_config(filename, port):
with open(filename, 'w') as f:
f.write("port %d\n" % (port))
f.write("\n")
f.write("max_keepalive 60\n")
port = mosq_test.get_port(1)
conf_file = os.path.basename(__file__).replace('.py', '.conf')
write_config(conf_file, port)
rc = 1
keepalive = 61
connect_packet = mosq_test.gen_connect("test", proto_ver=5, keepalive=keepalive)
props = mqtt5_props.gen_uint16_prop(mqtt5_props.PROP_SERVER_KEEP_ALIVE, 60)
connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5, properties=props)
broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port, use_conf=True)
try:
sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=port)
sock.close()
rc = 0
finally:
os.remove(conf_file)
broker.terminate()
broker.wait()
(stdo, stde) = broker.communicate()
if rc:
print(stde)
exit(rc)

View File

@ -140,3 +140,4 @@ endif
./12-prop-subpub-payload-format.py
./12-prop-subpub-content-type.py
./12-prop-assigned-client-identifier.py
./12-prop-server-keepalive.py

View File

@ -109,6 +109,7 @@ tests = [
(1, './12-prop-subpub-payload-format.py'),
(1, './12-prop-subpub-content-type.py'),
(1, './12-prop-assigned-client-identifier.py'),
(1, './12-prop-server-keepalive.py'),
]
minport = 1888