libamxrt  0.4.2
Ambiorix Run Time Library
amxrt_connections.c File Reference
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <amxrt/amxrt.h>
#include <amxp/amxp_dir.h>
#include <amxp/amxp_connection.h>
#include <amxb/amxb_register.h>
#include "amxrt_priv.h"

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 

Functions

static void amxrt_connection_read (UNUSED int fd, UNUSED void *priv)
 
static int amxrt_connection_listen_bus_uri (const char *uri, amxb_bus_ctx_t **bus_ctx)
 
static int amxrt_connection_connect_all_type (const amxc_llist_t *uris, uint32_t type)
 
static bool amxrt_list_contains (amxc_var_t *list, const char *value)
 
static int amxrt_connection_add_usp_socket (const char *name, void *priv)
 
static void amxrt_connection_filter_uris (const amxc_llist_t *uris, const amxc_llist_t *exclude_uris)
 
static void amxrt_add_known_uris (amxc_var_t *uris)
 
static void amxrt_set_backend_setting (amxc_var_t *config, const char *backend, const char *setting, const char *value)
 
static void amxrt_move_backend_uris (amxc_var_t *config, amxc_var_t *backend_settings)
 
void amxrt_connection_detect_sockets (amxc_var_t *config)
 
int amxrt_connection_load_backends (amxc_var_t *config)
 
int amxrt_connection_connect_all (amxo_parser_t *parser)
 
int amxrt_connection_listen_all (amxo_parser_t *parser)
 
int amxrt_connection_register_dm (UNUSED amxo_parser_t *parser, amxd_dm_t *dm)
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 56 of file amxrt_connections.c.

Function Documentation

◆ amxrt_add_known_uris()

static void amxrt_add_known_uris ( amxc_var_t *  uris)
static

Definition at line 183 of file amxrt_connections.c.

183  {
184  struct stat sb;
185 
186  // always check if not already added
187  if(amxb_be_get_info("pcb") != NULL) {
188  if(stat("/var/run/pcb_sys", &sb) == 0) {
189  if(!amxrt_list_contains(uris, "pcb:/var/run/pcb_sys")) {
190  amxc_var_add(cstring_t, uris, "pcb:/var/run/pcb_sys");
191  }
192  }
193  }
194  if(amxb_be_get_info("ubus") != NULL) {
195  if((stat("/var/run/ubus.sock", &sb) == 0) || (stat("/var/run/ubus/ubus.sock", &sb) == 0)) {
196  if(stat("/var/run/ubus.sock", &sb) == 0) {
197  if(!amxrt_list_contains(uris, "ubus:/var/run/ubus.sock")) {
198  amxc_var_add(cstring_t, uris, "ubus:/var/run/ubus.sock");
199  }
200  } else {
201  if(!amxrt_list_contains(uris, "ubus:/var/run/ubus/ubus.sock")) {
202  amxc_var_add(cstring_t, uris, "ubus:/var/run/ubus/ubus.sock");
203  }
204  }
205  }
206  }
207 
208  if(amxb_be_get_info("usp") != NULL) {
209  amxp_dir_scan("/var/run/usp", "d_type == DT_SOCK", false, amxrt_connection_add_usp_socket, uris);
210  }
211 }
static int amxrt_connection_add_usp_socket(const char *name, void *priv)
static bool amxrt_list_contains(amxc_var_t *list, const char *value)

◆ amxrt_connection_add_usp_socket()

static int amxrt_connection_add_usp_socket ( const char *  name,
void *  priv 
)
static

Definition at line 152 of file amxrt_connections.c.

152  {
153  amxc_var_t* sockets = (amxc_var_t*) priv;
154  amxc_string_t filename;
155  amxc_string_init(&filename, 0);
156  amxc_string_setf(&filename, "usp:%s", name);
157  if(!amxrt_list_contains(sockets, amxc_string_get(&filename, 0))) {
158  amxc_var_add(cstring_t, sockets, amxc_string_get(&filename, 0));
159  }
160  amxc_string_clean(&filename);
161 
162  return 0;
163 }

◆ amxrt_connection_connect_all()

int amxrt_connection_connect_all ( amxo_parser_t *  parser)

Definition at line 342 of file amxrt_connections.c.

342  {
343  int retval = 0;
344  const amxc_llist_t* uris = amxc_var_constcast(amxc_llist_t, GET_ARG(&parser->config, AMXRT_COPT_URIS));
345  const amxc_llist_t* data_uris = amxc_var_constcast(amxc_llist_t, GET_ARG(&parser->config, AMXRT_COPT_DATA_URIS));
346  bool connect = amxc_var_constcast(bool, GET_ARG(&parser->config, AMXRT_COPT_AUTO_CONNECT));
347  if(!connect) {
348  goto leave;
349  }
350 
351  amxrt_connection_filter_uris(uris, data_uris);
352  retval = amxrt_connection_connect_all_type(uris, AMXP_CONNECTION_BUS);
353  when_failed(retval, leave);
354  amxrt_connection_connect_all_type(data_uris, AMXP_CONNECTION_CUSTOM);
355 
356 leave:
357  return retval;
358 }
#define AMXRT_COPT_URIS
Definition: amxrt.h:73
#define AMXRT_COPT_DATA_URIS
Definition: amxrt.h:74
#define AMXRT_COPT_AUTO_CONNECT
Definition: amxrt.h:77
static void amxrt_connection_filter_uris(const amxc_llist_t *uris, const amxc_llist_t *exclude_uris)
static int amxrt_connection_connect_all_type(const amxc_llist_t *uris, uint32_t type)

◆ amxrt_connection_connect_all_type()

static int amxrt_connection_connect_all_type ( const amxc_llist_t *  uris,
uint32_t  type 
)
static

Definition at line 117 of file amxrt_connections.c.

118  {
119  int retval = 0;
120 
121  amxc_llist_for_each(it, uris) {
122  amxb_bus_ctx_t* bus_ctx = NULL;
123  int fd = -1;
124  const char* uri = amxc_var_constcast(cstring_t,
125  amxc_var_from_llist_it(it));
126 
127  retval = amxb_connect(&bus_ctx, uri);
128  if(retval != 0) {
129  amxrt_print_error("(%d) Failed to connect to [%s]\n", retval, uri);
130  } else {
131  fd = amxb_get_fd(bus_ctx);
132  amxp_connection_add(fd, amxrt_connection_read, uri, type, bus_ctx);
133  }
134  }
135 
136  return retval;
137 }
static void amxrt_connection_read(UNUSED int fd, UNUSED void *priv)
PRIVATE void amxrt_print_error(const char *fmt,...)

◆ amxrt_connection_detect_sockets()

void amxrt_connection_detect_sockets ( amxc_var_t *  config)

Definition at line 256 of file amxrt_connections.c.

256  {
257  amxc_var_t* uris = GET_ARG(config, AMXRT_COPT_URIS);
258  bool auto_detect = GET_BOOL(config, AMXRT_COPT_AUTO_DETECT);
259  amxc_array_t* backends = amxb_be_list();
260  size_t size = amxc_array_size(backends);
261 
262  // when auto-detect is on use the socket uris that:
263  // 1. are provided by the back-ends (these are the back-end default uris)
264  // 2. are known to libamxrt
265  // never add uris that are already defined in the config, make sure
266  // no double entries are added.
267 
268  if(auto_detect) {
269  // loop over all loaded backends and fetch uris and data-uris
270  // check if they are not already added to top-level uris or data-uris
271  // if not found in top level move them to top level otherwise delete them
272  for(size_t i = 0; i < size; i++) {
273  const char* be_name = (const char*) amxc_array_get_data_at(backends, i);
274  amxc_var_t* backend_settings = GET_ARG(config, be_name);
275  amxrt_move_backend_uris(config, backend_settings);
276  }
277  // last step - check known unix domain sockets - this for backwards compatibility
278  amxrt_add_known_uris(uris);
279  } else {
280  for(size_t i = 0; i < size; i++) {
281  const char* be_name = (const char*) amxc_array_get_data_at(backends, i);
282  amxc_var_t* backend_settings = GET_ARG(config, be_name);
283  amxc_var_t* be_uris = GET_ARG(backend_settings, AMXRT_COPT_URIS);
284  amxc_var_t* be_data_uris = GET_ARG(backend_settings, AMXRT_COPT_DATA_URIS);
285  amxc_var_delete(&be_uris);
286  amxc_var_delete(&be_data_uris);
287  }
288  }
289 
290  amxc_array_delete(&backends, NULL);
291 }
#define AMXRT_COPT_AUTO_DETECT
Definition: amxrt.h:76
static void amxrt_move_backend_uris(amxc_var_t *config, amxc_var_t *backend_settings)
static void amxrt_add_known_uris(amxc_var_t *uris)
config
Definition: test.odl:54

◆ amxrt_connection_filter_uris()

static void amxrt_connection_filter_uris ( const amxc_llist_t *  uris,
const amxc_llist_t *  exclude_uris 
)
static

Definition at line 165 of file amxrt_connections.c.

166  {
167  int cresult = 0;
168  amxc_var_t* euri_var = NULL;
169  amxc_var_t* uri_var = NULL;
170 
171  amxc_llist_for_each(eit, exclude_uris) {
172  euri_var = amxc_var_from_llist_it(eit);
173  amxc_llist_for_each(it, uris) {
174  uri_var = amxc_var_from_llist_it(it);
175  if((amxc_var_compare(uri_var, euri_var, &cresult) == 0) && (cresult == 0)) {
176  amxc_llist_it_take(it);
177  variant_list_it_free(it);
178  }
179  }
180  }
181 }

◆ amxrt_connection_listen_all()

int amxrt_connection_listen_all ( amxo_parser_t *  parser)

Definition at line 360 of file amxrt_connections.c.

360  {
361  int retval = 0;
362  const amxc_llist_t* listen = amxc_var_constcast(amxc_llist_t, GET_ARG(&parser->config, AMXRT_COPT_LISTEN));
363 
364  amxc_llist_for_each(it, listen) {
365  amxb_bus_ctx_t* bus_ctx = NULL;
366  int fd = -1;
367  const char* uri = amxc_var_constcast(cstring_t,
368  amxc_var_from_llist_it(it));
369 
370  retval = amxrt_connection_listen_bus_uri(uri, &bus_ctx);
371  if(retval != 0) {
372  amxrt_print_error("Failed to listen on %s", uri);
373  } else {
374  fd = amxb_get_fd(bus_ctx);
375  amxp_connection_add(fd, amxrt_connection_read, uri, AMXP_CONNECTION_LISTEN, bus_ctx);
376  }
377  }
378 
379  return retval;
380 }
#define AMXRT_COPT_LISTEN
Definition: amxrt.h:89
static int amxrt_connection_listen_bus_uri(const char *uri, amxb_bus_ctx_t **bus_ctx)

◆ amxrt_connection_listen_bus_uri()

static int amxrt_connection_listen_bus_uri ( const char *  uri,
amxb_bus_ctx_t **  bus_ctx 
)
static

Definition at line 107 of file amxrt_connections.c.

107  {
108  int retval = amxb_listen(bus_ctx, uri);
109  if(retval != 0) {
110  amxrt_print_error("(%d) Failed to listen on [%s]\n", retval, uri);
111  retval = 3;
112  }
113 
114  return retval;
115 }

◆ amxrt_connection_load_backends()

int amxrt_connection_load_backends ( amxc_var_t *  config)

Definition at line 293 of file amxrt_connections.c.

293  {
294  int retval = 0;
295  const char* name = GET_CHAR(config, AMXRT_COPT_NAME);
296  amxc_array_t* backend_names = NULL;
297  size_t size = 0;
298  amxc_var_t* backends = amxc_var_get_key(config, AMXRT_COPT_BACKENDS, AMXC_VAR_FLAG_COPY);
299 
300  if(amxc_var_type_of(backends) == AMXC_VAR_ID_LIST) {
301  const amxc_llist_t* bel = amxc_var_constcast(amxc_llist_t, backends);
302  if(amxc_llist_is_empty(bel)) {
303  amxrt_print_error("No backends specified\n");
304  retval = 2;
305  }
306  } else {
307  char* str = amxc_var_dyncast(cstring_t, backends);
308  if((str == NULL) || (str[0] == 0)) {
309  amxrt_print_error("No backends specified\n");
310  retval = 2;
311  }
312  free(str);
313  }
314 
315  if(retval == 0) {
316  retval = amxb_be_load_multiple(backends);
317  if(retval != 0) {
318  amxrt_print_error("Failed to load backends\n");
319  retval = 2;
320  }
321  }
322 
323  /*
324  Create backend config section if not existing
325  For backwards compatibility set `register-name` if not existing
326  Needed for pcb backend if loaded
327  */
328  backend_names = amxb_be_list();
329  size = amxc_array_size(backend_names);
330  for(size_t i = 0; i < size; i++) {
331  const char* be_name = (const char*) amxc_array_get_data_at(backend_names, i);
332  amxrt_set_backend_setting(config, be_name, "register-name", name);
333  }
334  amxc_array_delete(&backend_names, NULL);
335 
336  amxb_set_config(config);
337 
338  amxc_var_delete(&backends);
339  return retval;
340 }
#define AMXRT_COPT_BACKENDS
Definition: amxrt.h:75
#define AMXRT_COPT_NAME
Definition: amxrt.h:85
static void amxrt_set_backend_setting(amxc_var_t *config, const char *backend, const char *setting, const char *value)

◆ amxrt_connection_read()

static void amxrt_connection_read ( UNUSED int  fd,
UNUSED void *  priv 
)
static

Definition at line 70 of file amxrt_connections.c.

70  {
71  amxb_bus_ctx_t* bus_ctx = (amxb_bus_ctx_t*) priv;
72  int rv = 0;
73 
74  if(amxb_is_data_socket(bus_ctx)) {
75  rv = amxb_read(bus_ctx);
76  } else {
77  amxb_bus_ctx_t* new_ctx = NULL;
78  rv = amxb_accept(bus_ctx, &new_ctx);
79  if(rv == 0) {
80  fd = amxb_get_fd(new_ctx);
81  amxp_connection_add(fd, amxrt_connection_read, NULL, AMXO_BUS, new_ctx);
82  }
83  }
84  if(rv != 0) {
85  amxc_llist_t* connections = amxp_connection_get_connections();
86  amxp_connection_t* con = amxrt_el_get_connection(connections, fd);
87  when_null(con, exit);
88  amxrt_print_message("Failed to read from %s (%d), did the remote end hang up?",
89  con->uri == NULL ? "accepted" : con->uri, fd);
90  amxrt_print_message("=> Removing %s (%d)",
91  con->uri == NULL ? "accepted" : con->uri, fd);
92  amxp_connection_remove(fd);
93  amxb_free(&bus_ctx);
94 
95  if(amxc_llist_is_empty(amxp_connection_get_connections()) &&
96  amxc_llist_is_empty(amxp_connection_get_listeners())) {
97  amxrt_print_error("No more connections available");
98  amxrt_print_message("=> Stop application");
99  amxrt_el_stop();
100  }
101  }
102 
103 exit:
104  return;
105 }
PRIVATE void amxrt_print_message(const char *fmt,...)
PRIVATE amxp_connection_t * amxrt_el_get_connection(amxc_llist_t *cons, int fd)
int amxrt_el_stop(void)
Stops the event loop.

◆ amxrt_connection_register_dm()

int amxrt_connection_register_dm ( UNUSED amxo_parser_t *  parser,
amxd_dm_t *  dm 
)

Definition at line 382 of file amxrt_connections.c.

382  {
383  int retval = 0;
384  amxc_llist_t* connections = amxp_connection_get_connections();
385  amxc_llist_for_each(it, connections) {
386  amxp_connection_t* con = amxc_llist_it_get_data(it, amxp_connection_t, it);
387  amxb_bus_ctx_t* bus_ctx = (amxb_bus_ctx_t*) con->priv;
388  if(con->type != AMXP_CONNECTION_BUS) {
389  continue;
390  }
391  retval = amxb_register(bus_ctx, dm);
392  if(retval != 0) {
393  amxrt_print_error("Failed to register data model on %s", con->uri);
394  goto leave;
395  }
396  }
397 
398  amxc_llist_for_each(it, amxp_connection_get_listeners()) {
399  amxp_connection_t* con = amxc_llist_it_get_data(it, amxp_connection_t, it);
400  amxb_bus_ctx_t* bus_ctx = (amxb_bus_ctx_t*) con->priv;
401  retval = amxb_register(bus_ctx, dm);
402  when_failed(retval, leave);
403  }
404 
405 leave:
406  return retval;
407 }

◆ amxrt_list_contains()

static bool amxrt_list_contains ( amxc_var_t *  list,
const char *  value 
)
static

Definition at line 139 of file amxrt_connections.c.

139  {
140  bool retval = false;
141  amxc_var_for_each(v, list) {
142  const char* stored = GET_CHAR(v, NULL);
143  if(strcmp(stored, value) == 0) {
144  retval = true;
145  break;
146  }
147  }
148 
149  return retval;
150 }

◆ amxrt_move_backend_uris()

static void amxrt_move_backend_uris ( amxc_var_t *  config,
amxc_var_t *  backend_settings 
)
static

Definition at line 230 of file amxrt_connections.c.

230  {
231  amxc_var_t* uris = GET_ARG(config, AMXRT_COPT_URIS);
232  amxc_var_t* data_uris = GET_ARG(config, AMXRT_COPT_DATA_URIS);
233  amxc_var_t* be_uris = GET_ARG(backend_settings, AMXRT_COPT_URIS);
234  amxc_var_t* be_data_uris = GET_ARG(backend_settings, AMXRT_COPT_DATA_URIS);
235 
236  amxc_var_for_each(uri, be_uris) {
237  const char* u = GET_CHAR(uri, NULL);
238  if(!amxrt_list_contains(data_uris, u) &&
239  !amxrt_list_contains(uris, u)) {
240  amxc_var_set_index(uris, 0, uri, AMXC_VAR_FLAG_DEFAULT);
241  }
242  }
243 
244  amxc_var_for_each(uri, be_data_uris) {
245  const char* u = GET_CHAR(uri, NULL);
246  if(!amxrt_list_contains(data_uris, u) &&
247  !amxrt_list_contains(uris, u)) {
248  amxc_var_set_index(data_uris, 0, uri, AMXC_VAR_FLAG_DEFAULT);
249  }
250  }
251 
252  amxc_var_delete(&be_uris);
253  amxc_var_delete(&be_data_uris);
254 }

◆ amxrt_set_backend_setting()

static void amxrt_set_backend_setting ( amxc_var_t *  config,
const char *  backend,
const char *  setting,
const char *  value 
)
static

Definition at line 213 of file amxrt_connections.c.

216  {
217  amxc_var_t* backend_settings = GET_ARG(config, backend);
218  amxc_var_t* backend_config_opt = NULL;
219  if(backend_settings == NULL) {
220  backend_settings = amxc_var_add_key(amxc_htable_t, config, backend, NULL);
221  }
222  backend_config_opt = GET_ARG(backend_settings, setting);
223  if(backend_config_opt == NULL) {
224  amxc_var_add_key(cstring_t, backend_settings, setting, value);
225  } else {
226  amxc_var_set(cstring_t, backend_config_opt, value);
227  }
228 }