Asterisk - The Open Source Telephony Project GIT-master-7988d11
Loading...
Searching...
No Matches
Data Structures | Enumerations | Functions
resource_bridges.c File Reference

Implementation for ARI stubs. More...

#include "asterisk.h"
#include "resource_bridges.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_app.h"
#include "asterisk/stasis_app_impl.h"
#include "asterisk/stasis_app_playback.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/core_unreal.h"
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
#include "asterisk/format_cap.h"
#include "asterisk/file.h"
#include "asterisk/musiconhold.h"
#include "asterisk/format_cache.h"
Include dependency graph for resource_bridges.c:

Go to the source code of this file.

Data Structures

struct  bridge_channel_control_thread_data
 
struct  control_list
 

Enumerations

enum  play_found_result { PLAY_FOUND_SUCCESS , PLAY_FOUND_FAILURE , PLAY_FOUND_CHANNEL_UNAVAILABLE }
 

Functions

static void ari_bridges_handle_play (const char *args_bridge_id, const char **args_media, size_t args_media_count, const char *args_format, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response)
 
static enum play_found_result ari_bridges_play_found (const char **args_media, size_t args_media_count, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge, struct ast_channel *found_channel)
 Performs common setup for a bridge playback operation with both new controls and when existing controls are found.
 
static int ari_bridges_play_helper (const char **args_media, size_t args_media_count, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge, struct stasis_app_control *control, struct ast_json **json, char **playback_url)
 Performs common setup for a bridge playback operation with both new controls and when existing controls are found.
 
static void ari_bridges_play_new (const char **args_media, size_t args_media_count, const char *args_format, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge)
 
void ast_ari_bridges_add_channel (struct ast_variable *headers, struct ast_ari_bridges_add_channel_args *args, struct ast_ari_response *response)
 Add a channel to a bridge.
 
void ast_ari_bridges_clear_video_source (struct ast_variable *headers, struct ast_ari_bridges_clear_video_source_args *args, struct ast_ari_response *response)
 Removes any explicit video source in a multi-party mixing bridge. This operation has no effect on bridges with two or fewer participants. When no explicit video source is set, talk detection will be used to determine the active video stream.
 
void ast_ari_bridges_create (struct ast_variable *headers, struct ast_ari_bridges_create_args *args, struct ast_ari_response *response)
 Create a new bridge.
 
void ast_ari_bridges_create_with_id (struct ast_variable *headers, struct ast_ari_bridges_create_with_id_args *args, struct ast_ari_response *response)
 Create a new bridge.
 
void ast_ari_bridges_destroy (struct ast_variable *headers, struct ast_ari_bridges_destroy_args *args, struct ast_ari_response *response)
 Shut down a bridge.
 
void ast_ari_bridges_get (struct ast_variable *headers, struct ast_ari_bridges_get_args *args, struct ast_ari_response *response)
 Get bridge details.
 
void ast_ari_bridges_list (struct ast_variable *headers, struct ast_ari_bridges_list_args *args, struct ast_ari_response *response)
 List all active bridges in Asterisk.
 
void ast_ari_bridges_play (struct ast_variable *headers, struct ast_ari_bridges_play_args *args, struct ast_ari_response *response)
 Start playback of media on a bridge.
 
void ast_ari_bridges_play_with_id (struct ast_variable *headers, struct ast_ari_bridges_play_with_id_args *args, struct ast_ari_response *response)
 Start playback of media on a bridge.
 
void ast_ari_bridges_record (struct ast_variable *headers, struct ast_ari_bridges_record_args *args, struct ast_ari_response *response)
 Start a recording.
 
void ast_ari_bridges_remove_channel (struct ast_variable *headers, struct ast_ari_bridges_remove_channel_args *args, struct ast_ari_response *response)
 Remove a channel from a bridge.
 
void ast_ari_bridges_set_video_source (struct ast_variable *headers, struct ast_ari_bridges_set_video_source_args *args, struct ast_ari_response *response)
 Set a channel as the video source in a multi-party mixing bridge. This operation has no effect on bridges with two or fewer participants.
 
void ast_ari_bridges_start_moh (struct ast_variable *headers, struct ast_ari_bridges_start_moh_args *args, struct ast_ari_response *response)
 Play music on hold to a bridge or change the MOH class that is playing.
 
void ast_ari_bridges_stop_moh (struct ast_variable *headers, struct ast_ari_bridges_stop_moh_args *args, struct ast_ari_response *response)
 Stop playing music on hold to a bridge.
 
static void * bridge_channel_control_thread (void *data)
 
static int bridge_set_video_source_cb (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int check_add_remove_channel (struct ast_ari_response *response, struct stasis_app_control *control, enum stasis_app_control_channel_result result)
 
static struct control_listcontrol_list_create (struct ast_ari_response *response, size_t count, const char **channels)
 
static void control_list_dtor (void *obj)
 
static struct ast_bridgefind_bridge (struct ast_ari_response *response, const char *bridge_id)
 Finds a bridge, filling the response with an error, if appropriate.
 
static struct stasis_app_controlfind_channel_control (struct ast_ari_response *response, const char *channel_id)
 Finds the control object for a channel, filling the response with an error, if appropriate.
 
static struct ast_channelprepare_bridge_media_channel (const char *type, struct ast_format *channel_format)
 

Detailed Description

Implementation for ARI stubs.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

Definition in file resource_bridges.c.

Enumeration Type Documentation

◆ play_found_result

Enumerator
PLAY_FOUND_SUCCESS 
PLAY_FOUND_FAILURE 
PLAY_FOUND_CHANNEL_UNAVAILABLE 

Definition at line 572 of file resource_bridges.c.

572 {
576};
@ PLAY_FOUND_CHANNEL_UNAVAILABLE
@ PLAY_FOUND_SUCCESS
@ PLAY_FOUND_FAILURE

Function Documentation

◆ ari_bridges_handle_play()

static void ari_bridges_handle_play ( const char *  args_bridge_id,
const char **  args_media,
size_t  args_media_count,
const char *  args_format,
const char *  args_lang,
int  args_offset_ms,
int  args_skipms,
const char *  args_playback_id,
struct ast_ari_response response 
)
static

Definition at line 637 of file resource_bridges.c.

647{
648 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args_bridge_id), ao2_cleanup);
649 struct ast_channel *play_channel;
650
651 ast_assert(response != NULL);
652
653 if (!bridge) {
654 return;
655 }
656
657 while ((play_channel = stasis_app_bridge_playback_channel_find(bridge))) {
658 /* If ari_bridges_play_found fails because the channel is unavailable for
659 * playback, The channel will be removed from the playback list soon. We
660 * can keep trying to get channels from the list until we either get one
661 * that will work or else there isn't a channel for this bridge anymore,
662 * in which case we'll revert to ari_bridges_play_new.
663 */
664 if (ari_bridges_play_found(args_media, args_media_count, args_lang,
665 args_offset_ms, args_skipms, args_playback_id, response, bridge,
666 play_channel) == PLAY_FOUND_CHANNEL_UNAVAILABLE) {
667 continue;
668 }
669 return;
670 }
671
672 ari_bridges_play_new(args_media, args_media_count, args_format, args_lang, args_offset_ms,
673 args_skipms, args_playback_id, response, bridge);
674}
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define NULL
Definition resample.c:96
static void ari_bridges_play_new(const char **args_media, size_t args_media_count, const char *args_format, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge)
static struct ast_bridge * find_bridge(struct ast_ari_response *response, const char *bridge_id)
Finds a bridge, filling the response with an error, if appropriate.
static enum play_found_result ari_bridges_play_found(const char **args_media, size_t args_media_count, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge, struct ast_channel *found_channel)
Performs common setup for a bridge playback operation with both new controls and when existing contro...
struct ast_channel * stasis_app_bridge_playback_channel_find(struct ast_bridge *bridge)
Finds an existing ARI playback channel in a bridge.
Definition res_stasis.c:792
Structure that contains information about a bridge.
Definition bridge.h:353
Main Channel structure associated with a channel.
struct ast_bridge * bridge
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981
#define ast_assert(a)
Definition utils.h:779

References ao2_cleanup, ari_bridges_play_found(), ari_bridges_play_new(), ast_assert, ast_channel::bridge, find_bridge(), NULL, PLAY_FOUND_CHANNEL_UNAVAILABLE, RAII_VAR, and stasis_app_bridge_playback_channel_find().

Referenced by ast_ari_bridges_play(), and ast_ari_bridges_play_with_id().

◆ ari_bridges_play_found()

static enum play_found_result ari_bridges_play_found ( const char **  args_media,
size_t  args_media_count,
const char *  args_lang,
int  args_offset_ms,
int  args_skipms,
const char *  args_playback_id,
struct ast_ari_response response,
struct ast_bridge bridge,
struct ast_channel found_channel 
)
static

Performs common setup for a bridge playback operation with both new controls and when existing controls are found.

Parameters
args_mediamedias to play
args_media_countnumber of media items in media
args_langlanguage string split from arguments
args_offset_msmilliseconds offset split from arguments
args_skipms
args_playback_idstring to use for playback split from arguments (null valid)
responseARI response being built
bridgeBridge the playback is being performed on
found_channelThe channel that was found controlling playback
Return values
PLAY_FOUND_SUCCESSThe operation was successful
PLAY_FOUND_FAILUREThe operation failed (terminal failure)
PLAY_FOUND_CHANNEL_UNAVAILABLEThe operation failed because the channel requested to playback with is breaking down.

Definition at line 598 of file resource_bridges.c.

607{
608 RAII_VAR(struct ast_channel *, play_channel, found_channel, ao2_cleanup);
609 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
610 RAII_VAR(char *, playback_url, NULL, ast_free);
611 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
612
613 control = stasis_app_control_find_by_channel(play_channel);
614 if (!control) {
616 }
617
618 ao2_lock(control);
619 if (stasis_app_control_is_done(control)) {
620 /* We failed to queue the action. Bailout and return that we aren't terminal. */
621 ao2_unlock(control);
623 }
624
625 if (ari_bridges_play_helper(args_media, args_media_count,
626 args_lang, args_offset_ms, args_skipms, args_playback_id,
627 response, bridge, control, &json, &playback_url)) {
628 ao2_unlock(control);
629 return PLAY_FOUND_FAILURE;
630 }
631 ao2_unlock(control);
632
633 ast_ari_response_created(response, playback_url, ast_json_ref(json));
634 return PLAY_FOUND_SUCCESS;
635}
void ast_ari_response_created(struct ast_ari_response *response, const char *url, struct ast_json *message)
Fill in a Created (201) ast_ari_response.
Definition res_ari.c:258
#define ast_free(a)
Definition astmm.h:180
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition json.c:67
static int ari_bridges_play_helper(const char **args_media, size_t args_media_count, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge, struct stasis_app_control *control, struct ast_json **json, char **playback_url)
Performs common setup for a bridge playback operation with both new controls and when existing contro...
int stasis_app_control_is_done(struct stasis_app_control *control)
Check if a control is marked as done.
struct stasis_app_control * stasis_app_control_find_by_channel(const struct ast_channel *chan)
Returns the handler for the given channel.
Definition res_stasis.c:338
Abstract JSON element (object, array, string, int, ...).

References ao2_cleanup, ao2_lock, ao2_unlock, ari_bridges_play_helper(), ast_ari_response_created(), ast_free, ast_json_ref(), ast_json_unref(), NULL, PLAY_FOUND_CHANNEL_UNAVAILABLE, PLAY_FOUND_FAILURE, PLAY_FOUND_SUCCESS, RAII_VAR, stasis_app_control_find_by_channel(), and stasis_app_control_is_done().

Referenced by ari_bridges_handle_play().

◆ ari_bridges_play_helper()

static int ari_bridges_play_helper ( const char **  args_media,
size_t  args_media_count,
const char *  args_lang,
int  args_offset_ms,
int  args_skipms,
const char *  args_playback_id,
struct ast_ari_response response,
struct ast_bridge bridge,
struct stasis_app_control control,
struct ast_json **  json,
char **  playback_url 
)
static

Performs common setup for a bridge playback operation with both new controls and when existing controls are found.

Parameters
args_mediamedias to play
args_media_countnumber of media items in media
args_langlanguage string split from arguments
args_offset_msmilliseconds offset split from arguments
args_skipms
args_playback_idstring to use for playback split from arguments (null valid)
responseARI response being built
bridgeBridge the playback is being performed on
controlControl being used for the playback channel
jsoncontents of the response to ARI
playback_urlstores playback URL for use with response
Return values
-1operation failed
Returns
operation was successful

Definition at line 363 of file resource_bridges.c.

374{
375 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
376 RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
377
378 const char *language;
379
380 snapshot = stasis_app_control_get_snapshot(control);
381 if (!snapshot) {
383 response, 500, "Internal Error", "Failed to get control snapshot");
384 return -1;
385 }
386
387 language = S_OR(args_lang, snapshot->base->language);
388
389 playback = stasis_app_control_play_uri(control, args_media, args_media_count,
390 language, bridge->uniqueid, STASIS_PLAYBACK_TARGET_BRIDGE, args_skipms,
391 args_offset_ms, args_playback_id);
392
393 if (!playback) {
395 return -1;
396 }
397
398 if (ast_asprintf(playback_url, "/playbacks/%s",
399 stasis_app_playback_get_id(playback)) == -1) {
401 return -1;
402 }
403
404 *json = stasis_app_playback_to_json(playback);
405 if (!*json) {
407 return -1;
408 }
409
410 return 0;
411}
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition res_ari.c:212
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition res_ari.c:251
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition astmm.h:267
static char language[MAX_LANGUAGE]
Definition chan_iax2.c:361
struct ast_channel_snapshot * stasis_app_control_get_snapshot(const struct stasis_app_control *control)
Returns the most recent snapshot for the associated channel.
Definition control.c:901
@ STASIS_PLAYBACK_TARGET_BRIDGE
struct stasis_app_playback * stasis_app_control_play_uri(struct stasis_app_control *control, const char **media, size_t media_count, const char *language, const char *target_id, enum stasis_app_playback_target_type target_type, int skipms, long offsetms, const char *id)
Play a file to the control's channel.
struct ast_json * stasis_app_playback_to_json(const struct stasis_app_playback *playback)
Convert a playback to its JSON representation.
const char * stasis_app_playback_get_id(struct stasis_app_playback *playback)
Gets the unique id of a playback object.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
const ast_string_field uniqueid
Definition bridge.h:405
Structure representing a snapshot of channel state.

References ao2_cleanup, ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_asprintf, ast_channel_snapshot::base, ast_channel::bridge, language, ast_channel_snapshot_base::language, NULL, RAII_VAR, S_OR, ast_channel::snapshot, stasis_app_control_get_snapshot(), stasis_app_control_play_uri(), stasis_app_playback_get_id(), stasis_app_playback_to_json(), STASIS_PLAYBACK_TARGET_BRIDGE, and ast_bridge::uniqueid.

Referenced by ari_bridges_play_found(), and ari_bridges_play_new().

◆ ari_bridges_play_new()

static void ari_bridges_play_new ( const char **  args_media,
size_t  args_media_count,
const char *  args_format,
const char *  args_lang,
int  args_offset_ms,
int  args_skipms,
const char *  args_playback_id,
struct ast_ari_response response,
struct ast_bridge bridge 
)
static

Definition at line 413 of file resource_bridges.c.

422{
423 RAII_VAR(struct ast_channel *, play_channel, NULL, ast_hangup);
424 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
425 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
426 RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);
427 RAII_VAR(char *, playback_url, NULL, ast_free);
428
429 struct stasis_topic *channel_topic;
430 struct stasis_topic *bridge_topic;
431 struct bridge_channel_control_thread_data *thread_data;
432 pthread_t threadid;
433 struct ast_format *channel_format = NULL;
434
435 struct ast_frame prog = {
437 .subclass.integer = AST_CONTROL_PROGRESS,
438 };
439
440 /*
441 * Determine the format for the playback channel.
442 * If a format was specified, use that if it's valid.
443 * Otherwise, if the bridge is empty, use slin.
444 * If the bridge has one channel, use that channel's raw write format.
445 * If the bridge has multiple channels, use the slin format that
446 * will handle the highest sample rate of the raw write format of all the channels.
447 */
448 if (!ast_strlen_zero(args_format)) {
449 channel_format = ast_format_cache_get(args_format);
450 if (!channel_format) {
452 response, 422, "Unprocessable Entity",
453 "specified announcer_format is unknown on this system");
454 return;
455 }
456 } else {
457 ast_bridge_lock(bridge);
458 if (bridge->num_channels == 0) {
459 channel_format = ao2_bump(ast_format_slin);
460 } else if (bridge->num_channels == 1) {
461 struct ast_bridge_channel *bc = NULL;
463 if (bc) {
464 channel_format = ast_channel_rawwriteformat(bc->chan);
465 if (channel_format) {
466 channel_format = ao2_bump(channel_format);
467 }
468 }
469 } else {
470 struct ast_bridge_channel *bc = NULL;
471 unsigned int max_sample_rate = 0;
473 struct ast_format *fmt = ast_channel_rawwriteformat(bc->chan);
474 max_sample_rate = MAX(ast_format_get_sample_rate(fmt), max_sample_rate);
475 }
476 channel_format = ao2_bump(ast_format_cache_get_slin_by_rate(max_sample_rate));
477 }
478 ast_bridge_unlock(bridge);
479 }
480
481 if (!channel_format) {
482 channel_format = ao2_bump(ast_format_slin);
483 }
484
485 play_channel = prepare_bridge_media_channel("Announcer", channel_format);
486 ao2_cleanup(channel_format);
487
488 if (!play_channel) {
490 response, 500, "Internal Error", "Could not create playback channel");
491 return;
492 }
493 ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel));
494
495 bridge_topic = ast_bridge_topic(bridge);
496 channel_topic = ast_channel_topic(play_channel);
497
498 /* Forward messages from the playback channel topic to the bridge topic so that anything listening for
499 * messages on the bridge topic will receive the playback start/stop messages. Other messages that would
500 * go to this channel will be suppressed since the channel is marked as internal.
501 */
502 if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
504 response, 500, "Internal Error", "Could not forward playback channel stasis messages to bridge topic");
505 return;
506 }
507
508 if (ast_unreal_channel_push_to_bridge(play_channel, bridge,
511 response, 500, "Internal Error", "Failed to put playback channel into the bridge");
512 return;
513 }
514
515 control = stasis_app_control_create(play_channel);
516 if (control == NULL) {
518 return;
519 }
520
521 ao2_lock(control);
522 if (ari_bridges_play_helper(args_media, args_media_count, args_lang,
523 args_offset_ms, args_skipms, args_playback_id, response, bridge,
524 control, &json, &playback_url)) {
525 ao2_unlock(control);
526 return;
527 }
528 ao2_unlock(control);
529
530 if (stasis_app_bridge_playback_channel_add(bridge, play_channel, control)) {
532 return;
533 }
534
535 ast_bridge_queue_everyone_else(bridge, NULL, &prog);
536
537 /* Give play_channel and control reference to the thread data */
538 thread_data = ast_calloc(1, sizeof(*thread_data));
539 if (!thread_data) {
540 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
542 return;
543 }
544
545 thread_data->bridge_channel = play_channel;
546 thread_data->control = control;
547 thread_data->forward = channel_forward;
548 thread_data->bridge_id = ast_strdup(bridge->uniqueid);
549 if (!thread_data->bridge_id) {
550 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
552 ast_free(thread_data);
553 return;
554 }
555
556 if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
557 stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
558 ast_free(thread_data->bridge_id);
560 ast_free(thread_data);
561 return;
562 }
563
564 /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
565 play_channel = NULL;
566 control = NULL;
567 channel_forward = NULL;
568
569 ast_ari_response_created(response, playback_url, ast_json_ref(json));
570}
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition bridge.h:485
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition bridge.h:474
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Queue the given frame to everyone else.
@ AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE
@ AST_BRIDGE_CHANNEL_FLAG_LONELY
const char * ast_channel_name(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2574
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
struct ast_format * ast_channel_rawwriteformat(struct ast_channel *chan)
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
Push the semi2 unreal channel into a bridge from either member of the unreal pair.
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition format.c:379
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
#define bc
@ AST_FRAME_CONTROL
@ AST_CONTROL_PROGRESS
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
static void * bridge_channel_control_thread(void *data)
static struct ast_channel * prepare_bridge_media_channel(const char *type, struct ast_format *channel_format)
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition stasis.c:1615
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition stasis.c:1645
void stasis_app_bridge_playback_channel_remove(char *bridge_id, struct stasis_app_control *control)
remove channel from list of ARI playback channels for bridges.
Definition res_stasis.c:776
int stasis_app_bridge_playback_channel_add(struct ast_bridge *bridge, struct ast_channel *chan, struct stasis_app_control *control)
Adds a channel to the list of ARI playback channels for bridges.
Definition res_stasis.c:738
struct stasis_app_control * stasis_app_control_create(struct ast_channel *chan)
Creates a control handler for a channel that isn't in a stasis app.
Definition res_stasis.c:333
struct stasis_topic * ast_bridge_topic(struct ast_bridge *bridge)
A topic which publishes the events for a particular bridge.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Structure that contains information regarding a channel in a bridge.
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_bridge_channel::@200 entry
struct ast_bridge_channels_list channels
Definition bridge.h:367
unsigned int num_channels
Definition bridge.h:377
Definition of a media format.
Definition format.c:43
Data structure associated with a single frame of data.
enum ast_frame_type frametype
struct stasis_app_control * control
Forwarding information.
Definition stasis.c:1598
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628
#define MAX(a, b)
Definition utils.h:254

References ao2_bump, ao2_cleanup, ao2_lock, ao2_unlock, ari_bridges_play_helper(), ast_ari_response_alloc_failed(), ast_ari_response_created(), ast_ari_response_error(), AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, AST_BRIDGE_CHANNEL_FLAG_LONELY, ast_bridge_lock, ast_bridge_queue_everyone_else(), ast_bridge_topic(), ast_bridge_unlock, ast_calloc, ast_channel_name(), ast_channel_rawwriteformat(), ast_channel_topic(), AST_CONTROL_PROGRESS, ast_debug, ast_format_cache_get, ast_format_cache_get_slin_by_rate(), ast_format_get_sample_rate(), ast_format_slin, AST_FRAME_CONTROL, ast_free, ast_hangup(), ast_json_ref(), ast_json_unref(), AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_pthread_create_detached, ast_strdup, ast_strlen_zero(), ast_unreal_channel_push_to_bridge(), bc, ast_bridge_channel::bridge, bridge_channel_control_thread_data::bridge_channel, bridge_channel_control_thread(), bridge_channel_control_thread_data::bridge_id, ast_channel::channel_forward, ast_bridge::channels, bridge_channel_control_thread_data::control, ast_bridge_channel::entry, bridge_channel_control_thread_data::forward, ast_frame::frametype, MAX, NULL, ast_bridge::num_channels, prepare_bridge_media_channel(), RAII_VAR, stasis_app_bridge_playback_channel_add(), stasis_app_bridge_playback_channel_remove(), stasis_app_control_create(), stasis_forward_all(), stasis_forward_cancel(), and ast_bridge::uniqueid.

Referenced by ari_bridges_handle_play().

◆ ast_ari_bridges_add_channel()

void ast_ari_bridges_add_channel ( struct ast_variable headers,
struct ast_ari_bridges_add_channel_args args,
struct ast_ari_response response 
)

Add a channel to a bridge.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 191 of file resource_bridges.c.

194{
195 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
196 RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
197 size_t i;
198 int has_error = 0;
199
200 if (!bridge) {
201 /* Response filled in by find_bridge() */
202 return;
203 }
204
205 list = control_list_create(response, args->channel_count, args->channel);
206 if (!list) {
207 /* Response filled in by control_list_create() */
208 return;
209 }
210
211 for (i = 0; i < list->count; ++i) {
212 stasis_app_control_clear_roles(list->controls[i]);
213 if (!ast_strlen_zero(args->role)) {
214 if (stasis_app_control_add_role(list->controls[i], args->role)) {
216 return;
217 }
218 }
219
220 /* Apply bridge features to each of the channel controls */
221 if (!stasis_app_control_bridge_features_init(list->controls[i])) {
222 stasis_app_control_absorb_dtmf_in_bridge(list->controls[i], args->absorb_dtmf);
223 stasis_app_control_mute_in_bridge(list->controls[i], args->mute);
224 stasis_app_control_inhibit_colp_in_bridge(list->controls[i], args->inhibit_connected_line_updates);
225 }
226 }
227
228 for (i = 0; i < list->count; ++i) {
229 if ((has_error = check_add_remove_channel(response, list->controls[i],
231 list->controls[i], bridge)))) {
232 break;
233 }
234 }
235
236 if (!has_error) {
238 }
239}
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
Definition res_ari.c:237
static struct @522 args
static struct control_list * control_list_create(struct ast_ari_response *response, size_t count, const char **channels)
static int check_add_remove_channel(struct ast_ari_response *response, struct stasis_app_control *control, enum stasis_app_control_channel_result result)
void stasis_app_control_mute_in_bridge(struct stasis_app_control *control, int mute)
Set whether audio from the channel is muted instead of passing through to the bridge.
Definition control.c:1522
int stasis_app_control_add_channel_to_bridge(struct stasis_app_control *control, struct ast_bridge *bridge)
Add a channel to the bridge.
Definition control.c:1435
void stasis_app_control_clear_roles(struct stasis_app_control *control)
Clear bridge roles currently applied to a channel controlled by a stasis app control.
Definition control.c:353
void stasis_app_control_absorb_dtmf_in_bridge(struct stasis_app_control *control, int absorb)
Set whether DTMF from the channel is absorbed instead of passing through to the bridge.
Definition control.c:1516
int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
Apply a bridge role to a channel controlled by a stasis app control.
Definition control.c:331
void stasis_app_control_inhibit_colp_in_bridge(struct stasis_app_control *control, int inhibit_colp)
Set whether COLP frames should be generated when joining the bridge.
Definition control.c:1528
int stasis_app_control_bridge_features_init(struct stasis_app_control *control)
Initialize bridge features into a channel control.
Definition control.c:1503

References ao2_cleanup, args, ast_ari_response_alloc_failed(), ast_ari_response_no_content(), ast_strlen_zero(), check_add_remove_channel(), control_list_create(), find_bridge(), NULL, RAII_VAR, stasis_app_control_absorb_dtmf_in_bridge(), stasis_app_control_add_channel_to_bridge(), stasis_app_control_add_role(), stasis_app_control_bridge_features_init(), stasis_app_control_clear_roles(), stasis_app_control_inhibit_colp_in_bridge(), and stasis_app_control_mute_in_bridge().

Referenced by ast_ari_bridges_add_channel_cb().

◆ ast_ari_bridges_clear_video_source()

void ast_ari_bridges_clear_video_source ( struct ast_variable headers,
struct ast_ari_bridges_clear_video_source_args args,
struct ast_ari_response response 
)

Removes any explicit video source in a multi-party mixing bridge. This operation has no effect on bridges with two or fewer participants. When no explicit video source is set, talk detection will be used to determine the active video stream.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1147 of file resource_bridges.c.

1149{
1150 struct ast_bridge *bridge;
1151
1152 bridge = find_bridge(response, args->bridge_id);
1153 if (!bridge) {
1154 return;
1155 }
1156
1157 ast_bridge_lock(bridge);
1159 ast_bridge_unlock(bridge);
1160
1161 ao2_ref(bridge, -1);
1163}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
void ast_bridge_set_talker_src_video_mode(struct ast_bridge *bridge)
Set the bridge to pick the strongest talker supporting video as the single source video feed.
Definition bridge.c:3845

References ao2_ref, args, ast_ari_response_no_content(), ast_bridge_lock, ast_bridge_set_talker_src_video_mode(), ast_bridge_unlock, and find_bridge().

Referenced by ast_ari_bridges_clear_video_source_cb().

◆ ast_ari_bridges_create()

void ast_ari_bridges_create ( struct ast_variable headers,
struct ast_ari_bridges_create_args args,
struct ast_ari_response response 
)

Create a new bridge.

This bridge persists until it has been shut down, or Asterisk has been shut down.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1026 of file resource_bridges.c.

1029{
1030 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1031 RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
1032
1033 if (ast_bridge_topic_exists(args->bridge_id)) {
1035 response, 409, "Conflict",
1036 "Bridge with id '%s' already exists", args->bridge_id);
1037 return;
1038 }
1039
1040 bridge = stasis_app_bridge_create(args->type, args->name, args->bridge_id);
1041 if (!bridge) {
1043 response, 500, "Internal Error",
1044 "Unable to create bridge. Possible duplicate bridge id '%s'", args->bridge_id);
1045 return;
1046 }
1047
1048 ast_bridge_lock(bridge);
1049 snapshot = ast_bridge_snapshot_create(bridge);
1050 ast_bridge_unlock(bridge);
1051
1052 if (!snapshot) {
1054 response, 500, "Internal Error",
1055 "Unable to create snapshot for new bridge");
1056 return;
1057 }
1058
1059 ast_ari_response_ok(response,
1061}
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition res_ari.c:229
struct stasis_message_sanitizer * stasis_app_get_sanitizer(void)
Get the Stasis message sanitizer for app_stasis applications.
struct ast_bridge * stasis_app_bridge_create(const char *type, const char *name, const char *id)
Create a bridge of the specified type.
Definition res_stasis.c:898
int ast_bridge_topic_exists(const char *uniqueid)
Check if a stasis topic exists for a bridge uniqueid.
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 ast_bridge_snapshot * ast_bridge_snapshot_create(struct ast_bridge *bridge)
Generate a snapshot of the bridge state. This is an ao2 object, so ao2_cleanup() to deallocate.
Structure that contains a snapshot of information about a bridge.
Definition bridge.h:318

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_ok(), ast_bridge_lock, ast_bridge_snapshot_create(), ast_bridge_snapshot_to_json(), ast_bridge_topic_exists(), ast_bridge_unlock, NULL, RAII_VAR, stasis_app_bridge_create(), and stasis_app_get_sanitizer().

Referenced by ast_ari_bridges_create_cb().

◆ ast_ari_bridges_create_with_id()

void ast_ari_bridges_create_with_id ( struct ast_variable headers,
struct ast_ari_bridges_create_with_id_args args,
struct ast_ari_response response 
)

Create a new bridge.

This bridge persists until it has been shut down, or Asterisk has been shut down.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1063 of file resource_bridges.c.

1066{
1067 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1068 RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
1069
1070 if (ast_bridge_topic_exists(args->bridge_id)) {
1072 response, 409, "Conflict",
1073 "Bridge with id '%s' already exists", args->bridge_id);
1074 return;
1075 }
1076
1077 bridge = stasis_app_bridge_create(args->type, args->name, args->bridge_id);
1078 if (!bridge) {
1080 response, 500, "Internal Error",
1081 "Unable to create bridge");
1082 return;
1083 }
1084
1085 ast_bridge_lock(bridge);
1086 snapshot = ast_bridge_snapshot_create(bridge);
1087 ast_bridge_unlock(bridge);
1088
1089 if (!snapshot) {
1091 response, 500, "Internal Error",
1092 "Unable to create snapshot for new bridge");
1093 return;
1094 }
1095
1096 ast_ari_response_ok(response,
1098}

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_ok(), ast_bridge_lock, ast_bridge_snapshot_create(), ast_bridge_snapshot_to_json(), ast_bridge_topic_exists(), ast_bridge_unlock, NULL, RAII_VAR, stasis_app_bridge_create(), and stasis_app_get_sanitizer().

Referenced by ast_ari_bridges_create_with_id_cb().

◆ ast_ari_bridges_destroy()

void ast_ari_bridges_destroy ( struct ast_variable headers,
struct ast_ari_bridges_destroy_args args,
struct ast_ari_response response 
)

Shut down a bridge.

If any channels are in this bridge, they will be removed and resume whatever they were doing beforehand.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 962 of file resource_bridges.c.

965{
966 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
967 if (!bridge) {
968 return;
969 }
970
973}
void stasis_app_bridge_destroy(const char *bridge_id)
Destroy the bridge.
Definition res_stasis.c:908

References ao2_cleanup, args, ast_ari_response_no_content(), ast_channel::bridge, find_bridge(), RAII_VAR, and stasis_app_bridge_destroy().

Referenced by ast_ari_bridges_destroy_cb().

◆ ast_ari_bridges_get()

void ast_ari_bridges_get ( struct ast_variable headers,
struct ast_ari_bridges_get_args args,
struct ast_ari_response response 
)

Get bridge details.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 946 of file resource_bridges.c.

949{
951 if (!snapshot) {
953 response, 404, "Not Found",
954 "Bridge not found");
955 return;
956 }
957
958 ast_ari_response_ok(response,
960}
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *bridge_id)
Returns the current snapshot for the bridge.

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_ok(), ast_bridge_get_snapshot_by_uniqueid(), ast_bridge_snapshot_to_json(), RAII_VAR, ast_channel::snapshot, and stasis_app_get_sanitizer().

Referenced by ast_ari_bridges_get_cb().

◆ ast_ari_bridges_list()

void ast_ari_bridges_list ( struct ast_variable headers,
struct ast_ari_bridges_list_args args,
struct ast_ari_response response 
)

List all active bridges in Asterisk.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 975 of file resource_bridges.c.

978{
980 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
981 struct ao2_iterator i;
982 struct ast_bridge *bridge;
983
985 if (!bridges) {
987 return;
988 }
989
990 json = ast_json_array_create();
991 if (!json) {
993 return;
994 }
995
997 while ((bridge = ao2_iterator_next(&i))) {
998 struct ast_bridge_snapshot *snapshot;
999 struct ast_json *json_bridge = NULL;
1000
1001 /* Invisible bridges don't get shown externally and have no snapshot */
1003 ao2_ref(bridge, -1);
1004 continue;
1005 }
1006
1007 snapshot = ast_bridge_get_snapshot(bridge);
1008 if (snapshot) {
1009 json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
1010 ao2_ref(snapshot, -1);
1011 }
1012
1013 ao2_ref(bridge, -1);
1014
1015 if (!json_bridge || ast_json_array_append(json, json_bridge)) {
1018 return;
1019 }
1020 }
1022
1023 ast_ari_response_ok(response, ast_json_ref(json));
1024}
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static struct ao2_container * bridges
Definition bridge.c:132
struct ao2_container * ast_bridges(void)
Returns the global bridges container.
Definition bridge.c:185
@ AST_BRIDGE_FLAG_INVISIBLE
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition json.c:378
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition json.c:362
struct ast_bridge_snapshot * ast_bridge_get_snapshot(struct ast_bridge *bridge)
Returns the current snapshot for the bridge.
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821
struct ast_flags feature_flags
Definition bridge.h:373
#define ast_test_flag(p, flag)
Definition utils.h:64

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_ari_response_alloc_failed(), ast_ari_response_ok(), AST_BRIDGE_FLAG_INVISIBLE, ast_bridge_get_snapshot(), ast_bridge_snapshot_to_json(), ast_bridges(), ast_json_array_append(), ast_json_array_create(), ast_json_ref(), ast_json_unref(), ast_test_flag, bridges, ast_bridge::feature_flags, NULL, RAII_VAR, and stasis_app_get_sanitizer().

Referenced by ast_ari_bridges_list_cb().

◆ ast_ari_bridges_play()

void ast_ari_bridges_play ( struct ast_variable headers,
struct ast_ari_bridges_play_args args,
struct ast_ari_response response 
)

Start playback of media on a bridge.

The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 677 of file resource_bridges.c.

680{
681 ari_bridges_handle_play(args->bridge_id,
682 args->media,
683 args->media_count,
684 args->announcer_format,
685 args->lang,
686 args->offsetms,
687 args->skipms,
688 args->playback_id,
689 response);
690}
static void ari_bridges_handle_play(const char *args_bridge_id, const char **args_media, size_t args_media_count, const char *args_format, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response)

References args, and ari_bridges_handle_play().

Referenced by ast_ari_bridges_play_cb().

◆ ast_ari_bridges_play_with_id()

void ast_ari_bridges_play_with_id ( struct ast_variable headers,
struct ast_ari_bridges_play_with_id_args args,
struct ast_ari_response response 
)

Start playback of media on a bridge.

The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 692 of file resource_bridges.c.

695{
696 ari_bridges_handle_play(args->bridge_id,
697 args->media,
698 args->media_count,
699 args->announcer_format,
700 args->lang,
701 args->offsetms,
702 args->skipms,
703 args->playback_id,
704 response);
705}

References args, and ari_bridges_handle_play().

Referenced by ast_ari_bridges_play_with_id_cb().

◆ ast_ari_bridges_record()

void ast_ari_bridges_record ( struct ast_variable headers,
struct ast_ari_bridges_record_args args,
struct ast_ari_response response 
)

Start a recording.

This records the mixed audio from all channels participating in this bridge.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 707 of file resource_bridges.c.

710{
711 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
712 RAII_VAR(struct ast_channel *, record_channel, NULL, ast_hangup);
713 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
714 RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
715 RAII_VAR(char *, recording_url, NULL, ast_free);
716 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
718 RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
719 RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);
720
721 struct stasis_topic *channel_topic;
722 struct stasis_topic *bridge_topic;
723 size_t uri_name_maxlen;
724 struct bridge_channel_control_thread_data *thread_data;
725 pthread_t threadid;
726 struct ast_format *file_format = NULL;
727 struct ast_format *channel_format = NULL;
728
729 ast_assert(response != NULL);
730
731 if (bridge == NULL) {
732 return;
733 }
734
736 if (!file_format) {
738 response, 422, "Unprocessable Entity",
739 "specified format is unknown on this system");
740 return;
741 }
742
743 if (!ast_strlen_zero(args->recorder_format)) {
744 channel_format = ast_format_cache_get(args->recorder_format);
745 if (!channel_format) {
747 response, 422, "Unprocessable Entity",
748 "specified recorder_format is unknown on this system");
749 return;
750 }
751 } else {
752 channel_format = ao2_bump(file_format);
753 }
754
755 if (!(record_channel = prepare_bridge_media_channel("Recorder", channel_format))) {
757 response, 500, "Internal Server Error", "Failed to create recording channel");
758 return;
759 }
760
761 ao2_cleanup(channel_format);
762
763 bridge_topic = ast_bridge_topic(bridge);
764 channel_topic = ast_channel_topic(record_channel);
765
766 /* Forward messages from the recording channel topic to the bridge topic so that anything listening for
767 * messages on the bridge topic will receive the recording start/stop messages. Other messages that would
768 * go to this channel will be suppressed since the channel is marked as internal.
769 */
770 if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
772 response, 500, "Internal Error", "Could not forward record channel stasis messages to bridge topic");
773 return;
774 }
775
776 if (ast_unreal_channel_push_to_bridge(record_channel, bridge,
779 response, 500, "Internal Error", "Failed to put recording channel into the bridge");
780 return;
781 }
782
783 control = stasis_app_control_create(record_channel);
784 if (control == NULL) {
786 return;
787 }
788
790 if (options == NULL) {
792 return;
793 }
794
795 ast_string_field_build(options, target, "bridge:%s", args->bridge_id);
796 options->max_silence_seconds = args->max_silence_seconds;
797 options->max_duration_seconds = args->max_duration_seconds;
798 options->terminate_on =
800 options->if_exists =
802 options->beep = args->beep;
803
804 if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
806 response, 400, "Bad Request",
807 "terminateOn invalid");
808 return;
809 }
810
811 if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
813 response, 400, "Bad Request",
814 "ifExists invalid");
815 return;
816 }
817
818 recording = stasis_app_control_record(control, options);
819 if (recording == NULL) {
820 switch(errno) {
821 case EINVAL:
822 /* While the arguments are invalid, we should have
823 * caught them prior to calling record.
824 */
826 response, 500, "Internal Server Error",
827 "Error parsing request");
828 break;
829 case EEXIST:
830 ast_ari_response_error(response, 409, "Conflict",
831 "Recording '%s' already exists and can not be overwritten",
832 args->name);
833 break;
834 case ENOMEM:
836 break;
837 case EPERM:
839 response, 400, "Bad Request",
840 "Recording name invalid");
841 break;
842 default:
844 "Unrecognized recording error: %s\n",
845 strerror(errno));
847 response, 500, "Internal Server Error",
848 "Internal Server Error");
849 break;
850 }
851 return;
852 }
853
854 uri_name_maxlen = strlen(args->name) * 3;
855 uri_encoded_name = ast_malloc(uri_name_maxlen);
856 if (!uri_encoded_name) {
858 return;
859 }
860 ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen, ast_uri_http);
861
862 if (ast_asprintf(&recording_url, "/recordings/live/%s",
863 uri_encoded_name) == -1) {
864 recording_url = NULL;
866 return;
867 }
868
869 json = stasis_app_recording_to_json(recording);
870 if (!json) {
872 return;
873 }
874
875 thread_data = ast_calloc(1, sizeof(*thread_data));
876 if (!thread_data) {
878 return;
879 }
880
881 thread_data->bridge_channel = record_channel;
882 thread_data->control = control;
883 thread_data->forward = channel_forward;
884
885 if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
887 ast_free(thread_data);
888 return;
889 }
890
891 /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
892 record_channel = NULL;
893 control = NULL;
894 channel_forward = NULL;
895
896 ast_ari_response_created(response, recording_url, ast_json_ref(json));
897}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
#define ast_log
Definition astobj2.c:42
struct ast_format * ast_get_format_for_file_ext(const char *file_ext)
Get the ast_format associated with the given file extension.
Definition file.c:2040
file_format
Definition func_env.c:440
@ AST_RECORD_IF_EXISTS_ERROR
#define LOG_WARNING
int errno
struct stasis_app_recording_options * stasis_app_recording_options_create(const char *name, const char *format)
Allocate a recording options object.
struct ast_json * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
struct stasis_app_recording * stasis_app_control_record(struct stasis_app_control *control, struct stasis_app_recording_options *options)
Record media from a channel.
enum ast_record_if_exists stasis_app_recording_if_exists_parse(const char *str)
Parse a string into the if_exists enum.
#define STASIS_APP_RECORDING_TERMINATE_INVALID
char stasis_app_recording_termination_parse(const char *str)
Parse a string into the recording termination enum.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
static struct test_options options
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition utils.c:721
const struct ast_flags ast_uri_http
Definition utils.c:717

References ao2_bump, ao2_cleanup, args, ast_ari_response_alloc_failed(), ast_ari_response_created(), ast_ari_response_error(), ast_asprintf, ast_assert, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, AST_BRIDGE_CHANNEL_FLAG_LONELY, ast_bridge_topic(), ast_calloc, ast_channel_topic(), ast_format_cache_get, ast_free, ast_get_format_for_file_ext(), ast_hangup(), ast_json_ref(), ast_json_unref(), ast_log, ast_malloc, ast_pthread_create_detached, AST_RECORD_IF_EXISTS_ERROR, ast_string_field_build, ast_strlen_zero(), ast_unreal_channel_push_to_bridge(), ast_uri_encode(), ast_uri_http, ast_channel::bridge, bridge_channel_control_thread_data::bridge_channel, bridge_channel_control_thread(), ast_channel::channel_forward, bridge_channel_control_thread_data::control, errno, find_bridge(), bridge_channel_control_thread_data::forward, LOG_WARNING, NULL, options, prepare_bridge_media_channel(), RAII_VAR, stasis_app_control_create(), stasis_app_control_record(), stasis_app_recording_if_exists_parse(), stasis_app_recording_options_create(), STASIS_APP_RECORDING_TERMINATE_INVALID, stasis_app_recording_termination_parse(), stasis_app_recording_to_json(), stasis_forward_all(), and stasis_forward_cancel().

Referenced by ast_ari_bridges_record_cb().

◆ ast_ari_bridges_remove_channel()

void ast_ari_bridges_remove_channel ( struct ast_variable headers,
struct ast_ari_bridges_remove_channel_args args,
struct ast_ari_response response 
)

Remove a channel from a bridge.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 241 of file resource_bridges.c.

244{
245 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
246 RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
247 size_t i;
248
249 if (!bridge) {
250 /* Response filled in by find_bridge() */
251 return;
252 }
253
254 list = control_list_create(response, args->channel_count, args->channel);
255 if (!list) {
256 /* Response filled in by control_list_create() */
257 return;
258 }
259
260 /* Make sure all of the channels are in this bridge */
261 for (i = 0; i < list->count; ++i) {
262 if (stasis_app_get_bridge(list->controls[i]) != bridge) {
263 ast_log(LOG_WARNING, "Channel %s not in bridge %s\n",
264 args->channel[i], args->bridge_id);
265 ast_ari_response_error(response, 422,
266 "Unprocessable Entity",
267 "Channel not in this bridge");
268 return;
269 }
270 }
271
272 /* Now actually remove it */
273 for (i = 0; i < list->count; ++i) {
275 bridge);
276 }
277
279}
int stasis_app_control_remove_channel_from_bridge(struct stasis_app_control *control, struct ast_bridge *bridge)
Remove a channel from the bridge.
Definition control.c:1472
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition control.c:972

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_log, control_list_create(), find_bridge(), LOG_WARNING, NULL, RAII_VAR, stasis_app_control_remove_channel_from_bridge(), and stasis_app_get_bridge().

Referenced by ast_ari_bridges_remove_channel_cb().

◆ ast_ari_bridges_set_video_source()

void ast_ari_bridges_set_video_source ( struct ast_variable headers,
struct ast_ari_bridges_set_video_source_args args,
struct ast_ari_response response 
)

Set a channel as the video source in a multi-party mixing bridge. This operation has no effect on bridges with two or fewer participants.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 1112 of file resource_bridges.c.

1114{
1115 struct ast_bridge *bridge;
1116 struct stasis_app_control *control;
1117
1118 bridge = find_bridge(response, args->bridge_id);
1119 if (!bridge) {
1120 return;
1121 }
1122
1123 control = find_channel_control(response, args->channel_id);
1124 if (!control) {
1125 ao2_ref(bridge, -1);
1126 return;
1127 }
1128
1129 if (stasis_app_get_bridge(control) != bridge) {
1130 ast_ari_response_error(response, 422,
1131 "Unprocessable Entity",
1132 "Channel not in this bridge");
1133 ao2_ref(bridge, -1);
1134 ao2_ref(control, -1);
1135 return;
1136 }
1137
1140
1141 ao2_ref(bridge, -1);
1142 ao2_ref(control, -1);
1143
1145}
void __ao2_cleanup(void *obj)
Definition astobj2.c:677
static struct stasis_app_control * find_channel_control(struct ast_ari_response *response, const char *channel_id)
Finds the control object for a channel, filling the response with an error, if appropriate.
static int bridge_set_video_source_cb(struct stasis_app_control *control, struct ast_channel *chan, void *data)
int stasis_app_send_command(struct stasis_app_control *control, stasis_app_command_cb command, void *data, command_data_destructor_fn data_destructor)
Invokes a command on a control's channel.
Definition control.c:939
struct ast_bridge * bridge
Definition control.c:67

References __ao2_cleanup(), ao2_bump, ao2_ref, args, ast_ari_response_error(), ast_ari_response_no_content(), stasis_app_control::bridge, bridge_set_video_source_cb(), find_bridge(), find_channel_control(), stasis_app_get_bridge(), and stasis_app_send_command().

Referenced by ast_ari_bridges_set_video_source_cb().

◆ ast_ari_bridges_start_moh()

void ast_ari_bridges_start_moh ( struct ast_variable headers,
struct ast_ari_bridges_start_moh_args args,
struct ast_ari_response response 
)

Play music on hold to a bridge or change the MOH class that is playing.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 899 of file resource_bridges.c.

902{
903 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
904 struct ast_channel *moh_channel;
905 const char *moh_class = args->moh_class;
906
907 if (!bridge) {
908 /* The response is provided by find_bridge() */
909 return;
910 }
911
913 if (!moh_channel) {
915 return;
916 }
917
918 ast_moh_start(moh_channel, moh_class, NULL);
919 ast_channel_cleanup(moh_channel);
920
922
923}
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition channel.h:3036
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition channel.c:7840
struct ast_channel * stasis_app_bridge_moh_channel(struct ast_bridge *bridge)
Finds or creates an announcer channel in a bridge that can play music on hold.
Definition res_stasis.c:655

References ao2_cleanup, args, ast_ari_response_alloc_failed(), ast_ari_response_no_content(), ast_channel_cleanup, ast_moh_start(), ast_channel::bridge, find_bridge(), NULL, RAII_VAR, and stasis_app_bridge_moh_channel().

Referenced by ast_ari_bridges_start_moh_cb().

◆ ast_ari_bridges_stop_moh()

void ast_ari_bridges_stop_moh ( struct ast_variable headers,
struct ast_ari_bridges_stop_moh_args args,
struct ast_ari_response response 
)

Stop playing music on hold to a bridge.

This will only stop music on hold being played via POST bridges/{bridgeId}/moh.

Parameters
headersHTTP headers
argsSwagger parameters
[out]responseHTTP response

Definition at line 925 of file resource_bridges.c.

928{
929 RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
930
931 if (!bridge) {
932 /* the response is provided by find_bridge() */
933 return;
934 }
935
936 if (stasis_app_bridge_moh_stop(bridge)) {
938 response, 409, "Conflict",
939 "Bridge isn't playing music");
940 return;
941 }
942
944}
int stasis_app_bridge_moh_stop(struct ast_bridge *bridge)
Breaks down MOH channels playing on the bridge created by stasis_app_bridge_moh_channel.
Definition res_stasis.c:675

References ao2_cleanup, args, ast_ari_response_error(), ast_ari_response_no_content(), ast_channel::bridge, find_bridge(), RAII_VAR, and stasis_app_bridge_moh_stop().

Referenced by ast_ari_bridges_stop_moh_cb().

◆ bridge_channel_control_thread()

static void * bridge_channel_control_thread ( void *  data)
static

Definition at line 288 of file resource_bridges.c.

289{
290 struct bridge_channel_control_thread_data *thread_data = data;
291 struct ast_channel *bridge_channel = thread_data->bridge_channel;
292 struct stasis_app_control *control = thread_data->control;
293 struct stasis_forward *forward = thread_data->forward;
294 ast_callid callid = ast_channel_callid(bridge_channel);
295 char *bridge_id = thread_data->bridge_id;
296
297 if (callid) {
299 }
300
301 ast_free(thread_data);
302 thread_data = NULL;
303
304 stasis_app_control_execute_until_exhausted(bridge_channel, control);
306
307 if (bridge_id) {
309 ast_free(bridge_id);
310 }
311 stasis_forward_cancel(forward);
312 ao2_cleanup(control);
313 ast_hangup(bridge_channel);
314 return NULL;
315}
ast_callid ast_channel_callid(const struct ast_channel *chan)
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition logger.c:2290
unsigned int ast_callid
void stasis_app_control_execute_until_exhausted(struct ast_channel *chan, struct stasis_app_control *control)
Act on a stasis app control queue until it is empty.
void stasis_app_bridge_playback_channel_control_remove(const char *bridge_id, struct stasis_app_control *control)
Remove a bridge playback channel's control from the app controls list.
Definition res_stasis.c:717
void stasis_app_control_flush_queue(struct stasis_app_control *control)
Flush the control command queue.
struct ast_bridge_channel * bridge_channel

References ao2_cleanup, ast_callid_threadassoc_add(), ast_channel_callid(), ast_free, ast_hangup(), ast_channel::bridge_channel, bridge_channel_control_thread_data::bridge_channel, bridge_channel_control_thread_data::bridge_id, bridge_channel_control_thread_data::control, bridge_channel_control_thread_data::forward, NULL, stasis_app_bridge_playback_channel_control_remove(), stasis_app_control_execute_until_exhausted(), stasis_app_control_flush_queue(), and stasis_forward_cancel().

Referenced by ari_bridges_play_new(), and ast_ari_bridges_record().

◆ bridge_set_video_source_cb()

static int bridge_set_video_source_cb ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 1100 of file resource_bridges.c.

1102{
1103 struct ast_bridge *bridge = data;
1104
1105 ast_bridge_lock(bridge);
1107 ast_bridge_unlock(bridge);
1108
1109 return 0;
1110}
void ast_bridge_set_single_src_video_mode(struct ast_bridge *bridge, struct ast_channel *video_src_chan)
Set a bridge to feed a single video source to all participants.
Definition bridge.c:3828

References ast_bridge_lock, ast_bridge_set_single_src_video_mode(), and ast_bridge_unlock.

Referenced by ast_ari_bridges_set_video_source().

◆ check_add_remove_channel()

static int check_add_remove_channel ( struct ast_ari_response response,
struct stasis_app_control control,
enum stasis_app_control_channel_result  result 
)
static

Definition at line 175 of file resource_bridges.c.

178{
179 switch (result) {
182 response, 409, "Conflict", "Channel %s currently recording",
184 return -1;
186 return 0;
187 }
188 return 0;
189}
static PGresult * result
Definition cel_pgsql.c:84
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition control.c:1482
@ STASIS_APP_CHANNEL_RECORDING
Definition stasis_app.h:823
@ STASIS_APP_CHANNEL_OKAY
Definition stasis_app.h:821

References ast_ari_response_error(), result, STASIS_APP_CHANNEL_OKAY, STASIS_APP_CHANNEL_RECORDING, and stasis_app_control_get_channel_id().

Referenced by ast_ari_bridges_add_channel().

◆ control_list_create()

static struct control_list * control_list_create ( struct ast_ari_response response,
size_t  count,
const char **  channels 
)
static

Definition at line 138 of file resource_bridges.c.

138 {
139 RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
140 size_t i;
141
142 if (count == 0 || !channels) {
143 ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
144 return NULL;
145 }
146
147 list = ao2_alloc(sizeof(*list) + count * sizeof(list->controls[0]), control_list_dtor);
148 if (!list) {
150 return NULL;
151 }
152
153 for (i = 0; i < count; ++i) {
154 if (ast_strlen_zero(channels[i])) {
155 continue;
156 }
157 list->controls[list->count] =
158 find_channel_control(response, channels[i]);
159 if (!list->controls[list->count]) {
160 /* response filled in by find_channel_control() */
161 return NULL;
162 }
163 ++list->count;
164 }
165
166 if (list->count == 0) {
167 ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
168 return NULL;
169 }
170
171 ao2_ref(list, +1);
172 return list;
173}
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
static struct channel_usage channels
static void control_list_dtor(void *obj)

References ao2_alloc, ao2_cleanup, ao2_ref, ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_strlen_zero(), channels, control_list_dtor(), control_list::count, find_channel_control(), NULL, and RAII_VAR.

Referenced by ast_ari_bridges_add_channel(), and ast_ari_bridges_remove_channel().

◆ control_list_dtor()

static void control_list_dtor ( void *  obj)
static

Definition at line 128 of file resource_bridges.c.

128 {
129 struct control_list *list = obj;
130 size_t i;
131
132 for (i = 0; i < list->count; ++i) {
133 ao2_cleanup(list->controls[i]);
134 list->controls[i] = NULL;
135 }
136}
struct stasis_app_control * controls[]

References ao2_cleanup, control_list::controls, control_list::count, and NULL.

Referenced by control_list_create().

◆ find_bridge()

static struct ast_bridge * find_bridge ( struct ast_ari_response response,
const char *  bridge_id 
)
static

Finds a bridge, filling the response with an error, if appropriate.

Parameters
[out]responseResponse to fill with an error if control is not found.
bridge_idID of the bridge to lookup.
Returns
Bridget.
Return values
NULLif bridge does not exist.

Definition at line 57 of file resource_bridges.c.

60{
61 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
62
63 ast_assert(response != NULL);
64
65 bridge = stasis_app_bridge_find_by_id(bridge_id);
66 if (bridge == NULL) {
67 RAII_VAR(struct ast_bridge_snapshot *, snapshot,
69 if (!snapshot) {
70 ast_ari_response_error(response, 404, "Not found",
71 "Bridge not found");
72 return NULL;
73 }
74
75 ast_ari_response_error(response, 409, "Conflict",
76 "Bridge not in Stasis application");
77 return NULL;
78 }
79
80 ao2_ref(bridge, +1);
81 return bridge;
82}
struct ast_bridge * stasis_app_bridge_find_by_id(const char *bridge_id)
Returns the bridge with the given id.
Definition res_stasis.c:807

References ao2_cleanup, ao2_ref, ast_ari_response_error(), ast_assert, ast_bridge_get_snapshot_by_uniqueid(), NULL, RAII_VAR, and stasis_app_bridge_find_by_id().

Referenced by ari_bridges_handle_play(), ast_ari_bridges_add_channel(), ast_ari_bridges_clear_video_source(), ast_ari_bridges_destroy(), ast_ari_bridges_record(), ast_ari_bridges_remove_channel(), ast_ari_bridges_set_video_source(), ast_ari_bridges_start_moh(), and ast_ari_bridges_stop_moh().

◆ find_channel_control()

static struct stasis_app_control * find_channel_control ( struct ast_ari_response response,
const char *  channel_id 
)
static

Finds the control object for a channel, filling the response with an error, if appropriate.

Parameters
[out]responseResponse to fill with an error if control is not found.
channel_idID of the channel to lookup.
Returns
Channel control object.
Return values
NULLif control object does not exist.

Definition at line 92 of file resource_bridges.c.

95{
96 RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
97
98 ast_assert(response != NULL);
99
100 control = stasis_app_control_find_by_channel_id(channel_id);
101 if (control == NULL) {
102 /* Distinguish between 400 and 422 errors */
103 RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL,
105 snapshot = ast_channel_snapshot_get_latest(channel_id);
106 if (snapshot == NULL) {
107 ast_log(LOG_DEBUG, "Couldn't find '%s'\n", channel_id);
108 ast_ari_response_error(response, 400, "Bad Request",
109 "Channel not found");
110 return NULL;
111 }
112
113 ast_log(LOG_DEBUG, "Found non-stasis '%s'\n", channel_id);
114 ast_ari_response_error(response, 422, "Unprocessable Entity",
115 "Channel not in Stasis application");
116 return NULL;
117 }
118
119 ao2_ref(control, +1);
120 return control;
121}
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,...
#define LOG_DEBUG
struct stasis_app_control * stasis_app_control_find_by_channel_id(const char *channel_id)
Returns the handler for the channel with the given id.
Definition res_stasis.c:349

References ao2_cleanup, ao2_ref, ast_ari_response_error(), ast_assert, ast_channel_snapshot_get_latest(), ast_log, LOG_DEBUG, NULL, RAII_VAR, and stasis_app_control_find_by_channel_id().

Referenced by ast_ari_bridges_set_video_source(), and control_list_create().

◆ prepare_bridge_media_channel()

static struct ast_channel * prepare_bridge_media_channel ( const char *  type,
struct ast_format channel_format 
)
static

Definition at line 317 of file resource_bridges.c.

319{
320 RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
321 struct ast_channel *chan;
322
324 if (!cap) {
325 return NULL;
326 }
327
328 /* This bumps the format's refcount */
329 ast_format_cap_append(cap, channel_format, 0);
330
331 chan = ast_request(type, cap, NULL, NULL, "ARI", NULL);
332 if (!chan) {
333 return NULL;
334 }
335
338 return NULL;
339 }
340 return chan;
341}
static const char type[]
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition channel.c:6411
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
int stasis_app_channel_unreal_set_internal(struct ast_channel *chan)
Mark this unreal channel and it's other half as being internal to Stasis.
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54

References ao2_cleanup, ast_channel_cleanup, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_request(), NULL, RAII_VAR, stasis_app_channel_unreal_set_internal(), and type.

Referenced by ari_bridges_play_new(), and ast_ari_bridges_record().