31 #include "asterisk/stasis_channels.h"
32 #include "asterisk/stasis_bridges.h"
34 #include "asterisk/stasis_message_router.h"
35 #include "include/confbridge.h"
251 if (event_type == confbridge_start_type()) {
252 return "ConfbridgeStart";
253 }
else if (event_type == confbridge_end_type()) {
254 return "ConfbridgeEnd";
255 }
else if (event_type == confbridge_join_type()) {
256 return "ConfbridgeJoin";
257 }
else if (event_type == confbridge_leave_type()) {
258 return "ConfbridgeLeave";
259 }
else if (event_type == confbridge_start_record_type()) {
260 return "ConfbridgeRecord";
261 }
else if (event_type == confbridge_stop_record_type()) {
262 return "ConfbridgeStopRecord";
263 }
else if (event_type == confbridge_mute_type()) {
264 return "ConfbridgeMute";
265 }
else if (event_type == confbridge_unmute_type()) {
266 return "ConfbridgeUnmute";
267 }
else if (event_type == confbridge_talking_type()) {
268 return "ConfbridgeTalking";
269 }
else if (event_type == confbridge_welcome_type()) {
270 return "ConfbridgeWelcome";
329 static struct ast_json *pack_bridge_and_channels(
336 "{s: s, s: o, s: o, s: o }" :
"{s: s, s: o, s: o, s: [ o ] }";
341 "bridge", json_bridge,
342 "channels", json_channels);
352 json_bridge = bridge_to_json(bridge_snapshot);
353 json_channel = channel_to_json(channel_snapshot, conf_blob, labels_blob);
355 return pack_bridge_and_channels(json_bridge, json_channel, msg);
358 static void send_message(
const char *msg_name,
char *conf_name,
struct ast_json *json_object,
363 { .type = AST_MSG_DATA_ATTR_FROM, conf_name },
364 { .type = AST_MSG_DATA_ATTR_CONTENT_TYPE, .value =
"application/x-asterisk-confbridge-event+json"},
365 { .type = AST_MSG_DATA_ATTR_BODY, },
380 ast_log(LOG_ERROR,
"Unable to convert json_object for %s message to string\n", msg_name);
383 attrs[2].value = json;
385 data_msg =
ast_msg_data_alloc(AST_MSG_DATA_SOURCE_TYPE_IN_DIALOG, attrs, ARRAY_LEN(attrs));
387 ast_log(LOG_ERROR,
"Unable to create %s message for channel '%s'\n", msg_name,
388 ast_channel_name(chan));
393 memset(&f, 0,
sizeof(f));
395 f.data.ptr = data_msg;
403 ast_log(LOG_ERROR,
"Failed to queue %s message to '%s'\n%s\n", msg_name,
404 ast_channel_name(chan), json);
410 ast_debug(3,
"Queued %s message to '%s'\n%s\n", msg_name, ast_channel_name(chan), json);
420 int source_send_events = 0;
421 int source_echo_events = 0;
422 struct ast_json* json_channels = NULL;
426 ast_debug(3,
"Distributing %s event to participants\n", msg_name);
431 ast_log(LOG_ERROR,
"Unable to retrieve user profile for channel '%s'\n",
432 ast_channel_name(chan));
435 source_send_events = ast_test_flag(&u_profile, USER_OPT_SEND_EVENTS);
436 source_echo_events = ast_test_flag(&u_profile, USER_OPT_ECHO_EVENTS);
437 ast_debug(3,
"send_events: %d echo_events: %d for profile %s\n",
438 source_send_events, source_echo_events, u_profile.name);
442 ao2_lock(conference);
452 struct ast_json *target_json_channel;
455 if (!target_snapshot) {
456 ast_log(LOG_ERROR,
"Unable to get a channel snapshot for '%s'\n",
457 ast_channel_name(user->
chan));
461 target_json_channel = channel_to_json(target_snapshot, extras, NULL);
464 if (!json_channels) {
466 if (!json_channels) {
467 ast_log(LOG_ERROR,
"Unable to allocate json array\n");
477 if (!source_echo_events && user->
chan == chan) {
478 ast_debug(3,
"Skipping queueing %s message to '%s'. Same channel.\n", msg_name,
479 ast_channel_name(user->
chan));
484 if (!ast_test_flag(&user->
u_profile, USER_OPT_SEND_EVENTS)) {
485 ast_debug(3,
"Skipping queueing %s message to '%s'. Not receiving events.\n", msg_name,
486 ast_channel_name(user->
chan));
490 json_object = pack_snapshots(obj->
bridge, obj->
channel, extras, NULL, msg);
493 ast_log(LOG_ERROR,
"Unable to convert %s message to json\n", msg_name);
497 send_message(msg_name, conference->
name, json_object, user->
chan);
500 ao2_unlock(conference);
506 if (source_send_events && json_channels
512 json_bridge = bridge_to_json(obj->
bridge);
513 json_object = pack_bridge_and_channels(json_bridge, json_channels, msg);
515 ast_log(LOG_ERROR,
"Unable to convert ConfbridgeWelcome message to json\n");
520 send_message(welcome_msg_name, conference->
name, json_object, chan);
525 static void confbridge_publish_manager_event(
531 const char *conference_name;
535 ast_assert(blob != NULL);
536 ast_assert(
event != NULL);
544 ast_assert(conference_name != NULL);
550 ao2_cleanup(conference);
565 const char *json_key,
const char *ami_header)
581 return get_bool_header(extra_text, message,
"admin",
"Admin");
586 return get_bool_header(extra_text, message,
"muted",
"Muted");
592 confbridge_publish_manager_event(message, NULL);
598 confbridge_publish_manager_event(message, NULL);
604 struct ast_str *extra_text = NULL;
606 if (!get_admin_header(&extra_text, message)) {
607 confbridge_publish_manager_event(message, extra_text);
609 ast_free(extra_text);
615 struct ast_str *extra_text = NULL;
617 if (!get_admin_header(&extra_text, message)
618 && !get_muted_header(&extra_text, message)) {
619 confbridge_publish_manager_event(message, extra_text);
621 ast_free(extra_text);
638 if (msg->
dest_type == AST_ATTENDED_TRANSFER_DEST_APP
639 && strcmp(msg->dest.
app,
"ConfBridge") == 0) {
647 confbridge_publish_manager_event(message, NULL);
653 confbridge_publish_manager_event(message, NULL);
659 struct ast_str *extra_text = NULL;
661 if (!get_admin_header(&extra_text, message)) {
662 confbridge_publish_manager_event(message, extra_text);
664 ast_free(extra_text);
670 struct ast_str *extra_text = NULL;
672 if (!get_admin_header(&extra_text, message)) {
673 confbridge_publish_manager_event(message, extra_text);
675 ast_free(extra_text);
684 if (!talking_status) {
693 if (!get_admin_header(&extra_text, message)) {
694 confbridge_publish_manager_event(message, extra_text);
710 if (bridge_state_router) {
712 bridge_state_router = NULL;
715 if (channel_state_router) {
717 channel_state_router = NULL;
734 bridge_state_router = stasis_message_router_create(
737 if (!bridge_state_router) {
742 confbridge_start_type(),
749 confbridge_end_type(),
756 confbridge_join_type(),
763 ast_attended_transfer_type(),
764 confbridge_atxfer_cb,
770 confbridge_leave_type(),
777 confbridge_start_record_type(),
778 confbridge_start_record_cb,
784 confbridge_stop_record_type(),
785 confbridge_stop_record_cb,
791 confbridge_mute_type(),
798 confbridge_unmute_type(),
799 confbridge_unmute_cb,
805 confbridge_talking_type(),
806 confbridge_talking_cb,
812 channel_state_router = stasis_message_router_create(
815 if (!channel_state_router) {
821 confbridge_start_type(),
828 confbridge_end_type(),
835 confbridge_join_type(),
842 confbridge_leave_type(),
849 confbridge_start_record_type(),
850 confbridge_start_record_cb,
856 confbridge_stop_record_type(),
857 confbridge_stop_record_cb,
863 confbridge_mute_type(),
870 confbridge_unmute_type(),
871 confbridge_unmute_cb,
877 confbridge_talking_type(),
878 confbridge_talking_cb,
size_t ast_msg_data_get_length(struct ast_msg_data *msg)
Get length of the structure.
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
int manager_confbridge_init(void)
register stasis message routers to handle manager events for confbridge messages
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
struct ast_channel * chan
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
Message representing attended transfer.
struct ast_channel_snapshot * channel
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
int ast_json_object_update(struct ast_json *object, struct ast_json *other)
Update object with all of the fields of other.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int ast_json_object_del(struct ast_json *object, const char *key)
Delete a field from a JSON object.
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
Structure that contains a snapshot of information about a bridge.
const struct user_profile * conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result)
find a user profile given a user profile's name and store that profile in result structure.
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Structure representing a snapshot of channel state.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
Structure used to transport a message through the frame core.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
struct ast_msg_data * ast_msg_data_alloc(enum ast_msg_data_source_type source, struct ast_msg_data_attribute attributes[], size_t count)
Allocates an ast_msg_data structure.
struct confbridge_user::@94 list
void confbridge_handle_atxfer(struct ast_attended_transfer_message *msg)
Create join/leave events for attended transfers.
Out-of-call text message support.
struct confbridge_conference::@90 active_list
struct ast_bridge_snapshot * bridge
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
enum ast_transfer_result result
General Asterisk PBX channel definitions.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_str * ast_manager_build_bridge_state_string(const struct ast_bridge_snapshot *snapshot)
Generate the AMI message body from a bridge snapshot.
Blob of data associated with a bridge.
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
char * ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
Encode a JSON value to a string.
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
enum ast_attended_transfer_dest_type dest_type
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define STASIS_MESSAGE_TYPE_DEFN(name,...)
Boiler-plate messaging macro for defining public message types.
Support for dynamic strings.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
void manager_confbridge_shutdown(void)
unregister stasis message routers to handle manager events for confbridge messages ...
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
The structure that represents a conference bridge.
const char * confbridge_event_type_to_string(struct stasis_message_type *event_type)
Get the string representation of a confbridge stasis message type.
void conf_send_event_to_participants(struct confbridge_conference *conference, struct ast_channel *chan, struct stasis_message *msg)
Send events to bridge participants.
structure to hold users read from users.conf
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr)
Write a frame to the specified bridge_channel.
#define AST_YESNO(x)
return Yes or No depending on the argument.
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.
Structure that contains information regarding a channel in a bridge.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
static struct stasis_message_router * bridge_state_router
Message router for cached bridge state snapshot updates.
struct confbridge_conference * conf_find_bridge(const char *conference_name)
Find a confbridge by name.
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
The structure that represents a conference bridge user.
struct ast_json * ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_bridge_snapshot.
struct user_profile u_profile
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
int ast_json_string_set(struct ast_json *string, const char *value)
Change the value of a JSON string.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
int ast_str_append_event_header(struct ast_str **fields_string, const char *header, const char *value)
append an event header to an ast string
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ast_json * ast_json_copy(const struct ast_json *value)
Copy a JSON value, but not its children.