Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 209 of file core_local.c.

209 {
210 /* The ast_call() will run dialplan on the ;2 channel. */
212 /* The ast_call() will impart the ;2 channel into a bridge. */
214 /* The ast_call() will masquerade the ;2 channel into a channel. */
216};
@ LOCAL_CALL_ACTION_BRIDGE
Definition: core_local.c:213
@ LOCAL_CALL_ACTION_MASQUERADE
Definition: core_local.c:215
@ LOCAL_CALL_ACTION_DIALPLAN
Definition: core_local.c:211

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 288 of file core_local.c.

289{
290 struct local_pvt *p = ast_channel_tech_pvt(ast);
291 struct local_pvt *found;
292 struct ast_channel *peer;
293
294 if (!p) {
295 return NULL;
296 }
297
298 found = p ? ao2_find(locals, p, 0) : NULL;
299 if (!found) {
300 /* ast is either not a local channel or it has already been hungup */
301 return NULL;
302 }
303 ao2_lock(found);
304 if (ast == p->base.owner) {
305 peer = p->base.chan;
306 } else if (ast == p->base.chan) {
307 peer = p->base.owner;
308 } else {
309 peer = NULL;
310 }
311 if (peer) {
312 ast_channel_ref(peer);
313 }
314 ao2_unlock(found);
315 ao2_ref(found, -1);
316 return peer;
317}
#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:2997
static struct ao2_container * locals
Definition: core_local.c:150
#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:235
struct ast_unreal_pvt base
Definition: core_local.c:237

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 1151 of file core_local.c.

1152{
1154 return -1;
1155 }
1156
1158 return -1;
1159 }
1160
1162 return -1;
1163 }
1164
1166 return -1;
1167 }
1169
1171 if (!locals) {
1172 return -1;
1173 }
1174
1175 /* Make sure we can register our channel type */
1177 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
1178
1179 return -1;
1180 }
1183
1185 return 0;
1186}
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:538
#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:1086
static int locals_cmp_cb(void *obj, void *arg, int flags)
Definition: core_local.c:1123
static struct ast_channel_tech local_tech
Definition: core_local.c:185
static struct ast_cli_entry cli_local[]
Definition: core_local.c:1082
static void local_shutdown(void)
Definition: core_local.c:1133
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:203
#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:652
#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 253 of file core_local.c.

255{
256 struct local_pvt *p = ast_channel_tech_pvt(chan);
257
258 *tech_pvt = NULL;
259 *base_chan = NULL;
260 *base_owner = NULL;
261
262 if (p) {
263 *tech_pvt = ao2_bump(p);
264 ast_unreal_lock_all(&p->base, base_chan, base_owner);
265 }
266}
#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 613 of file core_local.c.

614{
615 struct local_pvt *p;
616 struct local_pvt *found;
617 int res = -1;
618
619 /* Sanity checks. */
620 if (!ast || !bridge) {
622 return -1;
623 }
624
625 ast_channel_lock(ast);
626 p = ast_channel_tech_pvt(ast);
628
629 found = p ? ao2_find(locals, p, 0) : NULL;
630 if (found) {
631 ao2_lock(found);
632 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
633 && found->base.owner
634 && found->base.chan
636 ao2_ref(bridge, +1);
637 if (swap) {
638 ast_channel_ref(swap);
639 }
641 found->action.bridge.join = bridge;
642 found->action.bridge.swap = swap;
643 found->action.bridge.features = features;
644 res = 0;
645 } else {
647 }
648 ao2_unlock(found);
649 ao2_ref(found, -1);
650 }
651
652 return res;
653}
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3743
#define ast_channel_lock(chan)
Definition: channel.h:2972
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
struct ast_channel * swap
Definition: core_local.c:223
struct ast_bridge * join
Definition: core_local.c:221
struct ast_bridge_features * features
Definition: core_local.c:225
struct local_bridge bridge
Definition: core_local.c:241
union local_pvt::@341 action
enum local_call_action type
Definition: core_local.c:246
#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 655 of file core_local.c.

656{
657 struct local_pvt *p;
658 struct local_pvt *found;
659 int res = -1;
660
661 /* Sanity checks. */
662 if (!ast || !masq) {
663 return -1;
664 }
665
666 ast_channel_lock(ast);
667 p = ast_channel_tech_pvt(ast);
669
670 found = p ? ao2_find(locals, p, 0) : NULL;
671 if (found) {
672 ao2_lock(found);
673 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
674 && found->base.owner
675 && found->base.chan
679 found->action.masq = masq;
680 res = 0;
681 }
682 ao2_unlock(found);
683 ao2_ref(found, -1);
684 }
685
686 return res;
687}
struct ast_channel * masq
Definition: core_local.c:243

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 268 of file core_local.c.

270{
271 if (base_chan) {
272 ast_channel_unlock(base_chan);
273 ast_channel_unref(base_chan);
274 }
275
276 if (base_owner) {
277 ast_channel_unlock(base_owner);
278 ast_channel_unref(base_owner);
279 }
280
281 if (tech_pvt) {
282 struct local_pvt *p = tech_pvt;
283 ao2_unlock(&p->base);
284 ao2_ref(tech_pvt, -1);
285 }
286}
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008

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 878 of file core_local.c.

879{
880 struct local_pvt *pvt;
881 char *parse;
882 char *context;
883 char *opts;
884
885 pvt = (struct local_pvt *) ast_unreal_alloc_stream_topology(sizeof(*pvt), local_pvt_destructor, topology);
886 if (!pvt) {
887 return NULL;
888 }
890
891 parse = ast_strdupa(data);
892
893 /*
894 * Local channels intercept MOH by default.
895 *
896 * This is a silly default because it represents state held by
897 * the local channels. Unless local channel optimization is
898 * disabled, the state will disappear when the local channels
899 * optimize out.
900 */
902
903 /* Look for options.
904 * Slashes can appear in channel names, so options are after the last match. */
905 if ((opts = strrchr(parse, '/'))) {
906 *opts++ = '\0';
907 if (strchr(opts, 'n')) {
909 }
910 if (strchr(opts, 'j')) {
913 } else {
914 ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
915 }
916 }
917 if (strchr(opts, 'm')) {
919 }
920 }
921
922 /* Look for a context */
923 if ((context = strchr(parse, '@'))) {
924 *context++ = '\0';
925 }
926
927 ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
928 ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
929 snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);
930
931 return pvt; /* this is returned with a ref */
932}
@ 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:858
struct ast_unreal_pvt_callbacks local_unreal_callbacks
Callbacks from the unreal core when channel optimization occurs.
Definition: core_local.c:179
#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:250
char context[AST_MAX_CONTEXT]
Definition: core_local.c:248
#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 691 of file core_local.c.

692{
693 struct local_pvt *p = ast_channel_tech_pvt(ast);
694 int pvt_locked = 0;
695
696 struct ast_channel *owner = NULL;
697 struct ast_channel *chan = NULL;
698 int res;
699 char *reduced_dest = ast_strdupa(dest);
700 char *slash;
701 const char *chan_cid;
702
703 if (!p) {
704 return -1;
705 }
706
707 /* since we are letting go of channel locks that were locked coming into
708 * this function, then we need to give the tech pvt a ref */
709 ao2_ref(p, 1);
711
712 ast_unreal_lock_all(&p->base, &chan, &owner);
713 pvt_locked = 1;
714
715 if (owner != ast) {
716 res = -1;
717 goto return_cleanup;
718 }
719
720 if (!owner || !chan) {
721 res = -1;
722 goto return_cleanup;
723 }
724
725 ast_unreal_call_setup(owner, chan);
726
727 /*
728 * If the local channel has /n on the end of it, we need to lop
729 * that off for our argument to setting up the CC_INTERFACES
730 * variable.
731 */
732 if ((slash = strrchr(reduced_dest, '/'))) {
733 *slash = '\0';
734 }
735 ast_set_cc_interfaces_chanvar(chan, reduced_dest);
736
737 ao2_unlock(p);
738 pvt_locked = 0;
739
740 ast_channel_unlock(owner);
741
742 chan_cid = S_COR(ast_channel_caller(chan)->id.number.valid,
743 ast_channel_caller(chan)->id.number.str, NULL);
744 if (chan_cid) {
745 chan_cid = ast_strdupa(chan_cid);
746 }
747 ast_channel_unlock(chan);
748
749 res = -1;
750 switch (p->type) {
752 if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
753 ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
754 p->exten, p->context);
755 } else {
757
758 /* Start switch on sub channel */
759 res = ast_pbx_start(chan);
760 }
761 break;
764 ast_answer(chan);
767 ao2_ref(p->action.bridge.join, -1);
768 p->action.bridge.join = NULL;
770 p->action.bridge.swap = NULL;
772 break;
775 ast_answer(chan);
776 res = ast_channel_move(p->action.masq, chan);
777 if (!res) {
778 /* Chan is now an orphaned zombie. Destroy it. */
779 ast_hangup(chan);
780 }
782 break;
783 }
784 if (!res) {
785 ao2_lock(p);
787 ao2_unlock(p);
788 }
789
790 /* we already unlocked them, clear them here so the cleanup label won't touch them. */
791 owner = ast_channel_unref(owner);
792 chan = ast_channel_unref(chan);
793
794return_cleanup:
795 if (p) {
796 if (pvt_locked) {
797 ao2_unlock(p);
798 }
799 ao2_ref(p, -1);
800 }
801 if (chan) {
802 ast_channel_unlock(chan);
803 ast_channel_unref(chan);
804 }
805
806 /*
807 * owner is supposed to be == to ast, if it is, don't unlock it
808 * because ast must exit locked
809 */
810 if (owner) {
811 if (owner != ast) {
812 ast_channel_unlock(owner);
813 ast_channel_lock(ast);
814 }
815 ast_channel_unref(owner);
816 } else {
817 /* we have to exit with ast locked */
818 ast_channel_lock(ast);
819 }
820
821 return res;
822}
#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:1947
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:594
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:3639
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2510
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:10671
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
static void publish_local_bridge_message(struct local_pvt *p)
Definition: core_local.c:554
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:4190
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4723
#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:157

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 378 of file core_local.c.

380{
381 struct ast_multi_channel_blob *payload;
382 RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
383 RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
384
386 if (!local_one_snapshot) {
387 return NULL;
388 }
389
391 if (!local_two_snapshot) {
392 return NULL;
393 }
394
395 payload = ast_multi_channel_blob_create(json_object);
396 if (!payload) {
397 return NULL;
398 }
399 ast_multi_channel_blob_add_channel(payload, "1", local_one_snapshot);
400 ast_multi_channel_blob_add_channel(payload, "2", local_two_snapshot);
401
402 return payload;
403}
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 320 of file core_local.c.

321{
322 int is_inuse = 0;
323 int res = AST_DEVICE_INVALID;
324 char *exten = ast_strdupa(data);
325 char *context;
326 char *opts;
327 struct local_pvt *lp;
328 struct ao2_iterator it;
329
330 context = strchr(exten, '@');
331 if (!context) {
333 "Someone used Local/%s somewhere without a @context. This is bad.\n", data);
334 return AST_DEVICE_INVALID;
335 }
336 *context++ = '\0';
337
338 /* Strip options if they exist.
339 * However, don't strip '/' before an '@' (exten could contain slashes).
340 * So only start looking for '/' in context, because options would be past
341 * this point if they exist, but anything before would be a '/' in the exten,
342 * not options. */
343 opts = strchr(context, '/');
344 if (opts) {
345 *opts = '\0';
346 }
347
348 it = ao2_iterator_init(locals, 0);
349 for (; (lp = ao2_iterator_next(&it)); ao2_ref(lp, -1)) {
350 ao2_lock(lp);
351 if (!strcmp(exten, lp->exten)
352 && !strcmp(context, lp->context)) {
354 if (lp->base.owner
356 is_inuse = 1;
357 }
358 }
359 ao2_unlock(lp);
360 if (is_inuse) {
361 res = AST_DEVICE_INUSE;
362 ao2_ref(lp, -1);
363 break;
364 }
365 }
367
368 if (res == AST_DEVICE_INVALID) {
369 ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
370 if (ast_exists_extension(NULL, context, exten, 1, NULL)) {
372 }
373 }
374
375 return res;
376}
#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 825 of file core_local.c.

826{
827 struct local_pvt *p = ast_channel_tech_pvt(ast);
828 int res;
829
830 if (!p) {
831 return -1;
832 }
833
834 /* give the pvt a ref to fulfill calling requirements. */
835 ao2_ref(p, +1);
836 res = ast_unreal_hangup(&p->base, ast);
837 if (!res) {
838 int unlink;
839
840 ao2_lock(p);
841 unlink = !p->base.owner && !p->base.chan;
842 ao2_unlock(p);
843 if (unlink) {
844 ao2_unlink(locals, p);
845 }
846 }
847 ao2_ref(p, -1);
848
849 return res;
850}
#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 479 of file core_local.c.

480{
482 struct ast_json *blob = ast_multi_channel_blob_get_json(obj);
483 struct ast_channel_snapshot *local_snapshot_one;
484 struct ast_channel_snapshot *local_snapshot_two;
485 RAII_VAR(struct ast_str *, local_channel_one, NULL, ast_free);
486 RAII_VAR(struct ast_str *, local_channel_two, NULL, ast_free);
487 RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free);
488 const char *event;
489
490 local_snapshot_one = ast_multi_channel_blob_get_channel(obj, "1");
491 local_snapshot_two = ast_multi_channel_blob_get_channel(obj, "2");
492 if (!local_snapshot_one || !local_snapshot_two) {
493 return NULL;
494 }
495
496 event_buffer = ast_str_create(1024);
497 local_channel_one = ast_manager_build_channel_state_string_prefix(local_snapshot_one, "LocalOne");
498 local_channel_two = ast_manager_build_channel_state_string_prefix(local_snapshot_two, "LocalTwo");
499 if (!event_buffer || !local_channel_one || !local_channel_two) {
500 return NULL;
501 }
502
504 struct ast_channel_snapshot *source_snapshot;
505 RAII_VAR(struct ast_str *, source_str, NULL, ast_free);
506 const char *dest_uniqueid;
507
508 source_snapshot = ast_multi_channel_blob_get_channel(obj, "source");
509 if (source_snapshot) {
510 source_str = ast_manager_build_channel_state_string_prefix(source_snapshot, "Source");
511 if (!source_str) {
512 return NULL;
513 }
514 }
515
516 dest_uniqueid = ast_json_object_get(blob, "dest") == AST_UNREAL_OWNER ?
517 local_snapshot_one->base->uniqueid : local_snapshot_two->base->uniqueid;
518
519 event = "LocalOptimizationBegin";
520 if (source_str) {
521 ast_str_append(&event_buffer, 0, "%s", ast_str_buffer(source_str));
522 }
523 ast_str_append(&event_buffer, 0, "DestUniqueId: %s\r\n", dest_uniqueid);
524 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
526 event = "LocalOptimizationEnd";
527 ast_str_append(&event_buffer, 0, "Success: %s\r\n", ast_json_integer_get(ast_json_object_get(blob, "success")) ? "Yes" : "No");
528 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
530 event = "LocalBridge";
531 ast_str_append(&event_buffer, 0, "Context: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "context")));
532 ast_str_append(&event_buffer, 0, "Exten: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "exten")));
533 ast_str_append(&event_buffer, 0, "LocalOptimization: %s\r\n", ast_json_is_true(ast_json_object_get(blob, "can_optimize")) ? "Yes" : "No");
534 } else {
535 return NULL;
536 }
537
539 "%s"
540 "%s"
541 "%s",
542 ast_str_buffer(local_channel_one),
543 ast_str_buffer(local_channel_two),
544 ast_str_buffer(event_buffer));
545}
#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:10237
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 449 of file core_local.c.

450{
451 RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
452 RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
453 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
454 struct local_pvt *p = (struct local_pvt *)base;
455
457 return;
458 }
459
460 json_object = ast_json_pack("{s: i, s: I}", "success", success, "id", (ast_json_int_t)id);
461
462 if (!json_object) {
463 return;
464 }
465
466 payload = local_channel_optimization_blob(p, json_object);
467 if (!payload) {
468 return;
469 }
470
472 if (!msg) {
473 return;
474 }
475
477}
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:378
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:1538

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 406 of file core_local.c.

408{
409 RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
410 RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
411 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
412 struct local_pvt *p = (struct local_pvt *)base;
413
415 return;
416 }
417
418 json_object = ast_json_pack("{s: i, s: I}",
419 "dest", dest, "id", (ast_json_int_t)id);
420
421 if (!json_object) {
422 return;
423 }
424
425 payload = local_channel_optimization_blob(p, json_object);
426 if (!payload) {
427 return;
428 }
429
430 if (source) {
431 RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup);
432 source_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(source));
433 if (!source_snapshot) {
434 return;
435 }
436
437 ast_multi_channel_blob_add_channel(payload, "source", source_snapshot);
438 }
439
441 if (!msg) {
442 return;
443 }
444
446}

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 858 of file core_local.c.

859{
860 struct local_pvt *doomed = vdoomed;
861
862 switch (doomed->type) {
864 break;
866 ao2_cleanup(doomed->action.bridge.join);
867 ao2_cleanup(doomed->action.bridge.swap);
869 break;
871 ao2_cleanup(doomed->action.masq);
872 break;
873 }
874 ast_unreal_destructor(&doomed->base);
875}
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 935 of file core_local.c.

936{
937 struct ast_stream_topology *topology;
938 struct ast_channel *chan;
939
941 if (!topology) {
942 return NULL;
943 }
944
945 chan = local_request_with_stream_topology(type, topology, assignedids, requestor, data, cause);
946
947 ast_stream_topology_free(topology);
948
949 return chan;
950}
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:953
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:746
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:851
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 953 of file core_local.c.

954{
955 struct ast_stream_topology *audio_filtered_topology;
956 int i;
957 struct local_pvt *p;
958 struct ast_channel *chan;
960
961 /* Create a copy of the requested topology as we don't have ownership over
962 * the one that is passed in.
963 */
964 audio_filtered_topology = ast_stream_topology_clone(topology);
965 if (!audio_filtered_topology) {
966 return NULL;
967 }
968
969 /* Some users of Local channels request every known format in the
970 * universe. The core itself automatically pruned this list down to a single
971 * "best" format for audio in non-multistream. We replicate the logic here to
972 * do the same thing.
973 */
974 for (i = 0; i < ast_stream_topology_get_count(audio_filtered_topology); ++i) {
975 struct ast_stream *stream;
976 int res;
977 struct ast_format *tmp_fmt = NULL;
978 struct ast_format *best_audio_fmt = NULL;
979 struct ast_format_cap *caps;
980
981 stream = ast_stream_topology_get_stream(audio_filtered_topology, i);
982
985 continue;
986 }
987
988 /* Respect the immutable state of formats on the stream and create a new
989 * format capabilities to replace the existing one.
990 */
992 if (!caps) {
993 ao2_ref(audio_filtered_topology, -1);
994 return NULL;
995 }
996
997 /* The ast_translator_best_choice function treats both caps as const
998 * but does not declare it in the API.
999 */
1001 &tmp_fmt, &best_audio_fmt);
1002 if (res < 0) {
1003 struct ast_str *tech_codecs = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1004 struct ast_str *request_codecs = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1005
1006 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type,
1008 ast_format_cap_get_names(ast_stream_get_formats(stream), &request_codecs));
1009
1010 /* If there are no formats then we abort */
1011 ao2_ref(caps, -1);
1012 ao2_ref(audio_filtered_topology, -1);
1013 return NULL;
1014 }
1015
1016 ast_format_cap_append(caps, best_audio_fmt, 0);
1017 ast_stream_set_formats(stream, caps);
1018
1019 ao2_ref(caps, -1);
1020 ao2_ref(tmp_fmt, -1);
1021 ao2_ref(best_audio_fmt, -1);
1022 }
1023
1024 /* Allocate a new private structure and then Asterisk channels */
1025 p = local_alloc(data, audio_filtered_topology);
1026 ao2_ref(audio_filtered_topology, -1);
1027 if (!p) {
1028 return NULL;
1029 }
1032 p->exten, p->context, assignedids, requestor, callid);
1033 if (chan) {
1034 ao2_link(locals, p);
1035 }
1036 ao2_ref(p, -1); /* kill the ref from the alloc */
1037
1038 return chan;
1039}
#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:878
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:2273
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:791
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:768
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:670
#define ast_str_alloca(init_len)
Definition: strings.h:848
ast_callid callid
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 1188 of file core_local.c.

1189{
1190 switch (option) {
1193 return 0; /* local calls (like forwardings) are secure always */
1194 default:
1195 return ast_unreal_setoption(ast, option, data, datalen);
1196 }
1197}
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 1133 of file core_local.c.

1134{
1135 /* First, take us out of the channel loop */
1137 ast_manager_unregister("LocalOptimizeAway");
1139
1140 ao2_ref(locals, -1);
1141 locals = NULL;
1142
1145
1149}
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:569
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:7697
#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 1123 of file core_local.c.

1124{
1125 return (obj == arg) ? CMP_MATCH : 0;
1126}
@ 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 1043 of file core_local.c.

1044{
1045 struct local_pvt *p;
1046 struct ao2_iterator it;
1047
1048 switch (cmd) {
1049 case CLI_INIT:
1050 e->command = "local show channels";
1051 e->usage =
1052 "Usage: local show channels\n"
1053 " Provides summary information on active local proxy channels.\n";
1054 return NULL;
1055 case CLI_GENERATE:
1056 return NULL;
1057 }
1058
1059 if (a->argc != 3) {
1060 return CLI_SHOWUSAGE;
1061 }
1062
1063 if (ao2_container_count(locals) == 0) {
1064 ast_cli(a->fd, "No local channels in use\n");
1065 return RESULT_SUCCESS;
1066 }
1067
1068 it = ao2_iterator_init(locals, 0);
1069 while ((p = ao2_iterator_next(&it))) {
1070 ao2_lock(p);
1071 ast_cli(a->fd, "%s -- %s\n",
1072 p->base.owner ? ast_channel_name(p->base.owner) : "<unowned>",
1073 p->base.name);
1074 ao2_unlock(p);
1075 ao2_ref(p, -1);
1076 }
1078
1079 return CLI_SUCCESS;
1080}
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 1086 of file core_local.c.

1087{
1088 const char *channel;
1089 struct local_pvt *p;
1090 struct local_pvt *found;
1091 struct ast_channel *chan;
1092
1093 channel = astman_get_header(m, "Channel");
1094 if (ast_strlen_zero(channel)) {
1095 astman_send_error(s, m, "'Channel' not specified.");
1096 return 0;
1097 }
1098
1099 chan = ast_channel_get_by_name(channel);
1100 if (!chan) {
1101 astman_send_error(s, m, "Channel does not exist.");
1102 return 0;
1103 }
1104
1105 p = ast_channel_tech_pvt(chan);
1106 ast_channel_unref(chan);
1107
1108 found = p ? ao2_find(locals, p, 0) : NULL;
1109 if (found) {
1110 ao2_lock(found);
1112 ao2_unlock(found);
1113 ao2_ref(found, -1);
1114 astman_send_ack(s, m, "Queued channel to be optimized away");
1115 } else {
1116 astman_send_error(s, m, "Unable to find channel");
1117 }
1118
1119 return 0;
1120}
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1397
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
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 554 of file core_local.c.

555{
556 RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup);
557 RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
558 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
559 RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup);
560 RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup);
561 struct ast_channel *owner;
562 struct ast_channel *chan;
563
564 if (!ast_local_bridge_type()) {
565 return;
566 }
567
568 ast_unreal_lock_all(&p->base, &chan, &owner);
569
570 blob = ast_json_pack("{s: s, s: s, s: b}",
571 "context", p->context,
572 "exten", p->exten,
573 "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
574 if (!blob) {
575 goto end;
576 }
577
578 multi_blob = ast_multi_channel_blob_create(blob);
579 if (!multi_blob) {
580 goto end;
581 }
582
584 if (!one_snapshot) {
585 goto end;
586 }
587
589 if (!two_snapshot) {
590 goto end;
591 }
592
593 ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
594 ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot);
595
596 msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
597 if (!msg) {
598 goto end;
599 }
600
602
603end:
604 ast_channel_unlock(owner);
605 ast_channel_unref(owner);
606
607 ast_channel_unlock(chan);
608 ast_channel_unref(chan);
609
610 ao2_unlock(&p->base);
611}
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:1043

Definition at line 1082 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:406
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:449

Callbacks from the unreal core when channel optimization occurs.

Definition at line 179 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 148 of file core_local.c.