37 #include "asterisk/stasis_channels.h"
45 static unsigned int name_sequence = 0;
65 if (!owner || !chan) {
67 ast_channel_lock(owner);
69 ast_channel_lock(chan);
78 if (p->
owner != owner || p->
chan != chan) {
80 ast_channel_unlock(owner);
84 ast_channel_unlock(chan);
112 ast_log(LOG_ERROR,
"The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
116 info_data = write_info->data;
117 if (!strcmp(write_info->function,
"CHANNEL")) {
118 if (!strncasecmp(info_data,
"hangup_handler_", 15)) {
124 if (!strcasecmp(info_data,
"accountcode")) {
125 info_data =
"peeraccount";
126 }
else if (!strcasecmp(info_data,
"peeraccount")) {
127 info_data =
"accountcode";
132 if (!(p = ast_channel_tech_pvt(ast))) {
136 ast_channel_unlock(ast);
141 if (!otherchan || otherchan == write_info->chan) {
145 goto setoption_cleanup;
152 ast_channel_lock(otherchan);
153 res = write_info->write_fn(otherchan, write_info->function, info_data, write_info->value);
154 ast_channel_unlock(otherchan);
161 ast_channel_lock(ast);
173 if (option != AST_OPTION_T38_STATE) {
179 if (!(p = ast_channel_tech_pvt(ast))) {
184 other = AST_UNREAL_IS_OUTBOUND(ast, p) ? p->
owner : p->
chan;
191 ast_channel_unlock(ast);
199 ast_channel_lock(ast);
227 && ast_channel_generator(us)
228 && ast_channel_generator(other)) {
235 if (us && us_locked) {
236 ast_channel_unlock(us);
246 if (us && us_locked) {
247 ast_channel_lock(us);
266 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
273 ast_log(LOG_WARNING,
"Huh? %s is being asked to answer?\n",
274 ast_channel_name(ast));
304 if (ast == p->
owner) {
306 }
else if (ast == p->
chan) {
355 if (got_optimized_out(ast, p)) {
381 if ((p->
owner != oldchan) && (p->
chan != oldchan)) {
382 ast_log(LOG_WARNING,
"Old channel %p wasn't %p or %p\n", oldchan, p->
owner, p->
chan);
386 if (p->
owner == oldchan) {
398 bridge_owner = ast_channel_internal_bridge(p->
owner);
399 bridge_chan = ast_channel_internal_bridge(p->
chan);
400 if (bridge_owner && bridge_owner == bridge_chan) {
401 ast_log(LOG_WARNING,
"You can not bridge an unreal channel (%s) to itself!\n",
402 ast_channel_name(newchan));
427 static int unreal_queue_indicate(
struct ast_unreal_pvt *p,
struct ast_channel *ast,
int condition,
const void *data,
size_t datalen)
441 .subclass.integer = condition,
442 .data.ptr = (
void *) data,
446 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
458 ast_debug(4,
"Blocked indication %d\n", condition);
485 unsigned char frame_data[1024];
488 .subclass.integer = condition,
489 .data.ptr = frame_data,
504 ast_channel_unlock(ast);
506 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
508 this_channel = p->
chan;
509 the_other_channel = p->
owner;
511 this_channel = p->
owner;
512 the_other_channel = p->
chan;
514 if (the_other_channel) {
517 ast_channel_connected(this_channel));
519 ast_channel_connected(this_channel), NULL);
522 ast_channel_redirecting(this_channel), NULL);
526 ast_channel_unlock(my_chan);
530 ast_channel_unlock(my_owner);
533 if (the_other_channel) {
537 ast_channel_lock(ast);
568 if (!this_channel_topology) {
573 if (!the_other_channel_topology) {
591 ast_channel_unlock(ast);
593 if (AST_UNREAL_IS_OUTBOUND(ast, p)) {
594 this_channel = p->
chan;
595 the_other_channel = p->
owner;
597 this_channel = p->
owner;
598 the_other_channel = p->
chan;
604 if (the_other_channel) {
609 ast_channel_unlock(my_chan);
613 ast_channel_unlock(my_owner);
617 ast_channel_lock(ast);
645 res = unreal_colp_redirect_indicate(p, ast, condition);
652 res = unreal_queue_indicate(p, ast, condition, data, datalen);
659 res = unreal_queue_indicate(p, ast, condition, data, datalen);
668 res = unreal_queue_indicate(p, ast, condition, data, datalen);
675 unreal_queue_indicate(p, ast, condition, data, datalen);
680 res = unreal_colp_stream_topology_request_change(p, ast, data);
691 ast_log(LOG_ERROR,
"Failed to allocate memory for stream.\n");
697 ast_log(LOG_ERROR,
"Failed to allocate memory for stream topology.\n");
713 ast_channel_unlock(ast);
730 ast_channel_lock(ast);
737 ast_channel_unlock(ast);
751 ast_channel_lock(ast);
761 ast_channel_unlock(owner);
766 ast_channel_unlock(chan);
771 res = unreal_queue_indicate(p, ast, condition, data, datalen);
792 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
814 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
837 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
838 f.
data.ptr = (
char *) text;
859 isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
861 f.
data.ptr = (
char *)data;
890 ast_channel_language_set(semi2, ast_channel_language(semi1));
891 ast_channel_musicclass_set(semi2, ast_channel_musicclass(semi1));
892 ast_channel_parkinglot_set(semi2, ast_channel_parkinglot(semi1));
895 ast_channel_accountcode_set(semi2, ast_channel_peeraccount(semi1));
896 ast_channel_peeraccount_set(semi2, ast_channel_accountcode(semi1));
904 if (ast_channel_hangupcause(semi1) == AST_CAUSE_ANSWERED_ELSEWHERE) {
905 ast_channel_hangupcause_set(semi2, AST_CAUSE_ANSWERED_ELSEWHERE);
916 clone_var = ast_var_assign(varptr->name, varptr->value);
920 ast_var_value(clone_var));
933 ast_callid bridge_callid;
937 bridge_callid = bridge->
callid;
942 p = ast_channel_tech_pvt(ast);
966 ast_callid chan_callid;
967 ast_callid owner_callid;
970 ast_channel_lock(chan);
972 chan_callid = ast_channel_callid(chan);
976 ast_channel_unlock(chan);
979 ast_channel_lock(owner);
981 owner_callid = ast_channel_callid(owner);
986 ast_channel_unlock(owner);
1020 int hangup_chan = 0;
1027 ast_channel_unlock(ast);
1032 if (ast != chan && ast != owner) {
1034 goto unreal_hangup_cleanup;
1037 cause = ast_channel_hangupcause(ast);
1039 if (ast == p->
chan) {
1047 ast_channel_hangupcause_set(p->
owner, cause);
1056 if (cause == AST_CAUSE_ANSWERED_ELSEWHERE) {
1057 ast_channel_hangupcause_set(p->
chan, AST_CAUSE_ANSWERED_ELSEWHERE);
1058 ast_debug(2,
"%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
1059 ast_channel_name(p->
chan));
1074 ast_channel_tech_pvt_set(ast, NULL);
1077 unreal_hangup_cleanup:
1080 ast_channel_unlock(owner);
1084 ast_channel_unlock(chan);
1092 ast_channel_lock(ast);
1101 ao2_cleanup(doomed->
reqcap);
1133 .resync_threshold = -1,
1138 unreal = ao2_alloc(size, destructor);
1176 if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
1177 id1.uniqueid = assignedids->uniqueid;
1178 id2.uniqueid = assignedids->uniqueid2;
1182 if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
1185 uniqueid2 =
ast_alloca(strlen(id1.uniqueid) + 3);
1186 strcpy(uniqueid2, id1.uniqueid);
1187 strcat(uniqueid2,
";2");
1188 id2.uniqueid = uniqueid2;
1195 if (!chan_topology) {
1220 exten, context, &id1, requestor, 0,
1221 "%s/%s-%08x;1", tech->type, p->
name, (
unsigned)generated_seqno);
1223 ast_log(LOG_WARNING,
"Unable to allocate owner channel structure\n");
1232 ast_channel_tech_set(owner, tech);
1234 ast_channel_tech_pvt_set(owner, p);
1236 ast_channel_nativeformats_set(owner, p->
reqcap);
1246 ast_channel_tech_pvt_set(owner, NULL);
1248 ast_channel_unlock(owner);
1253 ast_channel_set_writeformat(owner, fmt);
1254 ast_channel_set_rawwriteformat(owner, fmt);
1255 ast_channel_set_readformat(owner, fmt);
1256 ast_channel_set_rawreadformat(owner, fmt);
1264 ast_channel_tech_pvt_set(owner, NULL);
1266 ast_channel_tech_pvt_set(owner, NULL);
1267 ast_channel_unlock(owner);
1273 ast_channel_unlock(owner);
1276 exten, context, &id2, owner, 0,
1277 "%s/%s-%08x;2", tech->type, p->
name, (
unsigned)generated_seqno);
1279 ast_log(LOG_WARNING,
"Unable to allocate chan channel structure\n");
1280 ast_channel_tech_pvt_set(owner, NULL);
1282 ast_channel_tech_pvt_set(owner, NULL);
1291 ast_channel_tech_set(chan, tech);
1293 ast_channel_tech_pvt_set(chan, p);
1295 ast_channel_nativeformats_set(chan, p->
reqcap);
1302 ast_channel_set_writeformat(chan, fmt);
1303 ast_channel_set_rawwriteformat(chan, fmt);
1304 ast_channel_set_readformat(chan, fmt);
1305 ast_channel_set_rawreadformat(chan, fmt);
1310 ast_channel_unlock(chan);
int ast_unreal_hangup(struct ast_unreal_pvt *p, struct ast_channel *ast)
Hangup one end (maybe both ends) of an unreal channel derivative.
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Main Channel structure associated with a channel.
int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Build the connected line information data frame.
Asterisk main include file. File version handling, generic pbx functions.
int ast_unreal_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
struct ast_unreal_pvt * ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
Allocate the base unreal struct for a derivative.
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
Structure that contains features information.
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
char context[AST_MAX_CONTEXT]
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.
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
static int unreal_queue_frame(struct ast_unreal_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us, int us_locked)
queue a frame onto either the p->owner or p->chan
struct ast_channel * owner
#define AST_UNREAL_NO_OPTIMIZATION
struct ast_jb_conf jb_conf
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.
enum ast_control_t38 request_response
Structure to pass both assignedid values to channel drivers.
ast_channel_state
ast_channel states
int ast_unreal_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
#define AST_UNREAL_CARETAKER_THREAD
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...
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
struct ast_frame * ast_unreal_read(struct ast_channel *ast)
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
#define AST_UNREAL_MOH_INTERCEPT
const struct ast_channel_tech * tech
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
struct ast_stream_topology * chan_old_topology
struct ast_flags feature_flags
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
int ast_unreal_sendtext(struct ast_channel *ast, const char *text)
void ast_unreal_destructor(void *vdoomed)
struct ast_unreal_pvt destructor.
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)
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
General Asterisk PBX channel definitions.
int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int datalen)
int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
struct ast_stream * ast_channel_get_default_stream(struct ast_channel *chan, enum ast_media_type type)
Retrieve the default stream of a specific media type on a channel.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ast_debug(level,...)
Log a DEBUG message.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
struct ast_stream_topology * owner_old_topology
Core PBX routines and definitions.
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
struct ast_channel * chan
int ast_unreal_digit_begin(struct ast_channel *ast, char digit)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ast_format_cap * reqcap
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
Structure that contains information about a bridge.
int ast_bridge_unreal_optimize_out(struct ast_channel *chan, struct ast_channel *peer, struct ast_unreal_pvt *pvt)
Check and optimize out the unreal channels between bridges.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
struct ast_stream_topology * ast_channel_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Set the topology of streams on a channel.
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
Setup unreal owner and chan channels before initiating call.
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
Push the semi2 unreal channel into a bridge from either member of the unreal pair.
char name[AST_MAX_EXTENSION+AST_MAX_CONTEXT+2]
void(* ao2_destructor_fn)(void *vdoomed)
Typedef for an object destructor.
The base pvt structure for local channel derivatives.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Set when the stream is sending media only.
int ast_unreal_answer(struct ast_channel *ast)
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
union ast_frame::@224 data
#define AST_OPTION_CHANNEL_WRITE
Handle channel write data If a channel needs to process the data from a func_channel write operation ...
Structure to handle passing func_channel_write info to channels via setoption.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
#define ast_bridge_lock(bridge)
Lock the bridge.
struct ast_frame ast_null_frame
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
int ast_unreal_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
#define ast_channel_ref(c)
Increase channel reference count.
int ast_unreal_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
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.
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
void ast_connected_line_copy_to_caller(struct ast_party_caller *dest, const struct ast_party_connected_line *src)
Copy the connected line information to the caller information.
enum ast_frame_type frametype
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
int ast_channel_stream_topology_changed_externally(struct ast_channel *chan)
Provide notice from a channel that the topology has changed on it as a result of the remote party ren...
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ast_stream_topology * reqtopology
General jitterbuffer configuration.
Set when the stream is receiving media only.
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
char exten[AST_MAX_EXTENSION]
int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Build the redirecting id data frame.
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
void ast_party_dialed_copy(struct ast_party_dialed *dest, const struct ast_party_dialed *src)
Copy the source dialed party information to the destination dialed party.
Unreal channel derivative framework.