diff --git a/proto/protocol.xml b/proto/protocol.xml index cd7b6e2..7f3dcf5 100644 --- a/proto/protocol.xml +++ b/proto/protocol.xml @@ -193,7 +193,32 @@ + + + A reason why a client was disconnected. + + + + + + + This event may be sent by the EIS implementation immediately before + the client is disconnected. + + Where a client is disconnected by EIS directly, the reason is + disconnect_reason.disconnected and the explanation is NULL. + + Where a client is disconnected due to some invalid request or other + protocol error, the reason is disconnect_reason.error and + explanation may contain a string explaining why. This string is + intended to help debugging only and is not guaranteed to stay constant. + + There is no guarantee this event is sent - the connection may be closed + without a disconnection event. + + + diff --git a/src/libei.c b/src/libei.c index 2e26c01..15cb431 100644 --- a/src/libei.c +++ b/src/libei.c @@ -1109,8 +1109,15 @@ ei_peek_event(struct ei *ei) return ei_event_ref(e); } -static int handle_msg_disconnected(struct ei_connection *connection) +static int handle_msg_disconnected(struct ei_connection *connection, uint32_t reason, const char *explanation) { + struct ei *ei = ei_connection_get_context(connection); + + if (reason == EI_CONNECTION_DISCONNECT_REASON_DISCONNECTED) + log_info(ei, "Disconnected by EIS"); + else + log_info(ei, "Disconnected after error: %s", explanation); + return -ECANCELED; } diff --git a/src/libeis-client.c b/src/libeis-client.c index 06b8512..88915c0 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -194,9 +194,11 @@ client_send_connection_setup(struct eis_client *client, struct eis_connection_se } static int -client_send_disconnect(struct eis_client *client) +client_send_disconnect(struct eis_client *client, const char *reason) { - return eis_connection_event_disconnected(client->connection); + return eis_connection_event_disconnected(client->connection, + reason ? EIS_CONNECTION_DISCONNECT_REASON_ERROR : EIS_CONNECTION_DISCONNECT_REASON_DISCONNECTED, + reason); } static int @@ -277,8 +279,8 @@ eis_client_connect(struct eis_client *client) client->state = EIS_CLIENT_STATE_CONNECTED; } -_public_ void -eis_client_disconnect(struct eis_client *client) +static void +client_disconnect(struct eis_client *client, const char *reason) { switch(client->state) { case EIS_CLIENT_STATE_DISCONNECTED: @@ -296,7 +298,7 @@ eis_client_disconnect(struct eis_client *client) eis_queue_disconnect_event(client); _fallthrough_; case EIS_CLIENT_STATE_NEW: - client_send_disconnect(client); + client_send_disconnect(client, reason); client->state = EIS_CLIENT_STATE_DISCONNECTED; source_remove(client->source); break; @@ -305,6 +307,12 @@ eis_client_disconnect(struct eis_client *client) eis_client_unref(client); } +_public_ void +eis_client_disconnect(struct eis_client *client) +{ + client_disconnect(client, NULL); +} + void eis_client_setup_done(struct eis_client *client, const char *name, bool is_sender) { @@ -559,7 +567,9 @@ client_msg_touch_up(struct eis_connection *connection, uint32_t deviceid, uint32 static int client_msg_disconnect(struct eis_connection *connection) { - return -ECANCELED; + struct eis_client * client = eis_connection_get_client(connection); + client_disconnect(client, NULL); + return 0; } static int @@ -648,7 +658,7 @@ client_dispatch(struct source *source, void *userdata) int rc = brei_dispatch(source_get_fd(source), lookup_object, client); if (rc < 0) { brei_drain_fd(source_get_fd(source)); - eis_client_disconnect(client); + client_disconnect(client, strerror(-rc)); } static const char *client_states[] = {