Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Functions | Variables
bridge_roles.c File Reference

Channel Bridging Roles API. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/datastore.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_roles.h"
#include "asterisk/stringfields.h"

Go to the source code of this file.

Data Structures

struct  bridge_role
 
struct  bridge_role_option
 
struct  bridge_roles_datastore
 

Functions

void ast_bridge_channel_clear_roles (struct ast_bridge_channel *bridge_channel)
 Clear all roles from a bridge_channel's role list. More...
 
int ast_bridge_channel_establish_roles (struct ast_bridge_channel *bridge_channel)
 Clone the roles from a bridge_channel's attached ast_channel onto the bridge_channel's role list. More...
 
const char * ast_bridge_channel_get_role_option (struct ast_bridge_channel *bridge_channel, const char *role_name, const char *option)
 Retrieve the value of a requested role option from a bridge channel. More...
 
int ast_bridge_channel_has_role (struct ast_bridge_channel *bridge_channel, const char *role_name)
 Check to see if a bridge channel inherited a specific role from its channel. More...
 
int ast_channel_add_bridge_role (struct ast_channel *chan, const char *role_name)
 Adds a bridge role to a channel. More...
 
void ast_channel_clear_bridge_roles (struct ast_channel *chan)
 Removes all bridge roles currently on a channel. More...
 
const char * ast_channel_get_role_option (struct ast_channel *channel, const char *role_name, const char *option)
 Retrieve the value of a requested role option from a channel. More...
 
int ast_channel_has_role (struct ast_channel *channel, const char *role_name)
 Check if a role exists on a channel. More...
 
void ast_channel_remove_bridge_role (struct ast_channel *chan, const char *role_name)
 Removes a bridge role from a channel. More...
 
int ast_channel_set_bridge_role_option (struct ast_channel *channel, const char *role_name, const char *option, const char *value)
 Set a role option on a channel. More...
 
static void bridge_role_datastore_destroy (void *data)
 
static void bridge_role_destroy (struct bridge_role *role)
 
static struct bridge_roles_datastorefetch_bridge_roles_datastore (struct ast_channel *chan)
 
static struct bridge_roles_datastorefetch_or_create_bridge_roles_datastore (struct ast_channel *chan)
 
static struct bridge_roleget_role_from_channel (struct ast_channel *channel, const char *role_name)
 
static struct bridge_roleget_role_from_datastore (struct bridge_roles_datastore *roles_datastore, const char *role_name)
 
static struct bridge_role_optionget_role_option (struct bridge_role *role, const char *option)
 
static int setup_bridge_role (struct bridge_roles_datastore *roles_datastore, const char *role_name)
 
static int setup_bridge_role_option (struct bridge_role *role, const char *option, const char *value)
 
static struct bridge_roles_datastoresetup_bridge_roles_datastore (struct ast_channel *chan)
 

Variables

static const struct ast_datastore_info bridge_role_info
 

Detailed Description

Channel Bridging Roles API.

Author
Jonathan Rose jrose.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file bridge_roles.c.

Function Documentation

void ast_bridge_channel_clear_roles ( struct ast_bridge_channel bridge_channel)

Clear all roles from a bridge_channel's role list.

Parameters
bridge_channelthe bridge channel that we are scrubbing

If roles are already established on a bridge channel, ast_bridge_channel_establish_roles will fail unconditionally without changing any roles. In order to update a bridge channel's roles, they must first be cleared from the bridge channel using this function.

Note
ast_bridge_channel_clear_roles also serves as the destructor for the role list of a bridge channel.

Definition at line 491 of file bridge_roles.c.

References ast_bridge_channel::bridge_roles.

Referenced by ast_bridge_channel_establish_roles().

492 {
493  if (bridge_channel->bridge_roles) {
494  bridge_role_datastore_destroy(bridge_channel->bridge_roles);
495  bridge_channel->bridge_roles = NULL;
496  }
497 }
struct bridge_roles_datastore * bridge_roles
int ast_bridge_channel_establish_roles ( struct ast_bridge_channel bridge_channel)

Clone the roles from a bridge_channel's attached ast_channel onto the bridge_channel's role list.

Parameters
bridge_channelThe bridge channel that we are preparing
Return values
0on success
-1on failure

This function should always be called when the bridge_channel binds to an ast_channel at some point before the bridge_channel joins or is imparted onto a bridge. Failure to do so will result in an empty role list. While the list remains established, changes to roles on the ast_channel will not propagate to the bridge channel and roles can not be re-established on the bridge channel without first clearing the roles with ast_bridge_roles_bridge_channel_clear_roles.

Definition at line 443 of file bridge_roles.c.

References ast_bridge_channel_clear_roles(), ast_calloc, ast_debug, AST_LIST_LAST, AST_LIST_TRAVERSE, ast_bridge_channel::bridge_roles, and ast_bridge_channel::chan.

444 {
445  struct bridge_roles_datastore *roles_datastore;
446  struct bridge_role *role = NULL;
447  struct bridge_role_option *role_option;
448 
449  if (!bridge_channel->chan) {
450  ast_debug(2, "Attempted to set roles on a bridge channel that has no associated channel. That's a bad idea.\n");
451  return -1;
452  }
453 
454  if (bridge_channel->bridge_roles) {
455  ast_debug(2, "Attempted to reset roles while roles were already established. Purge existing roles first.\n");
456  return -1;
457  }
458 
459  roles_datastore = fetch_bridge_roles_datastore(bridge_channel->chan);
460  if (!roles_datastore) {
461  /* No roles to establish. */
462  return 0;
463  }
464 
465  if (!(bridge_channel->bridge_roles = ast_calloc(1, sizeof(*bridge_channel->bridge_roles)))) {
466  return -1;
467  }
468 
469  AST_LIST_TRAVERSE(&roles_datastore->role_list, role, list) {
470  struct bridge_role *this_role_copy;
471 
472  if (setup_bridge_role(bridge_channel->bridge_roles, role->role)) {
473  /* We need to abandon the copy because we couldn't setup a role */
474  ast_bridge_channel_clear_roles(bridge_channel);
475  return -1;
476  }
477  this_role_copy = AST_LIST_LAST(&bridge_channel->bridge_roles->role_list);
478 
479  AST_LIST_TRAVERSE(&role->options, role_option, list) {
480  if (setup_bridge_role_option(this_role_copy, role_option->option, role_option->value)) {
481  /* We need to abandon the copy because we couldn't setup a role option */
482  ast_bridge_channel_clear_roles(bridge_channel);
483  return -1;
484  }
485  }
486  }
487 
488  return 0;
489 }
void ast_bridge_channel_clear_roles(struct ast_bridge_channel *bridge_channel)
Clear all roles from a bridge_channel's role list.
Definition: bridge_roles.c:491
#define ast_debug(level,...)
Log a DEBUG message.
struct bridge_roles_datastore * bridge_roles
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
struct ast_channel * chan
const char* ast_bridge_channel_get_role_option ( struct ast_bridge_channel bridge_channel,
const char *  role_name,
const char *  option 
)

Retrieve the value of a requested role option from a bridge channel.

Parameters
bridge_channelThe bridge channel we are retrieving the option from
role_nameName of the role the option will be retrieved from
optionName of the option we are retrieving the value of
Return values
NULLIf either the role does not exist on the bridge_channel or the role does exist but the option has not been set
Thevalue of the option
Note
See ast_channel_set_role_option note about the need to call ast_bridge_channel_establish_roles.
The returned character pointer is only valid as long as the bridge_channel is guaranteed to be alive and hasn't had ast_bridge_channel_clear_roles called against it (as this will free all roles and role options in the bridge channel). If you need this value after one of these destruction events occurs, you must make a local copy while it is still valid.

Definition at line 423 of file bridge_roles.c.

References ast_bridge_channel::bridge_roles.

424 {
425  struct bridge_role *role;
426  struct bridge_role_option *role_option = NULL;
427 
428  if (!bridge_channel->bridge_roles) {
429  return NULL;
430  }
431 
432  role = get_role_from_datastore(bridge_channel->bridge_roles, role_name);
433 
434  if (!role) {
435  return NULL;
436  }
437 
438  role_option = get_role_option(role, option);
439 
440  return role_option ? role_option->value : NULL;
441 }
struct bridge_roles_datastore * bridge_roles
int ast_bridge_channel_has_role ( struct ast_bridge_channel bridge_channel,
const char *  role_name 
)

Check to see if a bridge channel inherited a specific role from its channel.

Parameters
bridge_channelThe bridge channel being checked
role_nameName of the role being checked
Return values
0The bridge channel does not have the requested role
1The bridge channel does have the requested role
Note
Before a bridge_channel can effectively check roles against a bridge, ast_bridge_channel_establish_roles should be called on the bridge_channel so that roles and their respective role options can be copied from the channel datastore into the bridge_channel roles list. Otherwise this function will just return 0 because the list will be NULL.

Definition at line 414 of file bridge_roles.c.

References ast_bridge_channel::bridge_roles.

415 {
416  if (!bridge_channel->bridge_roles) {
417  return 0;
418  }
419 
420  return get_role_from_datastore(bridge_channel->bridge_roles, role_name) ? 1 : 0;
421 }
struct bridge_roles_datastore * bridge_roles
int ast_channel_add_bridge_role ( struct ast_channel chan,
const char *  role_name 
)

Adds a bridge role to a channel.

Parameters
chanAcquirer of the requested role
role_nameName of the role being attached
Return values
0on success
-1on failure

Definition at line 313 of file bridge_roles.c.

References ast_debug.

Referenced by bridge_agent_hold_push(), and parking_channel_set_roles().

314 {
315  struct bridge_roles_datastore *roles_datastore = fetch_or_create_bridge_roles_datastore(chan);
316 
317  if (!roles_datastore) {
318  ast_log(LOG_WARNING, "Unable to set up bridge role datastore on channel %s\n", ast_channel_name(chan));
319  return -1;
320  }
321 
322  /* Check to make sure we aren't adding a redundant role */
323  if (get_role_from_datastore(roles_datastore, role_name)) {
324  ast_debug(2, "Bridge role %s is already applied to the channel %s\n", role_name, ast_channel_name(chan));
325  return 0;
326  }
327 
328  /* It wasn't already there, so we can just finish setting it up now. */
329  return setup_bridge_role(roles_datastore, role_name);
330 }
#define ast_debug(level,...)
Log a DEBUG message.
void ast_channel_clear_bridge_roles ( struct ast_channel chan)

Removes all bridge roles currently on a channel.

Parameters
chanChannel the roles are being removed from

Definition at line 356 of file bridge_roles.c.

References ast_debug, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, and AST_LIST_TRAVERSE_SAFE_END.

357 {
358  struct bridge_roles_datastore *roles_datastore = fetch_bridge_roles_datastore(chan);
359  struct bridge_role *role;
360 
361  if (!roles_datastore) {
362  /* The roles datastore didn't already exist, so there is no need to remove any roles */
363  ast_debug(2, "Roles did not exist on channel %s\n", ast_channel_name(chan));
364  return;
365  }
366 
367  AST_LIST_TRAVERSE_SAFE_BEGIN(&roles_datastore->role_list, role, list) {
368  ast_debug(2, "Removing bridge role %s from channel %s\n", role->role, ast_channel_name(chan));
370  bridge_role_destroy(role);
371  }
373 }
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
const char* ast_channel_get_role_option ( struct ast_channel channel,
const char *  role_name,
const char *  option 
)

Retrieve the value of a requested role option from a channel.

Parameters
channelThe channel to retrieve the requested option from
role_nameThe role to which the option belongs
optionThe name of the option to retrieve
Return values
NULLThe option does not exist
non-NULLThe value of the option

This is an alternative to ast_bridge_channel_get_role_option that is useful if bridge roles have not yet been established on a channel's bridge_channel. A possible example of when this could be used is in a bridge v_table's push() callback.

Definition at line 399 of file bridge_roles.c.

400 {
401  struct bridge_role *role;
402  struct bridge_role_option *role_option;
403 
404  role = get_role_from_channel(channel, role_name);
405  if (!role) {
406  return NULL;
407  }
408 
409  role_option = get_role_option(role, option);
410 
411  return role_option ? role_option->value : NULL;
412 }
int ast_channel_has_role ( struct ast_channel channel,
const char *  role_name 
)

Check if a role exists on a channel.

Parameters
channelThe channel to check
role_nameThe name of the role to search for
Return values
0The requested role does not exist on the channel
1The requested role exists on the channel

This is an alternative to ast_bridge_channel_has_role that is useful if bridge roles have not yet been established on a channel's bridge_channel. A possible example of when this could be used is in a bridge v_table's push() callback.

Definition at line 394 of file bridge_roles.c.

395 {
396  return get_role_from_channel(channel, role_name) ? 1 : 0;
397 }
void ast_channel_remove_bridge_role ( struct ast_channel chan,
const char *  role_name 
)

Removes a bridge role from a channel.

Parameters
chanChannel the role is being removed from
role_nameName of the role being removed

Definition at line 332 of file bridge_roles.c.

References ast_debug, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, and AST_LIST_TRAVERSE_SAFE_END.

Referenced by attended_transfer_properties_shutdown(), and bridge_agent_hold_push().

333 {
334  struct bridge_roles_datastore *roles_datastore = fetch_bridge_roles_datastore(chan);
335  struct bridge_role *role;
336 
337  if (!roles_datastore) {
338  /* The roles datastore didn't already exist, so there is no need to remove a role */
339  ast_debug(2, "Role %s did not exist on channel %s\n", role_name, ast_channel_name(chan));
340  return;
341  }
342 
343  AST_LIST_TRAVERSE_SAFE_BEGIN(&roles_datastore->role_list, role, list) {
344  if (!strcmp(role->role, role_name)) {
345  ast_debug(2, "Removing bridge role %s from channel %s\n", role_name, ast_channel_name(chan));
347  bridge_role_destroy(role);
348  return;
349  }
350  }
352 
353  ast_debug(2, "Role %s did not exist on channel %s\n", role_name, ast_channel_name(chan));
354 }
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
int ast_channel_set_bridge_role_option ( struct ast_channel channel,
const char *  role_name,
const char *  option,
const char *  value 
)

Set a role option on a channel.

Parameters
channelChannel receiving the role option
role_nameRole the role option is applied to
optionName of the option
valueValue of the option
Return values
0on success
-1on failure

Definition at line 375 of file bridge_roles.c.

References ast_string_field_set.

Referenced by bridge_agent_hold_push(), and parking_channel_set_roles().

376 {
377  struct bridge_role *role = get_role_from_channel(channel, role_name);
378  struct bridge_role_option *role_option;
379 
380  if (!role) {
381  return -1;
382  }
383 
384  role_option = get_role_option(role, option);
385 
386  if (role_option) {
387  ast_string_field_set(role_option, value, value);
388  return 0;
389  }
390 
391  return setup_bridge_role_option(role, option, value);
392 }
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521

Variable Documentation

const struct ast_datastore_info bridge_role_info
static
Initial value:
= {
.type = "bridge roles",
.destroy = bridge_role_datastore_destroy,
}

Definition at line 98 of file bridge_roles.c.