diff options
author | Russell King <rmk@armlinux.org.uk> | 2021-09-26 13:18:15 +0100 |
---|---|---|
committer | Russell King <rmk@armlinux.org.uk> | 2021-09-26 13:19:28 +0100 |
commit | fc720a141bfcbe915cded0d78a5fd5aac358b6e1 (patch) | |
tree | 1abe09664b9459bfbb430731e2d550e352572659 | |
parent | 6e0f5e73810814afcc0420eca4afdd44af6cc942 (diff) |
resource: provide "backend" status events
Provide status events for the backend connection state, so the web
clients know whether anything is connected and when the last connect
or disconnect event happened.
Signed-off-by: Russell King <rmk@armlinux.org.uk>
-rw-r--r-- | resource.c | 56 | ||||
-rw-r--r-- | resource.h | 1 |
2 files changed, 43 insertions, 14 deletions
@@ -12,23 +12,17 @@ struct resource_object { static struct resource_object position_object; static struct resource_object signal_object; -static void resource_obj_send(struct client *c, struct resource_object *obj) +static void resource_obj_send_one(gpointer data, gpointer user_data) { - GString *string = obj->string; - - if (!string) - return; + GString *string = user_data; + struct client *c = data; respond_chunk(c, string); } -// Update this client with the new resource object data -static void resource_obj_update(gpointer data, gpointer user_data) +static void resource_obj_send_all(struct resource_object *obj, GString *str) { - struct resource_object *obj = user_data; - struct client *c = data; - - resource_obj_send(c, obj); + g_list_foreach(obj->client_list, resource_obj_send_one, str); } static void resource_obj_set_string(struct resource_object *obj, GString *str) @@ -39,7 +33,7 @@ static void resource_obj_set_string(struct resource_object *obj, GString *str) obj->string = str; g_string_free(old, TRUE); - g_list_foreach(obj->client_list, resource_obj_update, obj); + resource_obj_send_all(obj, str); } static void resource_obj_add_client(struct resource_object *obj, @@ -54,10 +48,23 @@ static void resource_obj_del_client(struct resource_object *obj, obj->client_list = g_list_remove(obj->client_list, c); } +static GString *object_backend_status(struct resource *r) +{ + GString *str; + + str = g_string_new("event: backend\n"); + g_string_append_printf(str, + "data: {\"status\":\"%s\",\"timestamp\":%ld}\n\n", + r->updater ? "connected" : "disconnected", + r->updater_time); + + return str; +} static int object_v1_get(struct client *c, struct resource *r) { struct resource_object *obj = r->data; + GString *str; respond_header(c, 200, "OK", "Cache-Control: no-cache\r\n" @@ -65,7 +72,13 @@ static int object_v1_get(struct client *c, struct resource *r) "Content-Type: text/event-stream; charset=UTF-8\r\n" "Transfer-Encoding: chunked\r\n"); - resource_obj_send(c, obj); + str = object_backend_status(r); + g_string_append(str, "retry: 10000\n"); + if (obj->string) + g_string_append_len(str, obj->string->str, + obj->string->len); + respond_chunk(c, str); + g_string_free(str, TRUE); // Add this client to the object list so it receives updates resource_obj_add_client(obj, c); @@ -83,8 +96,15 @@ static void object_v1_close(struct client *c, struct resource *r) static void object_v1_update_open(struct client *c, struct resource *r) { + GString *str; + // Keep track of the latest updater r->updater = c; + time(&r->updater_time); + + str = object_backend_status(r); + resource_obj_send_all(r->data, str); + g_string_free(str, TRUE); } // Update all attached clients with the new resource object data @@ -119,10 +139,18 @@ static int object_v1_update(struct client *c, struct resource *r, const char *m) static void object_v1_update_close(struct client *c, struct resource *r) { + GString *str; + // If the updater goes away, clear the data so we don't serve // stale data. - if (r->updater == c) + if (r->updater == c) { r->updater = NULL; + time(&r->updater_time); + + str = object_backend_status(r); + resource_obj_send_all(r->data, str); + g_string_free(str, TRUE); + } } static const struct resource_ops resource_v1_ops = { @@ -17,6 +17,7 @@ struct resource_ops { struct resource { const struct resource_ops *ops; struct client *updater; + time_t updater_time; void *data; }; |