Methods for infos on clients/onDisconnect callback

master
martin-ger 2020-12-15 23:08:51 +01:00
rodzic 7488d3307c
commit c7290c6837
6 zmienionych plików z 142 dodań i 15 usunięć

Wyświetl plik

@ -35,15 +35,28 @@ public:
void init();
// Callbacks on client actions
virtual bool onConnect(IPAddress addr, uint16_t client_count);
virtual bool onAuth(String username, String password);
virtual void onDisconnect(IPAddress addr, String client_id);
virtual bool onAuth(String username, String password, String client_id);
virtual void onData(String topic, const char *data, uint32_t length);
// Infos on currently connected clients
virtual uint16_t getClientCount();
virtual bool getClientId(uint16_t index, String &client_id);
virtual bool getClientAddr(uint16_t index, IPAddress& addr);
// Interaction with the local broker
virtual bool publish(String topic, uint8_t* data, uint16_t data_length, uint8_t qos=0, uint8_t retain=0);
virtual bool publish(String topic, String data, uint8_t qos=0, uint8_t retain=0);
virtual bool subscribe(String topic, uint8_t qos=0);
virtual bool unsubscribe(String topic);
// Cleanup all clients on Wifi connection loss
void cleanupClientConnections();
};
```
@ -77,19 +90,25 @@ With these functions you can publish and subscribe topics as a local client like
Username/password authentication is provided with the following interface:
```c
typedef bool (*MqttAuthCallback)(const char* username, const char *password, struct espconn *pesp_conn);
typedef bool (*MqttAuthCallback)(const char* username, const char *password, const char *client_id, struct espconn *pesp_conn);
void MQTT_server_onAuth(MqttAuthCallback authCb);
typedef bool (*MqttConnectCallback)(struct espconn *pesp_conn, uint16_t client_count);
void MQTT_server_onConnect(MqttConnectCallback connectCb);
typedef void (*MqttDisconnectCallback)(struct espconn *pesp_conn, const char *client_id);
void MQTT_server_onDisconnect(MqttDisconnectCallback disconnectCb);
```
If an *MqttAuthCallback* function is registered with MQTT_server_onAuth(), it is called on each connect request. Based on username, password, and optionally the connection info (e.g. the IP address) the function has to return *true* for authenticated or *false* for rejected. If a request provides no username and/or password these parameter strings are empty. If no *MqttAuthCallback* function is set, each request will be admitted.
If an *MqttAuthCallback* function is registered with MQTT_server_onAuth(), it is called on each connect request. Based on username, password, and optionally the connection info (the client Id and the IP address) the function has to return *true* for authenticated or *false* for rejected. If a request provides no username and/or password these parameter strings are empty. If no *MqttAuthCallback* function is set, each request will be admitted.
The *MqttConnectCallback* function does a similar check for the connection, but it is called right after the connect request before the MQTT connect request is processed. This is done in order to reject requests from unautorized clients in an early stage. The number of currently connected clients (incl. the current one) is given in the *client_count* paramater. With this info you can reject too many concurrent connections.
The *MqttDisconnectCallback* is called each time a client disconnects from the server.
If you want to force a cleanup when the broker as a WiFi client (WIFI_STA mode) has lost connectivity to the AP, call:
```c
void MQTT_server_cleanupClientCons();

Wyświetl plik

@ -26,9 +26,13 @@ public:
Serial.println(addr.toString()+" connected");
return true;
}
virtual bool onAuth(String username, String password) {
Serial.println("Username/Password: "+username+"/"+password);
virtual void onDisconnect(IPAddress addr, String client_id) {
Serial.println(addr.toString()+" ("+client_id+") disconnected");
}
virtual bool onAuth(String username, String password, String client_id) {
Serial.println("Username/Password/ClientId: "+username+"/"+password+"/"+client_id);
return true;
}
@ -38,6 +42,20 @@ public:
data_str[length] = '\0';
Serial.println("received topic '"+topic+"' with data '"+(String)data_str+"'");
//printClients();
}
// Sample for the usage of the client info methods
virtual void printClients() {
for (int i = 0; i < getClientCount(); i++) {
IPAddress addr;
String client_id;
getClientAddr(i, addr);
getClientId(i, client_id);
Serial.println("Client "+client_id+" on addr: "+addr.toString());
}
}
};
@ -104,4 +122,3 @@ void loop()
// wait a second
delay(1000);
}

Wyświetl plik

@ -14,8 +14,9 @@
#define LOCAL_MQTT_CLIENT ((void*)-1)
typedef bool (*MqttAuthCallback)(const char* username, const char *password, struct espconn *pesp_conn);
typedef bool (*MqttAuthCallback)(const char* username, const char *password, const char* client_id, struct espconn *pesp_conn);
typedef bool (*MqttConnectCallback)(struct espconn *pesp_conn, uint16_t client_count);
typedef bool (*MqttDisconnectCallback)(struct espconn *pesp_conn, const char* client_id);
typedef struct _MQTT_ClientCon {
struct espconn *pCon;
@ -42,12 +43,16 @@ typedef struct _MQTT_ClientCon {
extern MQTT_ClientCon *clientcon_list;
uint16_t MQTT_server_countClientCon();
const char* MQTT_server_getClientId(uint16_t index);
const struct espconn* MQTT_server_getClientPcon(uint16_t index);
void MQTT_server_disconnectClientCon(MQTT_ClientCon *mqttClientCon);
bool MQTT_server_deleteClientCon(MQTT_ClientCon *mqttClientCon);
void MQTT_server_cleanupClientCons();
bool MQTT_server_start(uint16_t portno, uint16_t max_subscriptions, uint16_t max_retained_topics);
void MQTT_server_onConnect(MqttConnectCallback connectCb);
void MQTT_server_onDisconnect(MqttDisconnectCallback connectCb);
void MQTT_server_onAuth(MqttAuthCallback authCb);
void MQTT_server_onData(MqttDataCallback dataCb);

Wyświetl plik

@ -35,6 +35,7 @@ LOCAL uint8_t zero_len_id[2] = { 0, 0 };
MQTT_ClientCon *clientcon_list;
LOCAL MqttDataCallback local_data_cb = NULL;
LOCAL MqttConnectCallback local_connect_cb = NULL;
LOCAL MqttDisconnectCallback local_disconnect_cb = NULL;
LOCAL MqttAuthCallback local_auth_cb = NULL;
MQTT_ClientCon dummy_clientcon;
@ -149,6 +150,28 @@ uint16_t ICACHE_FLASH_ATTR MQTT_server_countClientCon() {
return count;
}
const char* ICACHE_FLASH_ATTR MQTT_server_getClientId(uint16_t index) {
MQTT_ClientCon *p;
uint16_t count = 0;
for (p = clientcon_list; p != NULL; p = p->next, count++) {
if (count == index) {
return p->connect_info.client_id;
}
}
return NULL;
}
const struct espconn* ICACHE_FLASH_ATTR MQTT_server_getClientPcon(uint16_t index) {
MQTT_ClientCon *p;
uint16_t count = 0;
for (p = clientcon_list; p != NULL; p = p->next, count++) {
if (count == index) {
return p->pCon;
}
}
return NULL;
}
bool ICACHE_FLASH_ATTR MQTT_server_deleteClientCon(MQTT_ClientCon * mqttClientCon) {
MQTT_INFO("MQTT: DeleteClientCon\r\n");
@ -196,7 +219,10 @@ bool ICACHE_FLASH_ATTR MQTT_server_deleteClientCon(MQTT_ClientCon * mqttClientCo
if (mqttClientCon->connect_info.client_id != NULL) {
/* Don't attempt to free if it's the zero_len array */
if (((uint8_t *) mqttClientCon->connect_info.client_id) != zero_len_id)
os_free(mqttClientCon->connect_info.client_id);
if (local_disconnect_cb != NULL) {
local_disconnect_cb(mqttClientCon->pCon, mqttClientCon->connect_info.client_id);
}
os_free(mqttClientCon->connect_info.client_id);
mqttClientCon->connect_info.client_id = NULL;
}
@ -564,6 +590,7 @@ static void ICACHE_FLASH_ATTR MQTT_ClientCon_recv_cb(void *arg, char *pdata, uns
if ((local_auth_cb != NULL) &&
local_auth_cb(clientcon->connect_info.username==NULL?"":clientcon->connect_info.username,
clientcon->connect_info.password==NULL?"":clientcon->connect_info.password,
clientcon->connect_info.client_id,
clientcon->pCon) == false) {
MQTT_WARNING("MQTT: Authorization failed\r\n");
@ -977,6 +1004,10 @@ void ICACHE_FLASH_ATTR MQTT_server_onConnect(MqttConnectCallback connectCb) {
local_connect_cb = connectCb;
}
void ICACHE_FLASH_ATTR MQTT_server_onDisconnect(MqttDisconnectCallback disconnectCb) {
local_disconnect_cb = disconnectCb;
}
void ICACHE_FLASH_ATTR MQTT_server_onAuth(MqttAuthCallback authCb) {
local_auth_cb = authCb;
}

Wyświetl plik

@ -11,8 +11,15 @@ uMQTTBroker *uMQTTBroker::TheBroker;
return TheBroker->onConnect(connAddr, client_count);
}
bool uMQTTBroker::_onAuth(const char* username, const char *password, struct espconn *pesp_conn) {
return TheBroker->onAuth((String)username, (String)password);
void uMQTTBroker::_onDisconnect(struct espconn *pesp_conn, const char *client_id) {
IPAddress connAddr(pesp_conn->proto.tcp->remote_ip[0], pesp_conn->proto.tcp->remote_ip[1],
pesp_conn->proto.tcp->remote_ip[2], pesp_conn->proto.tcp->remote_ip[3]);
TheBroker->onDisconnect(connAddr, (String)client_id);
}
bool uMQTTBroker::_onAuth(const char* username, const char *password, const char* client_id, struct espconn *pesp_conn) {
return TheBroker->onAuth((String)username, (String)password, (String)client_id);
}
void uMQTTBroker::_onData(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t length) {
@ -30,6 +37,7 @@ uMQTTBroker *uMQTTBroker::TheBroker;
_max_retained_topics = max_retained_topics;
MQTT_server_onConnect(_onConnect);
MQTT_server_onDisconnect(_onDisconnect);
MQTT_server_onAuth(_onAuth);
MQTT_server_onData(_onData);
}
@ -42,7 +50,11 @@ uMQTTBroker *uMQTTBroker::TheBroker;
return true;
}
bool uMQTTBroker::onAuth(String username, String password) {
void uMQTTBroker::onDisconnect(IPAddress addr, String client_id) {
return;
}
bool uMQTTBroker::onAuth(String username, String password, String client_id) {
return true;
}
@ -53,6 +65,26 @@ uMQTTBroker *uMQTTBroker::TheBroker;
return MQTT_local_publish((uint8_t*)topic.c_str(), data, data_length, qos, retain);
}
uint16_t uMQTTBroker::getClientCount() {
return MQTT_server_countClientCon();
}
bool uMQTTBroker::getClientId(uint16_t index, String &client_id) {
const char *c = MQTT_server_getClientId(index);
if (c == NULL)
return false;
client_id = c;
return true;
}
bool uMQTTBroker::getClientAddr(uint16_t index, IPAddress& addr) {
const struct espconn* pesp_conn = MQTT_server_getClientPcon(index);
if (pesp_conn == NULL)
return false;
addr = pesp_conn->proto.tcp->remote_ip;
return true;
}
bool uMQTTBroker::publish(String topic, String data, uint8_t qos, uint8_t retain) {
return MQTT_local_publish((uint8_t*)topic.c_str(), (uint8_t*)data.c_str(), data.length(), qos, retain);
}

Wyświetl plik

@ -18,12 +18,14 @@ bool MQTT_server_start(uint16_t portno, uint16_t max_subscriptions, uint16_t max
// Callbacks for message reception, username/password authentication, and client connection
typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh);
typedef bool (*MqttAuthCallback)(const char* username, const char *password, struct espconn *pesp_conn);
typedef bool (*MqttAuthCallback)(const char* username, const char *password, const char *client_id, struct espconn *pesp_conn);
typedef bool (*MqttConnectCallback)(struct espconn *pesp_conn, uint16_t client_count);
typedef void (*MqttDisconnectCallback)(struct espconn *pesp_conn, const char *client_id);
void MQTT_server_onData(MqttDataCallback dataCb);
void MQTT_server_onAuth(MqttAuthCallback authCb);
void MQTT_server_onConnect(MqttConnectCallback connectCb);
void MQTT_server_onDisconnect(MqttDisconnectCallback disconnectCb);
// Interface for local pub/sub interaction with the broker
@ -42,6 +44,13 @@ void MQTT_server_cleanupClientCons();
void clear_retainedtopics();
int serialize_retainedtopics(char *buf, int len);
bool deserialize_retainedtopics(char *buf, int len);
// Interface for getting some infos on the currently connected clients
// MQTT_server_getClientId() and MQTT_server_getClientPcon() return NULL on invalid indices
uint16_t MQTT_server_countClientCon();
const char* MQTT_server_getClientId(uint16_t index);
const struct espconn* MQTT_server_getClientPcon(uint16_t index);
}
class uMQTTBroker
@ -53,7 +62,8 @@ private:
uint16_t _max_retained_topics;
static bool _onConnect(struct espconn *pesp_conn, uint16_t client_count);
static bool _onAuth(const char* username, const char *password, struct espconn *pesp_conn);
static void _onDisconnect(struct espconn *pesp_conn, const char *client_id);
static bool _onAuth(const char* username, const char *password, const char *client_id, struct espconn *pesp_conn);
static void _onData(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t length);
public:
@ -61,15 +71,28 @@ public:
void init();
// Callbacks on client actions
virtual bool onConnect(IPAddress addr, uint16_t client_count);
virtual bool onAuth(String username, String password);
virtual void onDisconnect(IPAddress addr, String client_id);
virtual bool onAuth(String username, String password, String client_id);
virtual void onData(String topic, const char *data, uint32_t length);
// Infos on currently connected clients
virtual uint16_t getClientCount();
virtual bool getClientId(uint16_t index, String &client_id);
virtual bool getClientAddr(uint16_t index, IPAddress& addr);
// Interaction with the local broker
virtual bool publish(String topic, uint8_t* data, uint16_t data_length, uint8_t qos=0, uint8_t retain=0);
virtual bool publish(String topic, String data, uint8_t qos=0, uint8_t retain=0);
virtual bool subscribe(String topic, uint8_t qos=0);
virtual bool unsubscribe(String topic);
// Cleanup all clients on Wifi connection loss
void cleanupClientConnections();
};