libamxb  4.8.2
Bus Agnostic C API
Bus Connections

Functions

int amxb_connect (amxb_bus_ctx_t **ctx, const char *uri)
 Create a bus connection. More...
 
int amxb_connect_intf (amxb_bus_ctx_t **ctx, const char *uri, const char *intf)
 Create a bus connection. More...
 
int amxb_listen (amxb_bus_ctx_t **ctx, const char *uri)
 Create a listen socket. More...
 
int amxb_accept (amxb_bus_ctx_t *listen_ctx, amxb_bus_ctx_t **accepted_ctx)
 Accepts an incomming connection request. More...
 
int amxb_disconnect (amxb_bus_ctx_t *ctx)
 Disconnects a bus connection. More...
 
void amxb_free (amxb_bus_ctx_t **ctx)
 Frees allocated memory. More...
 
amxb_bus_ctx_tamxb_find_uri (const char *uri)
 Find the bus context for a given uri. More...
 
amxc_array_t * amxb_list_uris (void)
 List all open connections by their uri. More...
 
int amxb_get_fd (const amxb_bus_ctx_t *const ctx)
 Get the connection file descriptor. More...
 
int amxb_read (const amxb_bus_ctx_t *const ctx)
 Reads data from the file descriptor. More...
 
int amxb_read_raw (const amxb_bus_ctx_t *const ctx, void *buf, size_t count)
 Attempts to read up to count bytes from the file descriptor into the buffer starting at buf. More...
 
static void amxb_set_access (amxb_bus_ctx_t *const ctx, uint32_t access)
 Sets the access method. More...
 
static bool amxb_is_listen_socket (const amxb_bus_ctx_t *const ctx)
 Checks if the provided context is a listen socket. More...
 
static bool amxb_is_data_socket (const amxb_bus_ctx_t *const ctx)
 Checks if the provided context is a data socket. More...
 

Detailed Description

Function Documentation

◆ amxb_accept()

int amxb_accept ( amxb_bus_ctx_t listen_ctx,
amxb_bus_ctx_t **  accepted_ctx 
)

Accepts an incomming connection request.

To be able to accept incoming connection requests a listen socket must be created first. A listen socket can be created using amxb_listen.

This function is typically used from within an event loop callback function, and should be called when data is available on the created listen socket.

Note
This function allocates memory for the new connection context. The connection context can be freed using amxb_free
Parameters
listen_ctxThe listen connection context
accepted_ctxThe accepted connection
Returns

Definition at line 268 of file amxb_ba_connect.c.

268  {
269  int retval = -1;
270  amxb_be_funcs_t* fns = NULL;
271  const char* uri = NULL;
272  char* scheme = NULL;
273  char* host = NULL;
274  char* port = NULL;
275  char* path = NULL;
276 
277  when_null(listen_ctx, exit);
278  uri = amxc_htable_it_get_key(&listen_ctx->hit);
279  when_null(listen_ctx, exit);
280  retval = amxb_bus_ctx_create(accepted_ctx, &fns, uri, &scheme, &host, &port, &path);
281  when_failed(retval, exit);
282  if(amxb_is_valid_be_func(fns, accept, fns->accept)) {
283  (*accepted_ctx)->bus_ctx = fns->accept(listen_ctx->bus_ctx, &listen_ctx->sigmngr);
284  if((*accepted_ctx)->bus_ctx == NULL) {
285  retval = AMXB_ERROR_BACKEND_FAILED;
286  } else {
287  (*accepted_ctx)->dm = listen_ctx->dm;
288  amxc_llist_append(&fns->connections, &(*accepted_ctx)->it);
289  retval = 0;
290  }
291  } else {
293  }
294 
295 exit:
296  free(scheme);
297  free(port);
298  free(host);
299  free(path);
300  return retval;
301 }
static int amxb_bus_ctx_create(amxb_bus_ctx_t **ctx, amxb_be_funcs_t **fns, const char *uri, char **scheme, char **host, char **port, char **path)
#define amxb_is_valid_be_func(ft, member, ptr)
Definition: amxb_priv.h:78
#define AMXB_ERROR_BACKEND_FAILED
Back-end failed.
Definition: amxb_error.h:128
#define AMXB_ERROR_NOT_SUPPORTED_OP
Function/operation not supported.
Definition: amxb_error.h:110
The back-end interface structure.
amxb_be_accept_fn_t accept
amxc_llist_t connections
amxd_dm_t * dm
Definition: amxb_types.h:123
amxp_signal_mngr_t sigmngr
Definition: amxb_types.h:120
amxc_htable_it_t hit
Definition: amxb_types.h:117
void * bus_ctx
Definition: amxb_types.h:122

◆ amxb_connect()

int amxb_connect ( amxb_bus_ctx_t **  ctx,
const char *  uri 
)

Create a bus connection.

Connects to a bus using a uri.

The uri must be strictly compliant with RFC 3986. The scheme of the uri refers to the backend that is used. The other parts of the uri are used by the backend to create a connection

Searches a bus backend using the scheme of the uri, if found creates a connection to the bus and allocates a connection context.

Multiple connections can be created to different busses.

Note
This function allocates memory for the connection context. The connection context can be freed using amxb_free
Parameters
ctxThe connection context
uriThe connection uri, compliant with RFC 3986
Returns

Definition at line 235 of file amxb_ba_connect.c.

235  {
236  return amxb_connect_intf(ctx, uri, NULL);
237 }
int amxb_connect_intf(amxb_bus_ctx_t **ctx, const char *uri, const char *intf)
Create a bus connection.

◆ amxb_connect_intf()

int amxb_connect_intf ( amxb_bus_ctx_t **  ctx,
const char *  uri,
const char *  intf 
)

Create a bus connection.

Connects to a bus using a uri and a network interface name or id (aka zone id).

This function works exactly the same as Bus Connections, the interface name will be added to the host part of the uri prefixed with a %.

Parameters
ctxThe connection context
uriThe connection uri, compliant with RFC 3986
Returns

Definition at line 197 of file amxb_ba_connect.c.

197  {
198  int retval = -1;
199  amxb_be_funcs_t* fns = NULL;
200  char* scheme = NULL;
201  char* host = NULL;
202  char* port = NULL;
203  char* path = NULL;
204 
205  retval = amxb_bus_ctx_create(ctx, &fns, uri, &scheme, &host, &port, &path);
206  when_failed(retval, exit);
207  if((host != NULL) && (*host != 0) && (intf != NULL) && (*intf != 0)) {
208  // add the interface name/index prefixed with % to the host.
209  amxc_string_t host_intf;
210  amxc_string_init(&host_intf, 64);
211  amxc_string_setf(&host_intf, "%s%%%s", host, intf);
212  free(host);
213  host = amxc_string_take_buffer(&host_intf);
214  amxc_string_clean(&host_intf);
215  }
216 
217  if(amxb_is_valid_be_func(fns, connect, fns->connect)) {
218  retval = amxb_bus_ctx_be_init(*ctx, fns, fns->connect, uri, host, port, path);
219  } else {
221  }
222 
223  if(retval != 0) {
224  amxb_free(ctx);
225  }
226 
227 exit:
228  free(scheme);
229  free(port);
230  free(host);
231  free(path);
232  return retval;
233 }
static int amxb_bus_ctx_be_init(amxb_bus_ctx_t *ctx, amxb_be_funcs_t *fns, amxb_be_connect_fn_t fn, const char *uri, const char *host, const char *port, const char *path)
auto connect
Definition: test.odl:65
void amxb_free(amxb_bus_ctx_t **ctx)
Frees allocated memory.
amxb_be_connect_fn_t connect

◆ amxb_disconnect()

int amxb_disconnect ( amxb_bus_ctx_t ctx)

Disconnects a bus connection.

Closes the connection to a bus that was previously created with Bus Connections.

After calling this function the connection is closed and can not be used any more.

Note
This functions does not free the allocated memory for the connection context.
Parameters
ctxthe connection context
Returns

Definition at line 303 of file amxb_ba_connect.c.

303  {
304  int retval = -1;
305  const amxb_be_funcs_t* fns = NULL;
306 
307  when_null(ctx, exit);
308  when_null(ctx->bus_ctx, exit_clean);
309 
311 
312  amxc_llist_for_each(it, &ctx->client_subs) {
313  amxb_sub_t* sub = amxc_container_of(it, amxb_sub_t, it);
315  }
316 
317  fns = ctx->bus_fn;
318  if(amxb_is_valid_be_func(fns, disconnect, fns->disconnect)) {
319  retval = fns->disconnect(ctx->bus_ctx);
320  } else {
322  }
323 
324  if(fns->free != NULL) {
325  fns->free(ctx->bus_ctx);
326  }
327 
328 exit_clean:
329  amxc_llist_clean(&ctx->requests, amxb_free_request);
330  amxc_llist_clean(&ctx->invoke_ctxs, NULL);
331  amxc_llist_it_take(&ctx->it);
332  amxc_htable_it_clean(&ctx->hit, NULL);
333  ctx->bus_ctx = NULL;
334  ctx->bus_fn = NULL;
335 exit:
336  return retval;
337 }
static void amxb_free_request(amxc_llist_it_t *it)
int PRIVATE amxb_subscription_remove(amxb_subscription_t *subscription)
void amxb_be_cache_remove_ctx(amxb_bus_ctx_t *ctx)
Removes a bus context from the lookup cache.
amxb_be_disconnect_fn_t disconnect
amxb_be_free_fn_t free
const amxb_be_funcs_t * bus_fn
Definition: amxb_types.h:121
amxc_llist_t requests
Definition: amxb_types.h:118
amxc_llist_t client_subs
Definition: amxb_types.h:127
amxc_llist_t invoke_ctxs
Definition: amxb_types.h:119
amxc_llist_it_t it
Definition: amxb_types.h:116
Definition: amxb_priv.h:64
amxb_subscription_t data
Definition: amxb_priv.h:66

◆ amxb_find_uri()

amxb_bus_ctx_t* amxb_find_uri ( const char *  uri)

Find the bus context for a given uri.

If a connection already exists for a uri, the bus_ctx can be retrieved using this function

Parameters
uriThe connection uri
Returns
the bus context if any exists for the given uri, NULL otherwise.

Definition at line 360 of file amxb_ba_connect.c.

360  {
361  amxc_htable_it_t* hit = amxc_htable_get(&uri_bus_ctxs, uri);
362  amxb_bus_ctx_t* ctx = NULL;
363 
364  if(hit != NULL) {
365  ctx = amxc_htable_it_get_data(hit, amxb_bus_ctx_t, hit);
366  }
367  return ctx;
368 }
static amxc_htable_t uri_bus_ctxs

◆ amxb_free()

void amxb_free ( amxb_bus_ctx_t **  ctx)

Frees allocated memory.

The allocated memory for the connection context is freed.

The connection is automatically disconnected if it is still connected.

The pointer to the connection context is reset to NULL

Parameters
ctxthe connection context that was created with Bus Connections

Definition at line 339 of file amxb_ba_connect.c.

339  {
340  when_null(ctx, exit);
341  when_null(*ctx, exit);
342 
343  amxb_disconnect(*ctx);
344  amxp_sigmngr_clean(&(*ctx)->sigmngr);
345 
346  amxc_htable_for_each(it, &(*ctx)->subscriptions) {
347  amxp_slot_disconnect_with_priv(&(*ctx)->dm->sigmngr, amxb_dm_event_to_object_event, it);
348  amxc_htable_it_clean(it, NULL);
349  free(it);
350  }
351  amxc_htable_clean(&(*ctx)->subscriptions, NULL);
352 
353  free(*ctx);
354  *ctx = NULL;
355 
356 exit:
357  return;
358 }
void PRIVATE amxb_dm_event_to_object_event(const char *const sig_name, const amxc_var_t *const data, void *const priv)
Definition: amxb_ba_priv.c:76
int amxb_disconnect(amxb_bus_ctx_t *ctx)
Disconnects a bus connection.

◆ amxb_get_fd()

int amxb_get_fd ( const amxb_bus_ctx_t *const  ctx)

Get the connection file descriptor.

Gets the file descriptor of the connection context. Use this function to add the file descriptor to your event loop.

Parameters
ctxthe connection context
Returns
The valid file descriptor or -1 when no file descriptor is available.

Definition at line 375 of file amxb_ba_connect.c.

375  {
376  int retval = -1;
377  const amxb_be_funcs_t* fns = NULL;
378 
379  when_null(ctx, exit);
380  when_null(ctx->bus_ctx, exit);
381 
382  fns = ctx->bus_fn;
383  if(amxb_is_valid_be_func(fns, get_fd, fns->get_fd)) {
384  retval = fns->get_fd(ctx->bus_ctx);
385  when_true(retval < 0, exit);
386  }
387 
388 exit:
389  return retval;
390 }
amxb_be_get_fd_fn_t get_fd

◆ amxb_is_data_socket()

static bool amxb_is_data_socket ( const amxb_bus_ctx_t *const  ctx)
inlinestatic

Checks if the provided context is a data socket.

Data sockets are used to transfer messages between applications.

Parameters
ctxthe connection context
Returns
true when the provided connection context is a data socket, false otherwise

Definition at line 397 of file amxb_connect.h.

397  {
398  return ctx == NULL ? false : ctx->socket_type == AMXB_DATA_SOCK;
399 }
#define AMXB_DATA_SOCK
Definition: amxb_types.h:76
uint32_t socket_type
Definition: amxb_types.h:126

◆ amxb_is_listen_socket()

static bool amxb_is_listen_socket ( const amxb_bus_ctx_t *const  ctx)
inlinestatic

Checks if the provided context is a listen socket.

With a listen socket connection, incoming connection requests can be handled. Using listen sockets it is possible to create an E2E connection between different applications, without the need for a broker/dispatcher process.

Depending on the back-end and bus system used, this feature may not be available.

Parameters
ctxthe connection context
Returns
true when the provided connection context is a listen socket, false otherwise

Definition at line 379 of file amxb_connect.h.

379  {
380  return ctx == NULL ? false : ctx->socket_type == AMXB_LISTEN_SOCK;
381 }
#define AMXB_LISTEN_SOCK
Definition: amxb_types.h:77

◆ amxb_list_uris()

amxc_array_t* amxb_list_uris ( void  )

List all open connections by their uri.

returns an amxc_array_t containing const char * of all connect uris.

Note
The returned array contains const char*, the content should not be deleted The returned amxc_array_t* must be deleted using amxc_array_delete function.
Returns
A pointer to an amxc_array_t, which must be freed using amxc_array_delete Do not free the content of the array.

Definition at line 370 of file amxb_ba_connect.c.

370  {
371  amxc_array_t* keys = amxc_htable_get_sorted_keys(&uri_bus_ctxs);
372  return keys;
373 }

◆ amxb_listen()

int amxb_listen ( amxb_bus_ctx_t **  ctx,
const char *  uri 
)

Create a listen socket.

Creates a listen socket using a specific back-end.

The uri must be strictly compliant with RFC 3986. The scheme of the uri refers to the backend that is used. The other parts of the uri are used by the backend to create a connection

Searches a bus backend using the scheme of the uri, if found and the back-end supports the creation of a listen socket, a listen socket is created.

Multiple listen sockets can be created using different back-ends.

When a listen socket is created, its file descriptor should be added to the event loop, when data is available on that file descriptor (incoming connection), the callback function in the event loop should call amxb_accept

Note
This function allocates memory for the connection context. The connection context can be freed using amxb_free
Not all bus systems or back-ends support the creation of a listen socket. Consult the documentation of the back-end or the specific bus system to verify that listen sockets are supported.
Parameters
ctxThe connection context
uriThe listen uri, compliant with RFC 3986
Returns

Definition at line 239 of file amxb_ba_connect.c.

239  {
240  int retval = -1;
241  amxb_be_funcs_t* fns = NULL;
242  char* scheme = NULL;
243  char* host = NULL;
244  char* port = NULL;
245  char* path = NULL;
246 
247  retval = amxb_bus_ctx_create(ctx, &fns, uri, &scheme, &host, &port, &path);
248  when_failed(retval, exit);
249  (*ctx)->socket_type = AMXB_LISTEN_SOCK;
250  if(amxb_is_valid_be_func(fns, listen, fns->listen)) {
251  retval = amxb_bus_ctx_be_init(*ctx, fns, fns->listen, uri, host, port, path);
252  } else {
254  }
255 
256  if(retval != 0) {
257  amxb_free(ctx);
258  }
259 
260 exit:
261  free(scheme);
262  free(port);
263  free(host);
264  free(path);
265  return retval;
266 }
amxb_be_listen_fn_t listen

◆ amxb_read()

int amxb_read ( const amxb_bus_ctx_t *const  ctx)

Reads data from the file descriptor.

Reads data from the file descriptor of the connection context.

Typically the backend parses the received data and dispatches to the correct callbacks if needed.

This function is typically called whenever your eventloop detects that data is available for read on the connection context's file descriptor.

Parameters
ctxthe connection context
Returns
-1 when failed reading, other values are considered as success and depends on the backend implementation, typically the number of bytes read are returned.

Definition at line 392 of file amxb_ba_connect.c.

392  {
393  int retval = -1;
394  const amxb_be_funcs_t* fns = NULL;
395 
396  when_null(ctx, exit);
397  when_null(ctx->bus_ctx, exit);
398 
399  fns = ctx->bus_fn;
400  if(amxb_is_valid_be_func(fns, read, fns->read)) {
401  retval = fns->read(ctx->bus_ctx);
402  }
403 
404 exit:
405  return retval;
406 }
amxb_be_read_fn_t read

◆ amxb_read_raw()

int amxb_read_raw ( const amxb_bus_ctx_t *const  ctx,
void *  buf,
size_t  count 
)

Attempts to read up to count bytes from the file descriptor into the buffer starting at buf.

Reads data from the file descriptor of the connection context, and puts the read data in the provided bufffer, up to the given count bytes.

The data received is put in the buffer as is, not parsing is done.

This function is typically called whenever your eventloop detects that data is available for read on the connection context's file descriptor.

Note
do not use amxb_read and amxb_read_raw on the same context, only use one of them. When using this function it is up to the implementer to parse the received data and call any callbacks if needed.
Parameters
ctxthe connection context
bufpointer to a memory block where data can be put
countmaximum number of bytes that can be put in the memory block
Returns
-1 when failed reading, other values are considered as success and depends on the backend implementation, typically the number of bytes read are returned.

Definition at line 408 of file amxb_ba_connect.c.

408  {
409  int retval = -1;
410  const amxb_be_funcs_t* fns = NULL;
411 
412  when_null(ctx, exit);
413  when_null(ctx->bus_ctx, exit);
414  when_null(buf, exit);
415  when_true(count == 0, exit);
416 
417  fns = ctx->bus_fn;
418  if(amxb_is_valid_be_func(fns, read_raw, fns->read_raw)) {
419  retval = fns->read_raw(ctx->bus_ctx, buf, count);
420  }
421 
422 exit:
423  return retval;
424 }
amxb_be_read_raw_fn_t read_raw

◆ amxb_set_access()

static void amxb_set_access ( amxb_bus_ctx_t *const  ctx,
uint32_t  access 
)
inlinestatic

Sets the access method.

Parameters
ctxthe connection context
accessthe access method, must be one of AMXB_PUBLIC, AMXB_PROTECTED

Definition at line 355 of file amxb_connect.h.

355  {
356  if(ctx != NULL) {
357  ctx->access = access;
358  }
359 }
uint32_t access
Definition: amxb_types.h:125