Add `mosquitto_kick_client_by_clientid()` and `mosquitto_kick_client_by_username()`

These can be used by plugins to disconnect clients.
pull/1639/head
Roger A. Light 5 years ago
parent 3f1515e337
commit f0862e26ec

@ -18,6 +18,8 @@ Broker:
plugins to determine which version of MQTT a client has connected with. plugins to determine which version of MQTT a client has connected with.
- Send DISCONNECT with `malformed-packet` reason code on invalid PUBLISH, - Send DISCONNECT with `malformed-packet` reason code on invalid PUBLISH,
SUBSCRIBE, and UNSUBSCRIBE packets. SUBSCRIBE, and UNSUBSCRIBE packets.
- Add `mosquitto_kick_client_by_clientid()` and `mosquitto_kick_client_by_username()`
functions, which can be used by plugins to disconnect clients.
Client library: Client library:
- Client no longer generates random client ids for v3.1.1 clients, these are - Client no longer generates random client ids for v3.1.1 clients, these are

@ -101,6 +101,7 @@ enum mosq_err_t {
MOSQ_ERR_TIMEOUT = 27, MOSQ_ERR_TIMEOUT = 27,
MOSQ_ERR_RETAIN_NOT_SUPPORTED = 28, MOSQ_ERR_RETAIN_NOT_SUPPORTED = 28,
MOSQ_ERR_TOPIC_ALIAS_INVALID = 29, MOSQ_ERR_TOPIC_ALIAS_INVALID = 29,
MOSQ_ERR_ADMINISTRATIVE_ACTION = 30,
}; };
/* Option values */ /* Option values */

@ -9,6 +9,8 @@ _mosquitto_client_protocol
_mosquitto_client_protocol_version _mosquitto_client_protocol_version
_mosquitto_client_sub_count _mosquitto_client_sub_count
_mosquitto_client_username _mosquitto_client_username
_mosquitto_kick_client_by_clientid
_mosquitto_kick_client_by_username
_mosquitto_log_printf _mosquitto_log_printf
_mosquitto_property_add_binary _mosquitto_property_add_binary
_mosquitto_property_add_byte _mosquitto_property_add_byte

@ -10,6 +10,8 @@
mosquitto_client_protocol_version; mosquitto_client_protocol_version;
mosquitto_client_sub_count; mosquitto_client_sub_count;
mosquitto_client_username; mosquitto_client_username;
mosquitto_kick_client_by_clientid;
mosquitto_kick_client_by_username;
mosquitto_log_printf; mosquitto_log_printf;
mosquitto_plugin_publish; mosquitto_plugin_publish;
mosquitto_property_add_binary; mosquitto_property_add_binary;

@ -300,12 +300,19 @@ void do_disconnect(struct mosquitto_db *db, struct mosquitto *context, int reaso
case MOSQ_ERR_KEEPALIVE: case MOSQ_ERR_KEEPALIVE:
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s has exceeded timeout, disconnecting.", id); log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s has exceeded timeout, disconnecting.", id);
break; break;
case MOSQ_ERR_ADMINISTRATIVE_ACTION:
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s been disconnected by administrative action.", id);
break;
default: default:
log__printf(NULL, MOSQ_LOG_NOTICE, "Socket error on client %s, disconnecting.", id); log__printf(NULL, MOSQ_LOG_NOTICE, "Socket error on client %s, disconnecting.", id);
break; break;
} }
}else{ }else{
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", id); if(reason == MOSQ_ERR_ADMINISTRATIVE_ACTION){
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s been disconnected by administrative action.", id);
}else{
log__printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", id);
}
} }
} }
mux__delete(db, context); mux__delete(db, context);

@ -179,6 +179,46 @@ const char *mosquitto_client_username(const struct mosquitto *client);
int mosquitto_set_username(struct mosquitto *client, const char *username); int mosquitto_set_username(struct mosquitto *client, const char *username);
/* =========================================================================
*
* Client control
*
* ========================================================================= */
/* Function: mosquitto_kick_client_by_clientid
*
* Forcefully disconnect a client from the broker.
*
* If clientid != NULL, then the client with the matching client id is
* disconnected from the broker.
* If clientid == NULL, then all clients are disconnected from the broker.
*
* If with_will == true, then if the client has a Last Will and Testament
* defined then this will be sent. If false, the LWT will not be sent.
*/
int mosquitto_kick_client_by_clientid(const char *clientid, bool with_will);
/* Function: mosquitto_kick_client_by_username
*
* Forcefully disconnect a client from the broker.
*
* If username != NULL, then all clients with a matching username are kicked
* from the broker.
* If username == NULL, then all clients that do not have a username are
* kicked.
*
* If with_will == true, then if the client has a Last Will and Testament
* defined then this will be sent. If false, the LWT will not be sent.
*/
int mosquitto_kick_client_by_username(const char *username, bool with_will);
/* =========================================================================
*
* Publishing functions
*
* ========================================================================= */
/* Function: mosquitto_broker_publish /* Function: mosquitto_broker_publish
* *
* Publish a message from within a plugin. * Publish a message from within a plugin.

@ -20,6 +20,9 @@ Contributors:
#include "mosquitto_internal.h" #include "mosquitto_internal.h"
#include "mosquitto_broker.h" #include "mosquitto_broker.h"
#include "memory_mosq.h" #include "memory_mosq.h"
#include "mqtt_protocol.h"
#include "send_mosq.h"
#include "util_mosq.h"
#include "utlist.h" #include "utlist.h"
#ifdef WITH_TLS #ifdef WITH_TLS
@ -230,3 +233,59 @@ int mosquitto_set_username(struct mosquitto *client, const char *username)
} }
} }
static void disconnect_client(struct mosquitto_db *db, struct mosquitto *context, bool with_will)
{
if(context->protocol == mosq_p_mqtt5){
send__disconnect(context, MQTT_RC_ADMINISTRATIVE_ACTION, NULL);
}
if(with_will == false){
mosquitto__set_state(context, mosq_cs_disconnecting);
}
do_disconnect(db, context, MOSQ_ERR_ADMINISTRATIVE_ACTION);
}
int mosquitto_kick_client_by_clientid(const char *clientid, bool with_will)
{
struct mosquitto_db *db;
struct mosquitto *ctxt, *ctxt_tmp;
db = mosquitto__get_db();
if(clientid == NULL){
HASH_ITER(hh_sock, db->contexts_by_sock, ctxt, ctxt_tmp){
disconnect_client(db, ctxt, with_will);
}
return MOSQ_ERR_SUCCESS;
}else{
HASH_FIND(hh_id, db->contexts_by_id, clientid, strlen(clientid), ctxt);
if(ctxt){
disconnect_client(db, ctxt, with_will);
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_NOT_FOUND;
}
}
}
int mosquitto_kick_client_by_username(const char *username, bool with_will)
{
struct mosquitto_db *db;
struct mosquitto *ctxt, *ctxt_tmp;
db = mosquitto__get_db();
if(username == NULL){
HASH_ITER(hh_sock, db->contexts_by_sock, ctxt, ctxt_tmp){
if(ctxt->username == NULL){
disconnect_client(db, ctxt, with_will);
}
}
}else{
HASH_ITER(hh_sock, db->contexts_by_sock, ctxt, ctxt_tmp){
if(ctxt->username != NULL && !strcmp(ctxt->username, username)){
disconnect_client(db, ctxt, with_will);
}
}
}
return MOSQ_ERR_SUCCESS;
}

Loading…
Cancel
Save