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[] = {