From 023b55f2e53ae07018921bbbc1ff1bd8a0e482d8 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov <rojer@cesanta.com> Date: Sun, 4 Jun 2017 15:10:52 +0100 Subject: [PATCH] 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 --- docs/c-api/mqtt.h/struct_mg_mqtt_proto_data.md | 1 + mongoose.c | 17 +++++++++++++++-- mongoose.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/c-api/mqtt.h/struct_mg_mqtt_proto_data.md b/docs/c-api/mqtt.h/struct_mg_mqtt_proto_data.md index 8ae54fcfc..f095589d2 100644 --- a/docs/c-api/mqtt.h/struct_mg_mqtt_proto_data.md +++ b/docs/c-api/mqtt.h/struct_mg_mqtt_proto_data.md @@ -5,6 +5,7 @@ symbol_kind: "struct" signature: | struct mg_mqtt_proto_data { uint16_t keep_alive; + double last_control_time; }; --- diff --git a/mongoose.c b/mongoose.c index 1424e929c..f69d00105 100644 --- a/mongoose.c +++ b/mongoose.c @@ -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 (conn->proto_data != NULL && conn->proto_data_destructor != NULL) { conn->proto_data_destructor(conn->proto_data); @@ -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)); switch (ev) { - case MG_EV_RECV: + case MG_EV_RECV: { /* There can be multiple messages in the buffer, process them all. */ while (1) { int len = parse_mqtt(io, &mm); @@ -9966,6 +9966,17 @@ static void mqtt_handler(struct mg_connection *nc, int ev, mbuf_remove(io, len); } 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) { static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd, 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; 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, } while (len > 0); 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) { diff --git a/mongoose.h b/mongoose.h index a8e30c3f3..209614cb6 100644 --- a/mongoose.h +++ b/mongoose.h @@ -5105,6 +5105,7 @@ struct mg_send_mqtt_handshake_opts { /* mg_mqtt_proto_data should be in header to allow external access to it */ struct mg_mqtt_proto_data { uint16_t keep_alive; + double last_control_time; }; /* Message types */ -- GitLab