Commit 023b55f2 authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by Cesanta Bot

MQTT client keep alive fixes

 - Move keep alive management up to the Mongoose library
 - Only outgoing control messgaes should reset keepalive timer
 - Add unit test

https://forum.mongoose-os.com/discussion/1155/mqtt-keep-alive-compliance-issue

PUBLISHED_FROM=f86e30744ded53a6f7f96afec066b4ff3b4372c0
parent e4309d47
...@@ -5,6 +5,7 @@ symbol_kind: "struct" ...@@ -5,6 +5,7 @@ symbol_kind: "struct"
signature: | signature: |
struct mg_mqtt_proto_data { struct mg_mqtt_proto_data {
uint16_t keep_alive; uint16_t keep_alive;
double last_control_time;
}; };
--- ---
......
...@@ -2079,7 +2079,7 @@ void mg_if_poll(struct mg_connection *nc, time_t now) { ...@@ -2079,7 +2079,7 @@ void mg_if_poll(struct mg_connection *nc, time_t now) {
} }
} }
static void mg_destroy_conn(struct mg_connection *conn, int destroy_if) { void mg_destroy_conn(struct mg_connection *conn, int destroy_if) {
if (destroy_if) conn->iface->vtable->destroy_conn(conn); if (destroy_if) conn->iface->vtable->destroy_conn(conn);
if (conn->proto_data != NULL && conn->proto_data_destructor != NULL) { if (conn->proto_data != NULL && conn->proto_data_destructor != NULL) {
conn->proto_data_destructor(conn->proto_data); conn->proto_data_destructor(conn->proto_data);
...@@ -9957,7 +9957,7 @@ static void mqtt_handler(struct mg_connection *nc, int ev, ...@@ -9957,7 +9957,7 @@ static void mqtt_handler(struct mg_connection *nc, int ev,
nc->handler(nc, ev, ev_data MG_UD_ARG(user_data)); nc->handler(nc, ev, ev_data MG_UD_ARG(user_data));
switch (ev) { switch (ev) {
case MG_EV_RECV: case MG_EV_RECV: {
/* There can be multiple messages in the buffer, process them all. */ /* There can be multiple messages in the buffer, process them all. */
while (1) { while (1) {
int len = parse_mqtt(io, &mm); int len = parse_mqtt(io, &mm);
...@@ -9966,6 +9966,17 @@ static void mqtt_handler(struct mg_connection *nc, int ev, ...@@ -9966,6 +9966,17 @@ static void mqtt_handler(struct mg_connection *nc, int ev,
mbuf_remove(io, len); mbuf_remove(io, len);
} }
break; break;
}
case MG_EV_POLL: {
struct mg_mqtt_proto_data *pd =
(struct mg_mqtt_proto_data *) nc->proto_data;
double now = mg_time();
if (pd->keep_alive > 0 && pd->last_control_time > 0 &&
(now - pd->last_control_time) > pd->keep_alive) {
LOG(LL_DEBUG, ("Send PINGREQ"));
mg_mqtt_ping(nc);
}
}
} }
} }
...@@ -10007,6 +10018,7 @@ void mg_set_protocol_mqtt(struct mg_connection *nc) { ...@@ -10007,6 +10018,7 @@ void mg_set_protocol_mqtt(struct mg_connection *nc) {
static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd, static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd,
uint8_t flags, size_t len) { uint8_t flags, size_t len) {
struct mg_mqtt_proto_data *pd = (struct mg_mqtt_proto_data *) nc->proto_data;
size_t off = nc->send_mbuf.len - len; size_t off = nc->send_mbuf.len - len;
uint8_t header = cmd << 4 | (uint8_t) flags; uint8_t header = cmd << 4 | (uint8_t) flags;
...@@ -10026,6 +10038,7 @@ static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd, ...@@ -10026,6 +10038,7 @@ static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd,
} while (len > 0); } while (len > 0);
mbuf_insert(&nc->send_mbuf, off, buf, vlen - buf); mbuf_insert(&nc->send_mbuf, off, buf, vlen - buf);
pd->last_control_time = mg_time();
} }
void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id) { void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id) {
......
...@@ -5105,6 +5105,7 @@ struct mg_send_mqtt_handshake_opts { ...@@ -5105,6 +5105,7 @@ struct mg_send_mqtt_handshake_opts {
/* mg_mqtt_proto_data should be in header to allow external access to it */ /* mg_mqtt_proto_data should be in header to allow external access to it */
struct mg_mqtt_proto_data { struct mg_mqtt_proto_data {
uint16_t keep_alive; uint16_t keep_alive;
double last_control_time;
}; };
/* Message types */ /* Message types */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment