Amxb_Ubus  3.3.1
Ambiorix Ubus API
amxb_ubus_subscribe.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #include <stdlib.h>
56 
57 #include "amxb_ubus.h"
58 
59 static int amxb_ubus_receive_notification(struct ubus_context* ctx,
60  AMXB_UNUSED struct ubus_object* obj,
61  AMXB_UNUSED struct ubus_request_data* req,
62  const char* method,
63  struct blob_attr* msg) {
64  int status = UBUS_STATUS_UNKNOWN_ERROR;
65  struct ubus_subscriber* s = NULL;
66  amxb_ubus_t* amxb_ubus_ctx = NULL;
67  amxb_ubus_sub_t* amxb_ubus_sub = NULL;
68  amxc_htable_t* subscribers = NULL;
69  amxc_var_t notification;
70  const char* subscriber_object = NULL;
71 
72  amxc_var_init(&notification);
73  amxc_var_set_type(&notification, AMXC_VAR_ID_HTABLE);
74 
75  s = container_of(obj, struct ubus_subscriber, obj);
76  amxb_ubus_sub = container_of(s, amxb_ubus_sub_t, sub);
77  subscribers = container_of(amxb_ubus_sub->it.ait->array, amxc_htable_t, table);
78  amxb_ubus_ctx = container_of(subscribers, amxb_ubus_t, subscribers);
79 
80  subscriber_object = amxc_htable_it_get_key(&amxb_ubus_sub->it);
81  when_true(amxb_ubus_ctx->ubus_ctx != ctx, exit);
82 
83  amxb_ubus_parse_blob_table(&notification, (struct blob_attr*) blob_data(msg), blob_len(msg));
84  amxc_var_add_key(cstring_t, &notification, "notification", method);
85 
86  amxp_sigmngr_emit_signal(amxb_ubus_ctx->sigmngr, subscriber_object, &notification);
87 
88  status = UBUS_STATUS_OK;
89 
90 exit:
91  amxc_var_clean(&notification);
92  return status;
93 }
94 
95 int PRIVATE amxb_ubus_subscribe(void* const ctx,
96  const char* object) {
97  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx;
98  amxc_htable_it_t* it = NULL;
99  amxb_ubus_sub_t* amxb_ubus_sub = NULL;
100  amxc_string_t rel_path;
101  amxd_path_t path;
102  int ret = -1;
103  uint32_t id = 0;
104 
105  amxc_string_init(&rel_path, 64);
106  amxd_path_init(&path, NULL);
107  amxd_path_setf(&path, true, "%s", object);
108 
109  when_failed(amxb_ubus_get_longest_path(amxb_ubus_ctx, &path, &rel_path), exit);
110 
111  ret = ubus_lookup_id(amxb_ubus_ctx->ubus_ctx, amxd_path_get(&path, 0), &id);
112  when_true(ret != 0, exit);
113 
114  it = amxc_htable_get(&amxb_ubus_ctx->subscribers, amxd_path_get(&path, 0));
115  when_not_null(it, exit);
116 
117  amxb_ubus_sub = (amxb_ubus_sub_t*) calloc(1, sizeof(amxb_ubus_sub_t));
118  amxc_htable_insert(&amxb_ubus_ctx->subscribers,
119  object,
120  &amxb_ubus_sub->it);
121 
122  ret = ubus_register_subscriber(amxb_ubus_ctx->ubus_ctx,
123  &amxb_ubus_sub->sub);
124  when_true(ret != 0, exit);
125  amxb_ubus_sub->sub.cb = amxb_ubus_receive_notification;
126 
127  ret = ubus_subscribe(amxb_ubus_ctx->ubus_ctx, &amxb_ubus_sub->sub, id);
128 
129 exit:
130  amxc_string_clean(&rel_path);
131  amxd_path_clean(&path);
132  return ret;
133 }
134 
135 int PRIVATE amxb_ubus_unsubscribe(void* const ctx,
136  const char* object) {
137  amxb_ubus_t* amxb_ubus_ctx = (amxb_ubus_t*) ctx;
138  amxb_ubus_sub_t* amxb_ubus_sub = NULL;
139  amxc_htable_it_t* it = NULL;
140  amxc_string_t rel_path;
141  amxd_path_t path;
142  int ret = 0;
143  uint32_t id = 0;
144 
145  amxc_string_init(&rel_path, 64);
146  amxd_path_init(&path, NULL);
147  amxd_path_setf(&path, true, "%s", object);
148 
149  amxb_ubus_get_longest_path(amxb_ubus_ctx, &path, &rel_path);
150 
151  it = amxc_htable_get(&amxb_ubus_ctx->subscribers, object);
152  when_null(it, leave);
153  amxb_ubus_sub = amxc_htable_it_get_data(it, amxb_ubus_sub_t, it);
154 
155  ret = ubus_lookup_id(amxb_ubus_ctx->ubus_ctx, amxd_path_get(&path, 0), &id);
156  when_true(ret != 0, exit);
157 
158  ubus_unsubscribe(amxb_ubus_ctx->ubus_ctx, &amxb_ubus_sub->sub, id);
159 
160 exit:
161  ret = ubus_unregister_subscriber(amxb_ubus_ctx->ubus_ctx, &amxb_ubus_sub->sub);
162 
163  amxc_htable_it_clean(it, NULL);
164  amxp_timer_delete(&amxb_ubus_sub->reactivate);
165  free(amxb_ubus_sub);
166 
167 leave:
168  amxc_string_clean(&rel_path);
169  amxd_path_clean(&path);
170 
171  return ret;
172 }
173 
int PRIVATE amxb_ubus_parse_blob_table(amxc_var_t *var, struct blob_attr *attr, int len)
int PRIVATE amxb_ubus_get_longest_path(amxb_ubus_t *amxb_ubus_ctx, amxd_path_t *path, amxc_string_t *rel_path)
static int amxb_ubus_receive_notification(struct ubus_context *ctx, AMXB_UNUSED struct ubus_object *obj, AMXB_UNUSED struct ubus_request_data *req, const char *method, struct blob_attr *msg)
int PRIVATE amxb_ubus_unsubscribe(void *const ctx, const char *object)
int PRIVATE amxb_ubus_subscribe(void *const ctx, const char *object)
amxp_timer_t * reactivate
Definition: amxb_ubus.h:83
amxc_htable_it_t it
Definition: amxb_ubus.h:81
struct ubus_subscriber sub
Definition: amxb_ubus.h:82
amxc_htable_t subscribers
Definition: amxb_ubus.h:88
struct ubus_context * ubus_ctx
Definition: amxb_ubus.h:87
amxp_signal_mngr_t * sigmngr
Definition: amxb_ubus.h:90