From: Felix Fietkau Date: Mon, 28 May 2012 22:56:37 +0000 (+0200) Subject: libubus: add support for reconnecting (and re-publishing objects) X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubus.git;a=commitdiff_plain;h=34161692fae8a5d81bc73e8005effd1fd13aa412 libubus: add support for reconnecting (and re-publishing objects) --- diff --git a/libubus.c b/libubus.c index 590a0fa..5488f3b 100644 --- a/libubus.c +++ b/libubus.c @@ -38,6 +38,7 @@ const char *__ubus_strerror[__UBUS_STATUS_LAST] = { [UBUS_STATUS_TIMEOUT] = "Request timed out", [UBUS_STATUS_NOT_SUPPORTED] = "Operation not supported", [UBUS_STATUS_UNKNOWN_ERROR] = "Unknown error", + [UBUS_STATUS_CONNECTION_FAILED] = "Connection failed", }; static struct blob_buf b; @@ -922,75 +923,108 @@ int ubus_send_event(struct ubus_context *ctx, const char *id, return ubus_complete_request(ctx, &req, 0); } -static void ubus_default_connection_lost(struct ubus_context *ctx) +static void +ubus_refresh_state(struct ubus_context *ctx) { - if (ctx->sock.registered) - uloop_end(); + struct ubus_object *obj, *tmp; + + /* clear all type IDs, they need to be registered again */ + avl_for_each_element(&ctx->objects, obj, avl) + obj->type->id = 0; + + /* push out all objects again */ + avl_for_each_element_safe(&ctx->objects, obj, avl, tmp) { + obj->id = 0; + avl_delete(&ctx->objects, &obj->avl); + ubus_add_object(ctx, obj); + } } -struct ubus_context *ubus_connect(const char *path) +int ubus_reconnect(struct ubus_context *ctx, const char *path) { - struct ubus_context *ctx; struct { struct ubus_msghdr hdr; struct blob_attr data; } hdr; struct blob_attr *buf; + int ret = UBUS_STATUS_UNKNOWN_ERROR; if (!path) path = UBUS_UNIX_SOCKET; - ctx = calloc(1, sizeof(*ctx)); - if (!ctx) - goto error; + if (ctx->sock.fd >= 0) { + if (ctx->sock.registered) + uloop_fd_delete(&ctx->sock); + + close(ctx->sock.fd); + } ctx->sock.fd = usock(USOCK_UNIX, path, NULL); if (ctx->sock.fd < 0) - goto error_free; - - ctx->sock.cb = ubus_handle_data; + return UBUS_STATUS_CONNECTION_FAILED; if (read(ctx->sock.fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - goto error_close; + goto out_close; if (!ubus_validate_hdr(&hdr.hdr)) - goto error_close; + goto out_close; if (hdr.hdr.type != UBUS_MSG_HELLO) - goto error_close; + goto out_close; buf = calloc(1, blob_raw_len(&hdr.data)); if (!buf) - goto error_close; + goto out_close; memcpy(buf, &hdr.data, sizeof(hdr.data)); if (read(ctx->sock.fd, blob_data(buf), blob_len(buf)) != blob_len(buf)) - goto error_free_buf; + goto out_free; ctx->local_id = hdr.hdr.peer; + if (!ctx->local_id) + goto out_free; + + ret = UBUS_STATUS_OK; + fcntl(ctx->sock.fd, F_SETFL, fcntl(ctx->sock.fd, F_GETFL) | O_NONBLOCK); + + ubus_refresh_state(ctx); + +out_free: free(buf); +out_close: + if (ret) + close(ctx->sock.fd); + + return ret; +} +static void ubus_default_connection_lost(struct ubus_context *ctx) +{ + if (ctx->sock.registered) + uloop_end(); +} + +struct ubus_context *ubus_connect(const char *path) +{ + struct ubus_context *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return NULL; + + ctx->sock.fd = -1; + ctx->sock.cb = ubus_handle_data; ctx->connection_lost = ubus_default_connection_lost; INIT_LIST_HEAD(&ctx->requests); INIT_LIST_HEAD(&ctx->pending); avl_init(&ctx->objects, ubus_cmp_id, false, NULL); - - if (!ctx->local_id) - goto error_close; - - fcntl(ctx->sock.fd, F_SETFL, fcntl(ctx->sock.fd, F_GETFL) | O_NONBLOCK); + if (ubus_reconnect(ctx, path)) { + free(ctx); + ctx = NULL; + } return ctx; - -error_free_buf: - free(buf); -error_close: - close(ctx->sock.fd); -error_free: - free(ctx); -error: - return NULL; } void ubus_free(struct ubus_context *ctx) diff --git a/libubus.h b/libubus.h index 13e4c03..917d122 100644 --- a/libubus.h +++ b/libubus.h @@ -153,6 +153,7 @@ struct ubus_request { struct ubus_context *ubus_connect(const char *path); +int ubus_reconnect(struct ubus_context *ctx, const char *path); void ubus_free(struct ubus_context *ctx); const char *ubus_strerror(int error); diff --git a/ubusmsg.h b/ubusmsg.h index 607ecd4..10f84db 100644 --- a/ubusmsg.h +++ b/ubusmsg.h @@ -92,6 +92,7 @@ enum ubus_msg_status { UBUS_STATUS_TIMEOUT, UBUS_STATUS_NOT_SUPPORTED, UBUS_STATUS_UNKNOWN_ERROR, + UBUS_STATUS_CONNECTION_FAILED, __UBUS_STATUS_LAST };