Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Enumerations | Functions | Variables
core_local.c File Reference

Local proxy channel driver. More...

#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/devicestate.h"
#include "asterisk/astobj2.h"
#include "asterisk/bridge.h"
#include "asterisk/core_unreal.h"
#include "asterisk/core_local.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/_private.h"
#include "asterisk/stream.h"
#include "asterisk/translate.h"
Include dependency graph for core_local.c:

Go to the source code of this file.

Data Structures

struct  local_bridge
 
struct  local_pvt
 the local pvt structure for all channels More...
 

Enumerations

enum  local_call_action { LOCAL_CALL_ACTION_DIALPLAN , LOCAL_CALL_ACTION_BRIDGE , LOCAL_CALL_ACTION_MASQUERADE }
 

Functions

struct ast_channelast_local_get_peer (struct ast_channel *ast)
 Get the other local channel in the pair. More...
 
int ast_local_init (void)
 Initialize the local proxy channel. More...
 
void ast_local_lock_all (struct ast_channel *chan, void **tech_pvt, struct ast_channel **base_chan, struct ast_channel **base_owner)
 Add a reference to the local channel's private tech, lock the local channel's private base, and add references and lock both sides of the local channel. More...
 
int ast_local_setup_bridge (struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
 Setup the outgoing local channel to join a bridge on ast_call(). More...
 
int ast_local_setup_masquerade (struct ast_channel *ast, struct ast_channel *masq)
 Setup the outgoing local channel to masquerade into a channel on ast_call(). More...
 
void ast_local_unlock_all (void *tech_pvt, struct ast_channel *base_chan, struct ast_channel *base_owner)
 Remove a reference to the given local channel's private tech, unlock the given local channel's private base, and remove references and unlock both sides of given the local channel. More...
 
static struct local_pvtlocal_alloc (const char *data, struct ast_stream_topology *topology)
 Create a call structure. More...
 
static int local_call (struct ast_channel *ast, const char *dest, int timeout)
 Initiate new call, part of PBX interface dest is the dial string. More...
 
static struct ast_multi_channel_bloblocal_channel_optimization_blob (struct local_pvt *p, struct ast_json *json_object)
 
static int local_devicestate (const char *data)
 Adds devicestate to local channels. More...
 
static int local_hangup (struct ast_channel *ast)
 Hangup a call through the local proxy channel. More...
 
static struct ast_manager_event_bloblocal_message_to_ami (struct stasis_message *msg)
 
static void local_optimization_finished_cb (struct ast_unreal_pvt *base, int success, unsigned int id)
 Callback for ast_unreal_pvt_callbacks optimization_finished. More...
 
static void local_optimization_started_cb (struct ast_unreal_pvt *base, struct ast_channel *source, enum ast_unreal_channel_indicator dest, unsigned int id)
 Callback for ast_unreal_pvt_callbacks optimization_started. More...
 
static void local_pvt_destructor (void *vdoomed)
 
static struct ast_channellocal_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 Part of PBX interface. More...
 
static struct ast_channellocal_request_with_stream_topology (const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 Part of PBX interface. More...
 
static int local_setoption (struct ast_channel *chan, int option, void *data, int datalen)
 
static void local_shutdown (void)
 
static int locals_cmp_cb (void *obj, void *arg, int flags)
 
static char * locals_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command "local show channels". More...
 
static int manager_optimize_away (struct mansession *s, const struct message *m)
 
static void publish_local_bridge_message (struct local_pvt *p)
 
 STASIS_MESSAGE_TYPE_DEFN (ast_local_bridge_type,.to_ami=local_message_to_ami,)
 Define local channel message types. More...
 
 STASIS_MESSAGE_TYPE_DEFN (ast_local_optimization_begin_type,.to_ami=local_message_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN (ast_local_optimization_end_type,.to_ami=local_message_to_ami,)
 

Variables

static struct ast_cli_entry cli_local []
 
static struct ast_channel_tech local_tech
 
struct ast_unreal_pvt_callbacks local_unreal_callbacks
 Callbacks from the unreal core when channel optimization occurs. More...
 
static struct ao2_containerlocals
 
static const char tdesc [] = "Local Proxy Channel Driver"
 

Detailed Description

Local proxy channel driver.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

See Also:

Definition in file core_local.c.

Enumeration Type Documentation

◆ local_call_action

What to do with the ;2 channel when ast_call() happens.

Enumerator
LOCAL_CALL_ACTION_DIALPLAN 
LOCAL_CALL_ACTION_BRIDGE 
LOCAL_CALL_ACTION_MASQUERADE 

Definition at line 197 of file core_local.c.

197 {
198 /* The ast_call() will run dialplan on the ;2 channel. */
200 /* The ast_call() will impart the ;2 channel into a bridge. */
202 /* The ast_call() will masquerade the ;2 channel into a channel. */
204};
@ LOCAL_CALL_ACTION_BRIDGE
Definition: core_local.c:201
@ LOCAL_CALL_ACTION_MASQUERADE
Definition: core_local.c:203
@ LOCAL_CALL_ACTION_DIALPLAN
Definition: core_local.c:199

Function Documentation

◆ ast_local_get_peer()

struct ast_channel * ast_local_get_peer ( struct ast_channel ast)

Get the other local channel in the pair.

Since
12.0.0
Parameters
astLocal channel to get peer.
Note
On entry, ast must be locked.
Return values
peerreffed on success.
NULLif no peer or error.

Definition at line 276 of file core_local.c.

277{
278 struct local_pvt *p = ast_channel_tech_pvt(ast);
279 struct local_pvt *found;
280 struct ast_channel *peer;
281
282 if (!p) {
283 return NULL;
284 }
285
286 found = p ? ao2_find(locals, p, 0) : NULL;
287 if (!found) {
288 /* ast is either not a local channel or it has alredy been hungup */
289 return NULL;
290 }
291 ao2_lock(found);
292 if (ast == p->base.owner) {
293 peer = p->base.chan;
294 } else if (ast == p->base.chan) {
295 peer = p->base.owner;
296 } else {
297 peer = NULL;
298 }
299 if (peer) {
300 ast_channel_ref(peer);
301 }
302 ao2_unlock(found);
303 ao2_ref(found, -1);
304 return peer;
305}
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
static struct ao2_container * locals
Definition: core_local.c:138
#define NULL
Definition: resample.c:96
Main Channel structure associated with a channel.
struct ast_channel * chan
Definition: core_unreal.h:94
struct ast_channel * owner
Definition: core_unreal.h:93
the local pvt structure for all channels
Definition: core_local.c:223
struct ast_unreal_pvt base
Definition: core_local.c:225

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_channel_ref, ast_channel_tech_pvt(), local_pvt::base, ast_unreal_pvt::chan, locals, NULL, and ast_unreal_pvt::owner.

Referenced by ari_channels_handle_originate_with_id(), bridge_channel_internal_join(), and park_local_transfer().

◆ ast_local_init()

int ast_local_init ( void  )

Initialize the local proxy channel.

Since
12.0.0
Return values
0on success.
-1on error.

Definition at line 1139 of file core_local.c.

1140{
1142 return -1;
1143 }
1144
1146 return -1;
1147 }
1148
1150 return -1;
1151 }
1152
1154 return -1;
1155 }
1157
1159 if (!locals) {
1160 return -1;
1161 }
1162
1163 /* Make sure we can register our channel type */
1165 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
1166
1167 return -1;
1168 }
1171
1173 return 0;
1174}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
static int manager_optimize_away(struct mansession *s, const struct message *m)
Definition: core_local.c:1074
static int locals_cmp_cb(void *obj, void *arg, int flags)
Definition: core_local.c:1111
static struct ast_channel_tech local_tech
Definition: core_local.c:173
static struct ast_cli_entry cli_local[]
Definition: core_local.c:1070
static void local_shutdown(void)
Definition: core_local.c:1121
struct stasis_message_type * ast_local_bridge_type(void)
Message type for when two local channel halves are bridged together.
struct stasis_message_type * ast_local_optimization_end_type(void)
Message type for when a local channel optimization completes.
struct stasis_message_type * ast_local_optimization_begin_type(void)
Message type for when a local channel optimization begins.
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition: format_cap.c:216
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
#define LOG_ERROR
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:202
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define EVENT_FLAG_CALL
Definition: manager.h:76
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
struct ast_format_cap * capabilities
Definition: channel.h:632
#define ARRAY_LEN(a)
Definition: utils.h:666

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple, ast_format_cap_alloc, ast_format_cap_append_by_type(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_local_bridge_type(), ast_local_optimization_begin_type(), ast_local_optimization_end_type(), ast_log, ast_manager_register_xml_core, AST_MEDIA_TYPE_UNKNOWN, ast_register_cleanup(), ast_channel_tech::capabilities, cli_local, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, local_shutdown(), local_tech, locals, locals_cmp_cb(), LOG_ERROR, manager_optimize_away(), NULL, and STASIS_MESSAGE_TYPE_INIT.

Referenced by asterisk_daemon().

◆ ast_local_lock_all()

void ast_local_lock_all ( struct ast_channel chan,
void **  tech_pvt,
struct ast_channel **  base_chan,
struct ast_channel **  base_owner 
)

Add a reference to the local channel's private tech, lock the local channel's private base, and add references and lock both sides of the local channel.

Note
None of these locks should be held prior to calling this function.
To undo this process call ast_local_unlock_all2.
Since
13.17.0, 14.6.0
Parameters
chanMust be a local channel
[out]tech_pvtchannel's private tech (ref and lock added)
[out]base_chanOne side of the local channel (ref and lock added)
[out]base_ownerOther side of the local channel (ref and lock added)

Definition at line 241 of file core_local.c.

243{
244 struct local_pvt *p = ast_channel_tech_pvt(chan);
245
246 *tech_pvt = NULL;
247 *base_chan = NULL;
248 *base_owner = NULL;
249
250 if (p) {
251 *tech_pvt = ao2_bump(p);
252 ast_unreal_lock_all(&p->base, base_chan, base_owner);
253 }
254}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
Send an unreal pvt in with no locks held and get all locks.
Definition: core_unreal.c:47

References ao2_bump, ast_channel_tech_pvt(), ast_unreal_lock_all(), local_pvt::base, and NULL.

Referenced by attended_transfer_bridge().

◆ ast_local_setup_bridge()

int ast_local_setup_bridge ( struct ast_channel ast,
struct ast_bridge bridge,
struct ast_channel swap,
struct ast_bridge_features features 
)

Setup the outgoing local channel to join a bridge on ast_call().

Since
12.0.0
Parameters
astEither channel of a local channel pair.
bridgeBridge to join.
swapChannel to swap with when joining.
featuresBridge features structure.
Note
The features parameter must be NULL or obtained by ast_bridge_features_new(). You must not dereference features after calling even if the call fails.
Intended to be called after ast_request() and before ast_call() on a local channel.
Return values
0on success.
-1on error.

Definition at line 601 of file core_local.c.

602{
603 struct local_pvt *p;
604 struct local_pvt *found;
605 int res = -1;
606
607 /* Sanity checks. */
608 if (!ast || !bridge) {
610 return -1;
611 }
612
613 ast_channel_lock(ast);
614 p = ast_channel_tech_pvt(ast);
616
617 found = p ? ao2_find(locals, p, 0) : NULL;
618 if (found) {
619 ao2_lock(found);
620 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
621 && found->base.owner
622 && found->base.chan
624 ao2_ref(bridge, +1);
625 if (swap) {
626 ast_channel_ref(swap);
627 }
629 found->action.bridge.join = bridge;
630 found->action.bridge.swap = swap;
631 found->action.bridge.features = features;
632 res = 0;
633 } else {
635 }
636 ao2_unlock(found);
637 ao2_ref(found, -1);
638 }
639
640 return res;
641}
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3674
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
struct ast_channel * swap
Definition: core_local.c:211
struct ast_bridge * join
Definition: core_local.c:209
struct ast_bridge_features * features
Definition: core_local.c:213
struct local_bridge bridge
Definition: core_local.c:229
union local_pvt::@338 action
enum local_call_action type
Definition: core_local.c:234
#define ast_test_flag(p, flag)
Definition: utils.h:63

References local_pvt::action, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_features_destroy(), ast_channel_lock, ast_channel_ref, ast_channel_tech_pvt(), ast_channel_unlock, ast_test_flag, AST_UNREAL_CARETAKER_THREAD, local_pvt::base, local_pvt::bridge, ast_unreal_pvt::chan, local_bridge::features, local_bridge::join, LOCAL_CALL_ACTION_BRIDGE, LOCAL_CALL_ACTION_DIALPLAN, locals, NULL, ast_unreal_pvt::owner, local_bridge::swap, and local_pvt::type.

Referenced by attended_transfer_bridge().

◆ ast_local_setup_masquerade()

int ast_local_setup_masquerade ( struct ast_channel ast,
struct ast_channel masq 
)

Setup the outgoing local channel to masquerade into a channel on ast_call().

Since
12.0.0
Parameters
astEither channel of a local channel pair.
masqChannel to masquerade into.
Note
Intended to be called after ast_request() and before ast_call() on a local channel.
Return values
0on success.
-1on error.

Definition at line 643 of file core_local.c.

644{
645 struct local_pvt *p;
646 struct local_pvt *found;
647 int res = -1;
648
649 /* Sanity checks. */
650 if (!ast || !masq) {
651 return -1;
652 }
653
654 ast_channel_lock(ast);
655 p = ast_channel_tech_pvt(ast);
657
658 found = p ? ao2_find(locals, p, 0) : NULL;
659 if (found) {
660 ao2_lock(found);
661 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
662 && found->base.owner
663 && found->base.chan
667 found->action.masq = masq;
668 res = 0;
669 }
670 ao2_unlock(found);
671 ao2_ref(found, -1);
672 }
673
674 return res;
675}
struct ast_channel * masq
Definition: core_local.c:231

References local_pvt::action, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_channel_lock, ast_channel_ref, ast_channel_tech_pvt(), ast_channel_unlock, ast_test_flag, AST_UNREAL_CARETAKER_THREAD, local_pvt::base, ast_unreal_pvt::chan, LOCAL_CALL_ACTION_DIALPLAN, LOCAL_CALL_ACTION_MASQUERADE, locals, local_pvt::masq, NULL, ast_unreal_pvt::owner, and local_pvt::type.

Referenced by attended_transfer_bridge().

◆ ast_local_unlock_all()

void ast_local_unlock_all ( void *  tech_pvt,
struct ast_channel base_chan,
struct ast_channel base_owner 
)

Remove a reference to the given local channel's private tech, unlock the given local channel's private base, and remove references and unlock both sides of given the local channel.

Note
This function should be used in conjunction with ast_local_lock_all2.
Since
13.17.0, 14.6.0
Parameters
tech_pvtchannel's private tech (ref and lock removed)
base_chanOne side of the local channel (ref and lock removed)
base_ownerOther side of the local channel (ref and lock removed)

Definition at line 256 of file core_local.c.

258{
259 if (base_chan) {
260 ast_channel_unlock(base_chan);
261 ast_channel_unref(base_chan);
262 }
263
264 if (base_owner) {
265 ast_channel_unlock(base_owner);
266 ast_channel_unref(base_owner);
267 }
268
269 if (tech_pvt) {
270 struct local_pvt *p = tech_pvt;
271 ao2_unlock(&p->base);
272 ao2_ref(tech_pvt, -1);
273 }
274}
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958

References ao2_ref, ao2_unlock, ast_channel_unlock, ast_channel_unref, and local_pvt::base.

Referenced by attended_transfer_bridge().

◆ local_alloc()

static struct local_pvt * local_alloc ( const char *  data,
struct ast_stream_topology topology 
)
static

Create a call structure.

Definition at line 866 of file core_local.c.

867{
868 struct local_pvt *pvt;
869 char *parse;
870 char *context;
871 char *opts;
872
873 pvt = (struct local_pvt *) ast_unreal_alloc_stream_topology(sizeof(*pvt), local_pvt_destructor, topology);
874 if (!pvt) {
875 return NULL;
876 }
878
879 parse = ast_strdupa(data);
880
881 /*
882 * Local channels intercept MOH by default.
883 *
884 * This is a silly default because it represents state held by
885 * the local channels. Unless local channel optimization is
886 * disabled, the state will dissapear when the local channels
887 * optimize out.
888 */
890
891 /* Look for options.
892 * Slashes can appear in channel names, so options are after the last match. */
893 if ((opts = strrchr(parse, '/'))) {
894 *opts++ = '\0';
895 if (strchr(opts, 'n')) {
897 }
898 if (strchr(opts, 'j')) {
901 } else {
902 ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
903 }
904 }
905 if (strchr(opts, 'm')) {
907 }
908 }
909
910 /* Look for a context */
911 if ((context = strchr(parse, '@'))) {
912 *context++ = '\0';
913 }
914
915 ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
916 ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
917 snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);
918
919 return pvt; /* this is returned with a ref */
920}
@ AST_JB_ENABLED
Definition: abstract_jb.h:45
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static void local_pvt_destructor(void *vdoomed)
Definition: core_local.c:846
struct ast_unreal_pvt_callbacks local_unreal_callbacks
Callbacks from the unreal core when channel optimization occurs.
Definition: core_local.c:167
#define AST_UNREAL_MOH_INTERCEPT
Definition: core_unreal.h:109
#define AST_UNREAL_NO_OPTIMIZATION
Definition: core_unreal.h:108
struct ast_unreal_pvt * ast_unreal_alloc_stream_topology(size_t size, ao2_destructor_fn destructor, struct ast_stream_topology *topology)
Allocate the base unreal struct for a derivative.
Definition: core_unreal.c:1126
#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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
struct ast_jb_conf jb_conf
Definition: core_unreal.h:96
char name[AST_MAX_EXTENSION+AST_MAX_CONTEXT+2]
Definition: core_unreal.h:99
struct ast_unreal_pvt_callbacks * callbacks
Definition: core_unreal.h:92
char exten[AST_MAX_EXTENSION]
Definition: core_local.c:238
char context[AST_MAX_CONTEXT]
Definition: core_local.c:236
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_clear_flag, ast_copy_string(), AST_JB_ENABLED, ast_log, ast_set_flag, ast_strdupa, ast_test_flag, ast_unreal_alloc_stream_topology(), AST_UNREAL_MOH_INTERCEPT, AST_UNREAL_NO_OPTIMIZATION, local_pvt::base, ast_unreal_pvt::callbacks, voicemailpwcheck::context, local_pvt::context, local_pvt::exten, ast_unreal_pvt::jb_conf, local_pvt_destructor(), local_unreal_callbacks, LOG_ERROR, ast_unreal_pvt::name, NULL, and S_OR.

Referenced by local_request_with_stream_topology().

◆ local_call()

static int local_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
)
static

Initiate new call, part of PBX interface dest is the dial string.

Definition at line 679 of file core_local.c.

680{
681 struct local_pvt *p = ast_channel_tech_pvt(ast);
682 int pvt_locked = 0;
683
684 struct ast_channel *owner = NULL;
685 struct ast_channel *chan = NULL;
686 int res;
687 char *reduced_dest = ast_strdupa(dest);
688 char *slash;
689 const char *chan_cid;
690
691 if (!p) {
692 return -1;
693 }
694
695 /* since we are letting go of channel locks that were locked coming into
696 * this function, then we need to give the tech pvt a ref */
697 ao2_ref(p, 1);
699
700 ast_unreal_lock_all(&p->base, &chan, &owner);
701 pvt_locked = 1;
702
703 if (owner != ast) {
704 res = -1;
705 goto return_cleanup;
706 }
707
708 if (!owner || !chan) {
709 res = -1;
710 goto return_cleanup;
711 }
712
713 ast_unreal_call_setup(owner, chan);
714
715 /*
716 * If the local channel has /n on the end of it, we need to lop
717 * that off for our argument to setting up the CC_INTERFACES
718 * variable.
719 */
720 if ((slash = strrchr(reduced_dest, '/'))) {
721 *slash = '\0';
722 }
723 ast_set_cc_interfaces_chanvar(chan, reduced_dest);
724
725 ao2_unlock(p);
726 pvt_locked = 0;
727
728 ast_channel_unlock(owner);
729
730 chan_cid = S_COR(ast_channel_caller(chan)->id.number.valid,
731 ast_channel_caller(chan)->id.number.str, NULL);
732 if (chan_cid) {
733 chan_cid = ast_strdupa(chan_cid);
734 }
735 ast_channel_unlock(chan);
736
737 res = -1;
738 switch (p->type) {
740 if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
741 ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
742 p->exten, p->context);
743 } else {
745
746 /* Start switch on sub channel */
747 res = ast_pbx_start(chan);
748 }
749 break;
752 ast_answer(chan);
755 ao2_ref(p->action.bridge.join, -1);
756 p->action.bridge.join = NULL;
758 p->action.bridge.swap = NULL;
760 break;
763 ast_answer(chan);
764 res = ast_channel_move(p->action.masq, chan);
765 if (!res) {
766 /* Chan is now an orphaned zombie. Destroy it. */
767 ast_hangup(chan);
768 }
770 break;
771 }
772 if (!res) {
773 ao2_lock(p);
775 ao2_unlock(p);
776 }
777
778 /* we already unlocked them, clear them here so the cleanup label won't touch them. */
779 owner = ast_channel_unref(owner);
780 chan = ast_channel_unref(chan);
781
782return_cleanup:
783 if (p) {
784 if (pvt_locked) {
785 ao2_unlock(p);
786 }
787 ao2_ref(p, -1);
788 }
789 if (chan) {
790 ast_channel_unlock(chan);
791 ast_channel_unref(chan);
792 }
793
794 /*
795 * owner is supposed to be == to ast, if it is, don't unlock it
796 * because ast must exit locked
797 */
798 if (owner) {
799 if (owner != ast) {
800 ast_channel_unlock(owner);
801 ast_channel_lock(ast);
802 }
803 ast_channel_unref(owner);
804 } else {
805 /* we have to exit with ast locked */
806 ast_channel_lock(ast);
807 }
808
809 return res;
810}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1878
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:590
int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char *const extension)
Set the CC_INTERFACES channel variable for a channel using an.
Definition: ccss.c:3633
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
int ast_channel_move(struct ast_channel *dest, struct ast_channel *source)
Move a channel from its current location to a new location.
Definition: channel.c:10666
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2805
static void publish_local_bridge_message(struct local_pvt *p)
Definition: core_local.c:542
void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
Setup unreal owner and chan channels before initiating call.
Definition: core_unreal.c:870
#define LOG_NOTICE
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
Number structure.
Definition: app_followme.c:154

References local_pvt::action, ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_answer(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_channel_caller(), ast_channel_lock, ast_channel_move(), ast_channel_tech_pvt(), ast_channel_unlock, ast_channel_unref, ast_exists_extension(), ast_hangup(), ast_log, ast_pbx_start(), ast_set_cc_interfaces_chanvar(), ast_set_flag, ast_strdupa, ast_unreal_call_setup(), AST_UNREAL_CARETAKER_THREAD, ast_unreal_lock_all(), local_pvt::base, local_pvt::bridge, local_pvt::context, local_pvt::exten, local_bridge::features, local_bridge::join, LOCAL_CALL_ACTION_BRIDGE, LOCAL_CALL_ACTION_DIALPLAN, LOCAL_CALL_ACTION_MASQUERADE, LOG_NOTICE, local_pvt::masq, NULL, publish_local_bridge_message(), S_COR, local_bridge::swap, and local_pvt::type.

◆ local_channel_optimization_blob()

static struct ast_multi_channel_blob * local_channel_optimization_blob ( struct local_pvt p,
struct ast_json json_object 
)
static

Definition at line 366 of file core_local.c.

368{
369 struct ast_multi_channel_blob *payload;
370 RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
371 RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
372
374 if (!local_one_snapshot) {
375 return NULL;
376 }
377
379 if (!local_two_snapshot) {
380 return NULL;
381 }
382
383 payload = ast_multi_channel_blob_create(json_object);
384 if (!payload) {
385 return NULL;
386 }
387 ast_multi_channel_blob_add_channel(payload, "1", local_one_snapshot);
388 ast_multi_channel_blob_add_channel(payload, "2", local_two_snapshot);
389
390 return payload;
391}
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
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,...
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
Structure representing a snapshot of channel state.
A multi channel blob data structure for multi_channel_blob stasis messages.
#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:941

References ao2_cleanup, ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_multi_channel_blob_add_channel(), ast_multi_channel_blob_create(), local_pvt::base, ast_unreal_pvt::chan, NULL, ast_unreal_pvt::owner, and RAII_VAR.

Referenced by local_optimization_finished_cb(), and local_optimization_started_cb().

◆ local_devicestate()

static int local_devicestate ( const char *  data)
static

Adds devicestate to local channels.

Definition at line 308 of file core_local.c.

309{
310 int is_inuse = 0;
311 int res = AST_DEVICE_INVALID;
312 char *exten = ast_strdupa(data);
313 char *context;
314 char *opts;
315 struct local_pvt *lp;
316 struct ao2_iterator it;
317
318 context = strchr(exten, '@');
319 if (!context) {
321 "Someone used Local/%s somewhere without a @context. This is bad.\n", data);
322 return AST_DEVICE_INVALID;
323 }
324 *context++ = '\0';
325
326 /* Strip options if they exist.
327 * However, don't strip '/' before an '@' (exten could contain slashes).
328 * So only start looking for '/' in context, because options would be past
329 * this point if they exist, but anything before would be a '/' in the exten,
330 * not options. */
331 opts = strchr(context, '/');
332 if (opts) {
333 *opts = '\0';
334 }
335
336 it = ao2_iterator_init(locals, 0);
337 for (; (lp = ao2_iterator_next(&it)); ao2_ref(lp, -1)) {
338 ao2_lock(lp);
339 if (!strcmp(exten, lp->exten)
340 && !strcmp(context, lp->context)) {
342 if (lp->base.owner
344 is_inuse = 1;
345 }
346 }
347 ao2_unlock(lp);
348 if (is_inuse) {
349 res = AST_DEVICE_INUSE;
350 ao2_ref(lp, -1);
351 break;
352 }
353 }
355
356 if (res == AST_DEVICE_INVALID) {
357 ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
358 if (ast_exists_extension(NULL, context, exten, 1, NULL)) {
360 }
361 }
362
363 return res;
364}
#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.
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
@ AST_DEVICE_INVALID
Definition: devicestate.h:57
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_debug, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, ast_exists_extension(), ast_log, ast_strdupa, ast_test_flag, AST_UNREAL_CARETAKER_THREAD, local_pvt::base, voicemailpwcheck::context, local_pvt::context, ast_channel::data, ast_channel::exten, local_pvt::exten, locals, LOG_WARNING, NULL, and ast_unreal_pvt::owner.

◆ local_hangup()

static int local_hangup ( struct ast_channel ast)
static

Hangup a call through the local proxy channel.

Definition at line 813 of file core_local.c.

814{
815 struct local_pvt *p = ast_channel_tech_pvt(ast);
816 int res;
817
818 if (!p) {
819 return -1;
820 }
821
822 /* give the pvt a ref to fulfill calling requirements. */
823 ao2_ref(p, +1);
824 res = ast_unreal_hangup(&p->base, ast);
825 if (!res) {
826 int unlink;
827
828 ao2_lock(p);
829 unlink = !p->base.owner && !p->base.chan;
830 ao2_unlock(p);
831 if (unlink) {
832 ao2_unlink(locals, p);
833 }
834 }
835 ao2_ref(p, -1);
836
837 return res;
838}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
int ast_unreal_hangup(struct ast_unreal_pvt *p, struct ast_channel *ast)
Hangup one end (maybe both ends) of an unreal channel derivative.
Definition: core_unreal.c:1018

References ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ast_channel_tech_pvt(), ast_unreal_hangup(), local_pvt::base, ast_unreal_pvt::chan, locals, and ast_unreal_pvt::owner.

◆ local_message_to_ami()

static struct ast_manager_event_blob * local_message_to_ami ( struct stasis_message msg)
static

Definition at line 467 of file core_local.c.

468{
470 struct ast_json *blob = ast_multi_channel_blob_get_json(obj);
471 struct ast_channel_snapshot *local_snapshot_one;
472 struct ast_channel_snapshot *local_snapshot_two;
473 RAII_VAR(struct ast_str *, local_channel_one, NULL, ast_free);
474 RAII_VAR(struct ast_str *, local_channel_two, NULL, ast_free);
475 RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free);
476 const char *event;
477
478 local_snapshot_one = ast_multi_channel_blob_get_channel(obj, "1");
479 local_snapshot_two = ast_multi_channel_blob_get_channel(obj, "2");
480 if (!local_snapshot_one || !local_snapshot_two) {
481 return NULL;
482 }
483
484 event_buffer = ast_str_create(1024);
485 local_channel_one = ast_manager_build_channel_state_string_prefix(local_snapshot_one, "LocalOne");
486 local_channel_two = ast_manager_build_channel_state_string_prefix(local_snapshot_two, "LocalTwo");
487 if (!event_buffer || !local_channel_one || !local_channel_two) {
488 return NULL;
489 }
490
492 struct ast_channel_snapshot *source_snapshot;
493 RAII_VAR(struct ast_str *, source_str, NULL, ast_free);
494 const char *dest_uniqueid;
495
496 source_snapshot = ast_multi_channel_blob_get_channel(obj, "source");
497 if (source_snapshot) {
498 source_str = ast_manager_build_channel_state_string_prefix(source_snapshot, "Source");
499 if (!source_str) {
500 return NULL;
501 }
502 }
503
504 dest_uniqueid = ast_json_object_get(blob, "dest") == AST_UNREAL_OWNER ?
505 local_snapshot_one->base->uniqueid : local_snapshot_two->base->uniqueid;
506
507 event = "LocalOptimizationBegin";
508 if (source_str) {
509 ast_str_append(&event_buffer, 0, "%s", ast_str_buffer(source_str));
510 }
511 ast_str_append(&event_buffer, 0, "DestUniqueId: %s\r\n", dest_uniqueid);
512 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
514 event = "LocalOptimizationEnd";
515 ast_str_append(&event_buffer, 0, "Success: %s\r\n", ast_json_integer_get(ast_json_object_get(blob, "success")) ? "Yes" : "No");
516 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
518 event = "LocalBridge";
519 ast_str_append(&event_buffer, 0, "Context: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "context")));
520 ast_str_append(&event_buffer, 0, "Exten: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "exten")));
521 ast_str_append(&event_buffer, 0, "LocalOptimization: %s\r\n", ast_json_is_true(ast_json_object_get(blob, "can_optimize")) ? "Yes" : "No");
522 } else {
523 return NULL;
524 }
525
527 "%s"
528 "%s"
529 "%s",
530 ast_str_buffer(local_channel_one),
531 ast_str_buffer(local_channel_two),
532 ast_str_buffer(event_buffer));
533}
#define ast_free(a)
Definition: astmm.h:180
@ AST_UNREAL_OWNER
Definition: core_unreal.h:50
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
int ast_json_is_true(const struct ast_json *value)
Check if value is JSON true.
Definition: json.c:263
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10548
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
const ast_string_field uniqueid
struct ast_channel_snapshot_base * base
Abstract JSON element (object, array, string, int, ...).
Support for dynamic strings.
Definition: strings.h:623
Definition: astman.c:222

References ast_free, ast_json_integer_get(), ast_json_is_true(), ast_json_object_get(), ast_json_string_get(), ast_local_bridge_type(), ast_local_optimization_begin_type(), ast_local_optimization_end_type(), ast_manager_build_channel_state_string_prefix(), ast_manager_event_blob_create(), ast_multi_channel_blob_get_channel(), ast_multi_channel_blob_get_json(), ast_str_append(), ast_str_buffer(), ast_str_create, AST_UNREAL_OWNER, ast_channel_snapshot::base, EVENT_FLAG_CALL, NULL, RAII_VAR, stasis_message_data(), stasis_message_type(), and ast_channel_snapshot_base::uniqueid.

◆ local_optimization_finished_cb()

static void local_optimization_finished_cb ( struct ast_unreal_pvt base,
int  success,
unsigned int  id 
)
static

Callback for ast_unreal_pvt_callbacks optimization_finished.

Definition at line 437 of file core_local.c.

438{
439 RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
440 RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
441 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
442 struct local_pvt *p = (struct local_pvt *)base;
443
445 return;
446 }
447
448 json_object = ast_json_pack("{s: i, s: I}", "success", success, "id", (ast_json_int_t)id);
449
450 if (!json_object) {
451 return;
452 }
453
454 payload = local_channel_optimization_blob(p, json_object);
455 if (!payload) {
456 return;
457 }
458
460 if (!msg) {
461 return;
462 }
463
465}
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
static struct ast_multi_channel_blob * local_channel_optimization_blob(struct local_pvt *p, struct ast_json *json_object)
Definition: core_local.c:366
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
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_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511

References ao2_cleanup, ast_channel_topic(), ast_json_null(), ast_json_pack(), ast_json_unref(), ast_local_optimization_end_type(), local_pvt::base, local_channel_optimization_blob(), NULL, ast_unreal_pvt::owner, RAII_VAR, stasis_message_create(), and stasis_publish().

◆ local_optimization_started_cb()

static void local_optimization_started_cb ( struct ast_unreal_pvt base,
struct ast_channel source,
enum ast_unreal_channel_indicator  dest,
unsigned int  id 
)
static

Callback for ast_unreal_pvt_callbacks optimization_started.

Definition at line 394 of file core_local.c.

396{
397 RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
398 RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
399 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
400 struct local_pvt *p = (struct local_pvt *)base;
401
403 return;
404 }
405
406 json_object = ast_json_pack("{s: i, s: I}",
407 "dest", dest, "id", (ast_json_int_t)id);
408
409 if (!json_object) {
410 return;
411 }
412
413 payload = local_channel_optimization_blob(p, json_object);
414 if (!payload) {
415 return;
416 }
417
418 if (source) {
419 RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup);
420 source_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(source));
421 if (!source_snapshot) {
422 return;
423 }
424
425 ast_multi_channel_blob_add_channel(payload, "source", source_snapshot);
426 }
427
429 if (!msg) {
430 return;
431 }
432
434}

References ao2_cleanup, ast_channel_snapshot_get_latest(), ast_channel_topic(), ast_channel_uniqueid(), ast_json_null(), ast_json_pack(), ast_json_unref(), ast_local_optimization_begin_type(), ast_multi_channel_blob_add_channel(), local_pvt::base, local_channel_optimization_blob(), NULL, ast_unreal_pvt::owner, RAII_VAR, stasis_message_create(), and stasis_publish().

◆ local_pvt_destructor()

static void local_pvt_destructor ( void *  vdoomed)
static

Definition at line 846 of file core_local.c.

847{
848 struct local_pvt *doomed = vdoomed;
849
850 switch (doomed->type) {
852 break;
854 ao2_cleanup(doomed->action.bridge.join);
855 ao2_cleanup(doomed->action.bridge.swap);
857 break;
859 ao2_cleanup(doomed->action.masq);
860 break;
861 }
862 ast_unreal_destructor(&doomed->base);
863}
void ast_unreal_destructor(void *vdoomed)
struct ast_unreal_pvt destructor.
Definition: core_unreal.c:1097

References local_pvt::action, ao2_cleanup, ast_bridge_features_destroy(), ast_unreal_destructor(), local_pvt::base, local_pvt::bridge, local_bridge::features, local_bridge::join, LOCAL_CALL_ACTION_BRIDGE, LOCAL_CALL_ACTION_DIALPLAN, LOCAL_CALL_ACTION_MASQUERADE, local_pvt::masq, local_bridge::swap, and local_pvt::type.

Referenced by local_alloc().

◆ local_request()

static struct ast_channel * local_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  data,
int *  cause 
)
static

Part of PBX interface.

Definition at line 923 of file core_local.c.

924{
925 struct ast_stream_topology *topology;
926 struct ast_channel *chan;
927
929 if (!topology) {
930 return NULL;
931 }
932
933 chan = local_request_with_stream_topology(type, topology, assignedids, requestor, data, cause);
934
935 ast_stream_topology_free(topology);
936
937 return chan;
938}
static const char type[]
Definition: chan_ooh323.c:109
static struct ast_channel * local_request_with_stream_topology(const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Part of PBX interface.
Definition: core_local.c:941
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition: stream.c:848
const char * data

References ast_stream_topology_create_from_format_cap(), ast_stream_topology_free(), ast_channel::data, local_request_with_stream_topology(), NULL, and type.

◆ local_request_with_stream_topology()

static struct ast_channel * local_request_with_stream_topology ( const char *  type,
struct ast_stream_topology topology,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  data,
int *  cause 
)
static

Part of PBX interface.

Definition at line 941 of file core_local.c.

942{
943 struct ast_stream_topology *audio_filtered_topology;
944 int i;
945 struct local_pvt *p;
946 struct ast_channel *chan;
948
949 /* Create a copy of the requested topology as we don't have ownership over
950 * the one that is passed in.
951 */
952 audio_filtered_topology = ast_stream_topology_clone(topology);
953 if (!audio_filtered_topology) {
954 return NULL;
955 }
956
957 /* Some users of Local channels request every known format in the
958 * universe. The core itself automatically pruned this list down to a single
959 * "best" format for audio in non-multistream. We replicate the logic here to
960 * do the same thing.
961 */
962 for (i = 0; i < ast_stream_topology_get_count(audio_filtered_topology); ++i) {
963 struct ast_stream *stream;
964 int res;
965 struct ast_format *tmp_fmt = NULL;
966 struct ast_format *best_audio_fmt = NULL;
967 struct ast_format_cap *caps;
968
969 stream = ast_stream_topology_get_stream(audio_filtered_topology, i);
970
973 continue;
974 }
975
976 /* Respect the immutable state of formats on the stream and create a new
977 * format capabilities to replace the existing one.
978 */
980 if (!caps) {
981 ao2_ref(audio_filtered_topology, -1);
982 return NULL;
983 }
984
985 /* The ast_translator_best_choice function treats both caps as const
986 * but does not declare it in the API.
987 */
989 &tmp_fmt, &best_audio_fmt);
990 if (res < 0) {
991 struct ast_str *tech_codecs = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
992 struct ast_str *request_codecs = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
993
994 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type,
996 ast_format_cap_get_names(ast_stream_get_formats(stream), &request_codecs));
997
998 /* If there are no formats then we abort */
999 ao2_ref(caps, -1);
1000 ao2_ref(audio_filtered_topology, -1);
1001 return NULL;
1002 }
1003
1004 ast_format_cap_append(caps, best_audio_fmt, 0);
1005 ast_stream_set_formats(stream, caps);
1006
1007 ao2_ref(caps, -1);
1008 ao2_ref(tmp_fmt, -1);
1009 ao2_ref(best_audio_fmt, -1);
1010 }
1011
1012 /* Allocate a new private structure and then Asterisk channels */
1013 p = local_alloc(data, audio_filtered_topology);
1014 ao2_ref(audio_filtered_topology, -1);
1015 if (!p) {
1016 return NULL;
1017 }
1020 p->exten, p->context, assignedids, requestor, callid);
1021 if (chan) {
1022 ao2_link(locals, p);
1023 }
1024 ao2_ref(p, -1); /* kill the ref from the alloc */
1025
1026 return chan;
1027}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
static struct local_pvt * local_alloc(const char *data, struct ast_stream_topology *topology)
Create a call structure.
Definition: core_local.c:866
struct ast_channel * ast_unreal_new_channels(struct ast_unreal_pvt *p, const struct ast_channel_tech *tech, int semi1_state, int semi2_state, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
Create the semi1 and semi2 unreal channels.
Definition: core_unreal.c:1160
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2286
unsigned int ast_callid
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
#define ast_str_alloca(init_len)
Definition: strings.h:848
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
int ast_translator_best_choice(struct ast_format_cap *dst_cap, struct ast_format_cap *src_cap, struct ast_format **dst_fmt_out, struct ast_format **src_fmt_out)
Chooses the best translation path.
Definition: translate.c:1402

References ao2_link, ao2_ref, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, ast_log, AST_MEDIA_TYPE_AUDIO, ast_read_threadstorage_callid(), AST_STATE_DOWN, AST_STATE_RING, ast_str_alloca, ast_stream_get_formats(), ast_stream_get_state(), ast_stream_get_type(), ast_stream_set_formats(), AST_STREAM_STATE_REMOVED, ast_stream_topology_clone(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), ast_translator_best_choice(), ast_unreal_new_channels(), local_pvt::base, ast_channel::callid, ast_channel_tech::capabilities, local_pvt::context, local_pvt::exten, local_alloc(), local_tech, locals, LOG_WARNING, NULL, and type.

Referenced by local_request().

◆ local_setoption()

int local_setoption ( struct ast_channel chan,
int  option,
void *  data,
int  datalen 
)
static

Definition at line 1176 of file core_local.c.

1177{
1178 switch (option) {
1181 return 0; /* local calls (like forwardings) are secure always */
1182 default:
1183 return ast_unreal_setoption(ast, option, data, datalen);
1184 }
1185}
int ast_unreal_setoption(struct ast_channel *chan, int option, void *data, int datalen)
Definition: core_unreal.c:97
#define AST_OPTION_SECURE_MEDIA
#define AST_OPTION_SECURE_SIGNALING

References AST_OPTION_SECURE_MEDIA, AST_OPTION_SECURE_SIGNALING, ast_unreal_setoption(), and ast_channel::data.

◆ local_shutdown()

static void local_shutdown ( void  )
static

Definition at line 1121 of file core_local.c.

1122{
1123 /* First, take us out of the channel loop */
1125 ast_manager_unregister("LocalOptimizeAway");
1127
1128 ao2_ref(locals, -1);
1129 locals = NULL;
1130
1133
1137}
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8041
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515

References ao2_cleanup, ao2_ref, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_local_bridge_type(), ast_local_optimization_begin_type(), ast_local_optimization_end_type(), ast_manager_unregister(), ast_channel_tech::capabilities, cli_local, local_tech, locals, NULL, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by ast_local_init().

◆ locals_cmp_cb()

static int locals_cmp_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 1111 of file core_local.c.

1112{
1113 return (obj == arg) ? CMP_MATCH : 0;
1114}
@ CMP_MATCH
Definition: astobj2.h:1027

References CMP_MATCH.

Referenced by ast_local_init().

◆ locals_show()

static char * locals_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI command "local show channels".

Definition at line 1031 of file core_local.c.

1032{
1033 struct local_pvt *p;
1034 struct ao2_iterator it;
1035
1036 switch (cmd) {
1037 case CLI_INIT:
1038 e->command = "local show channels";
1039 e->usage =
1040 "Usage: local show channels\n"
1041 " Provides summary information on active local proxy channels.\n";
1042 return NULL;
1043 case CLI_GENERATE:
1044 return NULL;
1045 }
1046
1047 if (a->argc != 3) {
1048 return CLI_SHOWUSAGE;
1049 }
1050
1051 if (ao2_container_count(locals) == 0) {
1052 ast_cli(a->fd, "No local channels in use\n");
1053 return RESULT_SUCCESS;
1054 }
1055
1056 it = ao2_iterator_init(locals, 0);
1057 while ((p = ao2_iterator_next(&it))) {
1058 ao2_lock(p);
1059 ast_cli(a->fd, "%s -- %s\n",
1060 p->base.owner ? ast_channel_name(p->base.owner) : "<unowned>",
1061 p->base.name);
1062 ao2_unlock(p);
1063 ao2_ref(p, -1);
1064 }
1066
1067 return CLI_SUCCESS;
1068}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
const char * ast_channel_name(const struct ast_channel *chan)
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_channel_name(), ast_cli(), local_pvt::base, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, locals, ast_unreal_pvt::name, NULL, ast_unreal_pvt::owner, RESULT_SUCCESS, and ast_cli_entry::usage.

◆ manager_optimize_away()

static int manager_optimize_away ( struct mansession s,
const struct message m 
)
static

Definition at line 1074 of file core_local.c.

1075{
1076 const char *channel;
1077 struct local_pvt *p;
1078 struct local_pvt *found;
1079 struct ast_channel *chan;
1080
1081 channel = astman_get_header(m, "Channel");
1082 if (ast_strlen_zero(channel)) {
1083 astman_send_error(s, m, "'Channel' not specified.");
1084 return 0;
1085 }
1086
1087 chan = ast_channel_get_by_name(channel);
1088 if (!chan) {
1089 astman_send_error(s, m, "Channel does not exist.");
1090 return 0;
1091 }
1092
1093 p = ast_channel_tech_pvt(chan);
1094 ast_channel_unref(chan);
1095
1096 found = p ? ao2_find(locals, p, 0) : NULL;
1097 if (found) {
1098 ao2_lock(found);
1100 ao2_unlock(found);
1101 ao2_ref(found, -1);
1102 astman_send_ack(s, m, "Queued channel to be optimized away");
1103 } else {
1104 astman_send_error(s, m, "Unable to find channel");
1105 }
1106
1107 return 0;
1108}
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3381
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3413
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3042
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_channel_get_by_name(), ast_channel_tech_pvt(), ast_channel_unref, ast_clear_flag, ast_strlen_zero(), AST_UNREAL_NO_OPTIMIZATION, astman_get_header(), astman_send_ack(), astman_send_error(), local_pvt::base, locals, and NULL.

Referenced by ast_local_init().

◆ publish_local_bridge_message()

static void publish_local_bridge_message ( struct local_pvt p)
static

Definition at line 542 of file core_local.c.

543{
544 RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup);
545 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
546 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
547 RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup);
548 RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup);
549 struct ast_channel *owner;
550 struct ast_channel *chan;
551
552 if (!ast_local_bridge_type()) {
553 return;
554 }
555
556 ast_unreal_lock_all(&p->base, &chan, &owner);
557
558 blob = ast_json_pack("{s: s, s: s, s: b}",
559 "context", p->context,
560 "exten", p->exten,
561 "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
562 if (!blob) {
563 goto end;
564 }
565
566 multi_blob = ast_multi_channel_blob_create(blob);
567 if (!multi_blob) {
568 goto end;
569 }
570
572 if (!one_snapshot) {
573 goto end;
574 }
575
577 if (!two_snapshot) {
578 goto end;
579 }
580
581 ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
582 ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot);
583
584 msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
585 if (!msg) {
586 goto end;
587 }
588
590
591end:
592 ast_channel_unlock(owner);
593 ast_channel_unref(owner);
594
595 ast_channel_unlock(chan);
596 ast_channel_unref(chan);
597
598 ao2_unlock(&p->base);
599}
char * end
Definition: eagi_proxy.c:73

References ao2_cleanup, ao2_unlock, ast_channel_snapshot_get_latest(), ast_channel_topic(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_json_pack(), ast_json_unref(), ast_local_bridge_type(), ast_multi_channel_blob_add_channel(), ast_multi_channel_blob_create(), ast_test_flag, ast_unreal_lock_all(), AST_UNREAL_NO_OPTIMIZATION, local_pvt::base, local_pvt::context, end, local_pvt::exten, NULL, RAII_VAR, stasis_message_create(), and stasis_publish().

Referenced by local_call().

◆ STASIS_MESSAGE_TYPE_DEFN() [1/3]

STASIS_MESSAGE_TYPE_DEFN ( ast_local_bridge_type  ,
to_ami = local_message_to_ami 
)

Define local channel message types.

◆ STASIS_MESSAGE_TYPE_DEFN() [2/3]

STASIS_MESSAGE_TYPE_DEFN ( ast_local_optimization_begin_type  ,
to_ami = local_message_to_ami 
)

◆ STASIS_MESSAGE_TYPE_DEFN() [3/3]

STASIS_MESSAGE_TYPE_DEFN ( ast_local_optimization_end_type  ,
to_ami = local_message_to_ami 
)

Variable Documentation

◆ cli_local

struct ast_cli_entry cli_local[]
static
Initial value:
= {
{ .handler = locals_show , .summary = "List status of local channels" ,},
}
static char * locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command "local show channels".
Definition: core_local.c:1031

Definition at line 1070 of file core_local.c.

Referenced by ast_local_init(), and local_shutdown().

◆ local_tech

struct ast_channel_tech local_tech
static

◆ local_unreal_callbacks

struct ast_unreal_pvt_callbacks local_unreal_callbacks
Initial value:
= {
.optimization_started = local_optimization_started_cb,
.optimization_finished = local_optimization_finished_cb,
}
static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct ast_channel *source, enum ast_unreal_channel_indicator dest, unsigned int id)
Callback for ast_unreal_pvt_callbacks optimization_started.
Definition: core_local.c:394
static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id)
Callback for ast_unreal_pvt_callbacks optimization_finished.
Definition: core_local.c:437

Callbacks from the unreal core when channel optimization occurs.

Definition at line 167 of file core_local.c.

Referenced by local_alloc().

◆ locals

struct ao2_container* locals
static

◆ tdesc

const char tdesc[] = "Local Proxy Channel Driver"
static

Definition at line 136 of file core_local.c.