Asterisk - The Open Source Telephony Project  18.5.0
Functions | Variables
core_unreal.c File Reference

Unreal channel derivatives framework for channel drivers like local channels. More...

#include "asterisk.h"
#include "asterisk/causes.h"
#include "asterisk/channel.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/pbx.h"
#include "asterisk/musiconhold.h"
#include "asterisk/astobj2.h"
#include "asterisk/bridge.h"
#include "asterisk/core_unreal.h"
#include "asterisk/stream.h"
Include dependency graph for core_unreal.c:

Go to the source code of this file.

Functions

struct ast_unreal_pvtast_unreal_alloc (size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
 Allocate the base unreal struct for a derivative. More...
 
struct ast_unreal_pvtast_unreal_alloc_stream_topology (size_t size, ao2_destructor_fn destructor, struct ast_stream_topology *topology)
 Allocate the base unreal struct for a derivative. More...
 
int ast_unreal_answer (struct ast_channel *ast)
 
void ast_unreal_call_setup (struct ast_channel *semi1, struct ast_channel *semi2)
 Setup unreal owner and chan channels before initiating call. More...
 
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. More...
 
void ast_unreal_destructor (void *vdoomed)
 struct ast_unreal_pvt destructor. More...
 
int ast_unreal_digit_begin (struct ast_channel *ast, char digit)
 
int ast_unreal_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
int ast_unreal_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
int ast_unreal_hangup (struct ast_unreal_pvt *p, struct ast_channel *ast)
 Hangup one end (maybe both ends) of an unreal channel derivative. More...
 
int ast_unreal_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
 
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. More...
 
struct ast_channelast_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. More...
 
int ast_unreal_queryoption (struct ast_channel *ast, int option, void *data, int *datalen)
 
struct ast_frameast_unreal_read (struct ast_channel *ast)
 
int ast_unreal_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen)
 
int ast_unreal_sendtext (struct ast_channel *ast, const char *text)
 
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)
 
int ast_unreal_write_stream (struct ast_channel *ast, int stream_num, struct ast_frame *f)
 
static int got_optimized_out (struct ast_channel *ast, struct ast_unreal_pvt *p)
 
static int unreal_colp_redirect_indicate (struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
 
static int unreal_colp_stream_topology_request_change (struct ast_unreal_pvt *p, struct ast_channel *ast, const struct ast_stream_topology *topology)
 
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 More...
 
static int unreal_queue_indicate (struct ast_unreal_pvt *p, struct ast_channel *ast, int condition, const void *data, size_t datalen)
 

Variables

static unsigned int name_sequence = 0
 

Detailed Description

Unreal channel derivatives framework for channel drivers like local channels.

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

See Also:

Definition in file core_unreal.c.

Function Documentation

◆ ast_unreal_alloc()

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.

Since
12.0.0
Parameters
sizeSize of the unreal struct to allocate.
destructorDestructor callback.
capFormat capabilities to give the unreal private struct.
Return values
pvton success.
NULLon error.

Definition at line 1111 of file core_unreal.c.

References ast_stream_topology_create_from_format_cap(), ast_stream_topology_free(), ast_unreal_alloc_stream_topology(), and NULL.

Referenced by announce_request(), and media_request_helper().

1112 {
1113  struct ast_stream_topology *topology;
1114  struct ast_unreal_pvt *unreal;
1115 
1117  if (!topology) {
1118  return NULL;
1119  }
1120 
1121  unreal = ast_unreal_alloc_stream_topology(size, destructor, topology);
1122 
1123  ast_stream_topology_free(topology);
1124 
1125  return unreal;
1126 }
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:1128
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
#define NULL
Definition: resample.c:96
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743

◆ ast_unreal_alloc_stream_topology()

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.

Since
16.12.0
17.6.0
Parameters
sizeSize of the unreal struct to allocate.
destructorDestructor callback.
capFormat capabilities to give the unreal private struct.
Return values
pvton success.
NULLon error.

Definition at line 1128 of file core_unreal.c.

References ao2_alloc, ao2_ref, ast_stream_topology_clone(), ast_stream_topology_get_formats(), ast_jb_conf::flags, ast_unreal_pvt::jb_conf, NULL, ast_unreal_pvt::reqcap, and ast_unreal_pvt::reqtopology.

Referenced by ast_unreal_alloc(), and local_alloc().

1129 {
1130  struct ast_unreal_pvt *unreal;
1131 
1132  static const struct ast_jb_conf jb_conf = {
1133  .flags = 0,
1134  .max_size = -1,
1135  .resync_threshold = -1,
1136  .impl = "",
1137  .target_extra = -1,
1138  };
1139 
1140  unreal = ao2_alloc(size, destructor);
1141  if (!unreal) {
1142  return NULL;
1143  }
1144 
1145  unreal->reqtopology = ast_stream_topology_clone(topology);
1146  if (!unreal->reqtopology) {
1147  ao2_ref(unreal, -1);
1148  return NULL;
1149  }
1150 
1151  unreal->reqcap = ast_stream_topology_get_formats(topology);
1152  if (!unreal->reqcap) {
1153  ao2_ref(unreal, -1);
1154  return NULL;
1155  }
1156 
1157  memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
1158 
1159  return unreal;
1160 }
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
Definition: stream.c:930
struct ast_jb_conf jb_conf
Definition: core_unreal.h:96
#define NULL
Definition: resample.c:96
long resync_threshold
Definition: jitterbuf.h:68
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
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
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100
General jitterbuffer configuration.
Definition: abstract_jb.h:69

◆ ast_unreal_answer()

int ast_unreal_answer ( struct ast_channel ast)

Unreal channel framework struct ast_channel_tech.answer callback

Definition at line 254 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log, AST_UNREAL_IS_OUTBOUND, LOG_WARNING, and unreal_queue_frame().

255 {
256  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
257  int isoutbound;
258  int res = -1;
259 
260  if (!p) {
261  return -1;
262  }
263 
264  ao2_ref(p, 1);
265  ao2_lock(p);
266  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
267  if (isoutbound) {
268  /* Pass along answer since somebody answered us */
270 
271  res = unreal_queue_frame(p, isoutbound, &answer, ast, 1);
272  } else {
273  ast_log(LOG_WARNING, "Huh? %s is being asked to answer?\n",
274  ast_channel_name(ast));
275  }
276  ao2_unlock(p);
277  ao2_ref(p, -1);
278  return res;
279 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
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
Definition: core_unreal.c:213
#define LOG_WARNING
Definition: logger.h:274
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
static int answer(void *data)
Definition: chan_pjsip.c:682
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
const char * ast_channel_name(const struct ast_channel *chan)
Data structure associated with a single frame of data.

◆ ast_unreal_call_setup()

void ast_unreal_call_setup ( struct ast_channel semi1,
struct ast_channel semi2 
)

Setup unreal owner and chan channels before initiating call.

Since
12.0.0
Parameters
semi1Owner channel of unreal channel pair.
semi2Outgoing channel of unreal channel pair.
Note
On entry, the semi1 and semi2 channels are already locked.
Returns
Nothing

Definition at line 870 of file core_unreal.c.

References AST_CAUSE_ANSWERED_ELSEWHERE, ast_channel_accountcode(), ast_channel_caller(), ast_channel_cc_params_init(), ast_channel_connected(), ast_channel_datastore_inherit(), ast_channel_dialed(), ast_channel_get_cc_config_params(), ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_language(), ast_channel_musicclass(), ast_channel_parkinglot(), ast_channel_peeraccount(), ast_channel_publish_varset(), ast_channel_redirecting(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_varshead(), ast_connected_line_copy_from_caller(), ast_connected_line_copy_to_caller(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_party_dialed_copy(), ast_party_redirecting_copy(), ast_var_assign, ast_var_full_name(), ast_var_value(), ast_var_t::entries, ast_var_t::name, and ast_var_t::value.

Referenced by local_call().

871 {
872  struct ast_var_t *varptr;
873  struct ast_var_t *clone_var;
874 
876 
877  /*
878  * Note that cid_num and cid_name aren't passed in the
879  * ast_channel_alloc calls in ast_unreal_new_channels(). It's
880  * done here instead.
881  */
883 
885 
886  /* Crossover the CallerID and conected-line to cross the unreal bridge. */
889 
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));
893 
894  /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
895  ast_channel_accountcode_set(semi2, ast_channel_peeraccount(semi1));
896  ast_channel_peeraccount_set(semi2, ast_channel_accountcode(semi1));
897 
899 
900  /*
901  * Make sure we inherit the AST_CAUSE_ANSWERED_ELSEWHERE if it's
902  * set on the queue/dial call request in the dialplan.
903  */
906  }
907 
908  /*
909  * Copy the channel variables from the semi1 channel to the
910  * outgoing channel.
911  *
912  * Note that due to certain assumptions, they MUST be in the
913  * same order.
914  */
916  clone_var = ast_var_assign(varptr->name, varptr->value);
917  if (clone_var) {
920  ast_var_value(clone_var));
921  }
922  }
923  ast_channel_datastore_inherit(semi1, semi2);
924 
926 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10675
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2373
const char * ast_channel_accountcode(const struct ast_channel *chan)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:113
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.
Definition: channel.c:10652
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
char name[0]
Definition: chanvars.h:31
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_varset for a channel.
char * value
Definition: chanvars.h:30
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
const char * ast_channel_peeraccount(const struct ast_channel *chan)
const char * ast_var_full_name(const struct ast_var_t *var)
Definition: chanvars.c:75
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_var_t::@249 entries
#define ast_var_assign(name, value)
Definition: chanvars.h:40
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_channel_hangupcause(const struct ast_channel *chan)
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.
Definition: channel.c:8389
const char * ast_channel_language(const struct ast_channel *chan)
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.
Definition: channel.c:8396
const char * ast_channel_parkinglot(const struct ast_channel *chan)
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.
Definition: channel.c:2135
const char * ast_channel_musicclass(const struct ast_channel *chan)
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.
Definition: channel.c:1936

◆ ast_unreal_channel_push_to_bridge()

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.

Since
12.0.0
Parameters
astA member of the unreal channel being pushed
bridgeWhich bridge we want to push the channel to
flagsFeature flags to be set on the bridge channel.
Return values
0if the channel is successfully imparted onto the bridge
-1on failure
Note
This is equivalent to ast_call() on unreal based channel drivers that are designed to use it instead.

Definition at line 928 of file core_unreal.c.

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_features_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_bridge_lock, ast_bridge_unlock, ast_channel_callid(), ast_channel_callid_set(), ast_channel_lock, ast_channel_ref, ast_channel_tech_pvt(), ast_channel_unlock, ast_channel_unref, ast_set_flag, AST_UNREAL_CARETAKER_THREAD, ast_bridge::callid, ast_bridge_features::feature_flags, lock, NULL, RAII_VAR, SCOPED_AO2LOCK, and SCOPED_CHANNELLOCK.

Referenced by ari_bridges_play_new(), ast_ari_bridges_record(), and bridge_moh_create().

929 {
930  struct ast_bridge_features *features;
931  struct ast_channel *chan;
932  struct ast_channel *owner;
933  ast_callid bridge_callid;
934  RAII_VAR(struct ast_unreal_pvt *, p, NULL, ao2_cleanup);
935 
936  ast_bridge_lock(bridge);
937  bridge_callid = bridge->callid;
938  ast_bridge_unlock(bridge);
939 
940  {
941  SCOPED_CHANNELLOCK(lock, ast);
942  p = ast_channel_tech_pvt(ast);
943  if (!p) {
944  return -1;
945  }
946  ao2_ref(p, +1);
947  }
948 
949  {
950  SCOPED_AO2LOCK(lock, p);
951  chan = p->chan;
952  if (!chan) {
953  return -1;
954  }
955 
956  owner = p->owner;
957  if (!owner) {
958  return -1;
959  }
960 
961  ast_channel_ref(chan);
962  ast_channel_ref(owner);
963  }
964 
965  if (bridge_callid) {
966  ast_callid chan_callid;
967  ast_callid owner_callid;
968 
969  /* chan side call ID setting */
970  ast_channel_lock(chan);
971 
972  chan_callid = ast_channel_callid(chan);
973  if (!chan_callid) {
974  ast_channel_callid_set(chan, bridge_callid);
975  }
976  ast_channel_unlock(chan);
977 
978  /* owner side call ID setting */
979  ast_channel_lock(owner);
980 
981  owner_callid = ast_channel_callid(owner);
982  if (!owner_callid) {
983  ast_channel_callid_set(owner, bridge_callid);
984  }
985 
986  ast_channel_unlock(owner);
987  }
988 
989  /* We are done with the owner now that its call ID matches the bridge */
990  ast_channel_unref(owner);
991  owner = NULL;
992 
993  features = ast_bridge_features_new();
994  if (!features) {
995  ast_channel_unref(chan);
996  return -1;
997  }
998 
999  ast_set_flag(&features->feature_flags, flags);
1000 
1001  /* Impart the semi2 channel into the bridge */
1002  if (ast_bridge_impart(bridge, chan, NULL, features,
1004  ast_channel_unref(chan);
1005  return -1;
1006  }
1007 
1008  /* The bridge thread now controls the chan ref from the ast_unreal_pvt */
1009  ao2_lock(p);
1011  ao2_unlock(p);
1012 
1013  ast_channel_unref(chan);
1014 
1015  return 0;
1016 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
Structure that contains features information.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ast_set_flag(p, flag)
Definition: utils.h:70
ast_callid callid
Definition: bridge.h:369
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
unsigned int ast_callid
Definition: logger.h:87
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ast_flags feature_flags
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:1924
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
#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:911
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3750
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:480
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_callid ast_channel_callid(const struct ast_channel *chan)

◆ ast_unreal_destructor()

void ast_unreal_destructor ( void *  vdoomed)

struct ast_unreal_pvt destructor.

Since
12.0.0
Parameters
vdoomedObject to destroy.
Returns
Nothing

Definition at line 1099 of file core_unreal.c.

References ao2_cleanup, ast_stream_topology_free(), ast_unreal_pvt::chan_old_topology, NULL, ast_unreal_pvt::owner_old_topology, ast_unreal_pvt::reqcap, and ast_unreal_pvt::reqtopology.

Referenced by announce_pvt_destructor(), local_pvt_destructor(), and media_request_helper().

1100 {
1101  struct ast_unreal_pvt *doomed = vdoomed;
1102 
1103  ao2_cleanup(doomed->reqcap);
1104  doomed->reqcap = NULL;
1106  doomed->reqtopology = NULL;
1108  ao2_cleanup(doomed->chan_old_topology);
1109 }
#define NULL
Definition: resample.c:96
struct ast_stream_topology * chan_old_topology
Definition: core_unreal.h:102
struct ast_stream_topology * owner_old_topology
Definition: core_unreal.h:101
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100

◆ ast_unreal_digit_begin()

int ast_unreal_digit_begin ( struct ast_channel ast,
char  digit 
)

Unreal channel framework struct ast_channel_tech.send_digit_begin callback

Definition at line 779 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_channel_tech_pvt(), AST_FRAME_DTMF_BEGIN, AST_UNREAL_IS_OUTBOUND, digit, ast_frame_subclass::integer, ast_frame::subclass, and unreal_queue_frame().

780 {
781  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
782  int res = -1;
783  struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
784  int isoutbound;
785 
786  if (!p) {
787  return -1;
788  }
789 
790  ao2_ref(p, 1); /* ref for unreal_queue_frame */
791  ao2_lock(p);
792  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
793  f.subclass.integer = digit;
794  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
795  ao2_unlock(p);
796  ao2_ref(p, -1);
797 
798  return res;
799 }
char digit
void * ast_channel_tech_pvt(const struct ast_channel *chan)
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
Definition: core_unreal.c:213
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ast_frame_subclass subclass
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.

◆ ast_unreal_digit_end()

int ast_unreal_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
)

Unreal channel framework struct ast_channel_tech.send_digit_end callback

Definition at line 801 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_channel_tech_pvt(), AST_FRAME_DTMF_END, AST_UNREAL_IS_OUTBOUND, digit, ast_frame_subclass::integer, ast_frame::len, ast_frame::subclass, and unreal_queue_frame().

802 {
803  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
804  int res = -1;
805  struct ast_frame f = { AST_FRAME_DTMF_END, };
806  int isoutbound;
807 
808  if (!p) {
809  return -1;
810  }
811 
812  ao2_ref(p, 1); /* ref for unreal_queue_frame */
813  ao2_lock(p);
814  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
815  f.subclass.integer = digit;
816  f.len = duration;
817  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
818  ao2_unlock(p);
819  ao2_ref(p, -1);
820 
821  return res;
822 }
char digit
void * ast_channel_tech_pvt(const struct ast_channel *chan)
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
Definition: core_unreal.c:213
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ast_frame_subclass subclass
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.

◆ ast_unreal_fixup()

int ast_unreal_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
)

Unreal channel framework struct ast_channel_tech.fixup callback

Definition at line 369 of file core_unreal.c.

References ao2_lock, ao2_unlock, ast_channel_internal_bridge(), ast_channel_name(), ast_channel_tech_pvt(), ast_check_hangup(), ast_log, ast_queue_hangup(), ast_unreal_pvt::chan, LOG_WARNING, and ast_unreal_pvt::owner.

370 {
371  struct ast_unreal_pvt *p = ast_channel_tech_pvt(newchan);
372  struct ast_bridge *bridge_owner;
373  struct ast_bridge *bridge_chan;
374 
375  if (!p) {
376  return -1;
377  }
378 
379  ao2_lock(p);
380 
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);
383  ao2_unlock(p);
384  return -1;
385  }
386  if (p->owner == oldchan) {
387  p->owner = newchan;
388  } else {
389  p->chan = newchan;
390  }
391 
392  if (ast_check_hangup(newchan) || !p->owner || !p->chan) {
393  ao2_unlock(p);
394  return 0;
395  }
396 
397  /* Do not let a masquerade cause an unreal channel to be bridged to itself! */
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));
403  ao2_unlock(p);
404  ast_queue_hangup(newchan);
405  return -1;
406  }
407 
408  ao2_unlock(p);
409  return 0;
410 }
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define LOG_WARNING
Definition: logger.h:274
struct ast_channel * owner
Definition: core_unreal.h:93
struct ast_bridge * ast_channel_internal_bridge(const struct ast_channel *chan)
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_log
Definition: astobj2.c:42
#define ao2_lock(a)
Definition: astobj2.h:718
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
struct ast_channel * chan
Definition: core_unreal.h:94
Structure that contains information about a bridge.
Definition: bridge.h:357
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
const char * ast_channel_name(const struct ast_channel *chan)

◆ ast_unreal_hangup()

int ast_unreal_hangup ( struct ast_unreal_pvt p,
struct ast_channel ast 
)

Hangup one end (maybe both ends) of an unreal channel derivative.

Since
12.0.0
Parameters
pPrivate channel struct (reffed)
astChannel being hung up. (locked)
Note
Common hangup code for unreal channels. Derived channels will need to deal with any additional resources.
Return values
0on success.
-1on error.

Definition at line 1018 of file core_unreal.c.

References ao2_ref, ao2_unlock, AST_CAUSE_ANSWERED_ELSEWHERE, ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt_set(), ast_channel_unlock, ast_channel_unref, ast_clear_flag, ast_debug, ast_hangup(), ast_log, ast_queue_hangup_with_cause(), ast_test_flag, AST_UNREAL_CARETAKER_THREAD, ast_unreal_lock_all(), ast_unreal_pvt::chan, hangup_chan(), LOG_WARNING, NULL, ast_unreal_pvt::owner, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and status.

Referenced by announce_hangup(), local_hangup(), and media_hangup().

1019 {
1020  int hangup_chan = 0;
1021  int res = 0;
1022  int cause;
1023  struct ast_channel *owner = NULL;
1024  struct ast_channel *chan = NULL;
1025 
1026  /* the pvt isn't going anywhere, it has a ref */
1027  ast_channel_unlock(ast);
1028 
1029  /* lock everything */
1030  ast_unreal_lock_all(p, &chan, &owner);
1031 
1032  if (ast != chan && ast != owner) {
1033  res = -1;
1034  goto unreal_hangup_cleanup;
1035  }
1036 
1037  cause = ast_channel_hangupcause(ast);
1038 
1039  ast_log(LOG_WARNING, "Unreal hangup\n");
1040 
1041  if (ast == p->chan) {
1042  /* Outgoing side is hanging up. */
1044  p->chan = NULL;
1045  if (p->owner) {
1046  const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
1047 
1048  if (status) {
1050  pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
1051  }
1053  }
1054  } else {
1055  /* Owner side is hanging up. */
1056  p->owner = NULL;
1057  if (p->chan) {
1058  if (cause == AST_CAUSE_ANSWERED_ELSEWHERE) {
1060  ast_debug(2, "%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
1061  ast_channel_name(p->chan));
1062  }
1064  /*
1065  * Need to actually hangup p->chan since nothing else is taking
1066  * care of it.
1067  */
1068  hangup_chan = 1;
1069  } else {
1070  ast_queue_hangup_with_cause(p->chan, cause);
1071  }
1072  }
1073  }
1074 
1075  /* this is one of our locked channels, doesn't matter which */
1077  ao2_ref(p, -1);
1078 
1079 unreal_hangup_cleanup:
1080  ao2_unlock(p);
1081  if (owner) {
1082  ast_channel_unlock(owner);
1083  ast_channel_unref(owner);
1084  }
1085  if (chan) {
1086  ast_channel_unlock(chan);
1087  if (hangup_chan) {
1088  ast_hangup(chan);
1089  }
1090  ast_channel_unref(chan);
1091  }
1092 
1093  /* leave with the channel locked that came in */
1094  ast_channel_lock(ast);
1095 
1096  return res;
1097 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ast_test_flag(p, flag)
Definition: utils.h:63
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define LOG_WARNING
Definition: logger.h:274
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:113
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_channel * chan
Definition: core_unreal.h:94
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int cause
Definition: bridge.h:394
static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
Definition: chan_misdn.c:8447
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...
int ast_channel_hangupcause(const struct ast_channel *chan)
const char * ast_channel_name(const struct ast_channel *chan)
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
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
jack_status_t status
Definition: app_jack.c:146

◆ ast_unreal_indicate()

int ast_unreal_indicate ( struct ast_channel ast,
int  condition,
const void *  data,
size_t  datalen 
)

Unreal channel framework struct ast_channel_tech.indicate callback

Definition at line 622 of file core_unreal.c.

References ao2_bump, ao2_ref, ao2_unlock, ast_channel_get_stream_topology(), ast_channel_is_multistream(), ast_channel_lock, ast_channel_set_stream_topology(), ast_channel_tech_pvt(), ast_channel_unlock, ast_channel_unref, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HOLD, AST_CONTROL_MASQUERADE_NOTIFY, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, ast_free, ast_log, AST_MEDIA_TYPE_IMAGE, ast_moh_start(), ast_moh_stop(), AST_STATE_RING, ast_stream_alloc(), ast_stream_topology_alloc(), ast_stream_topology_append_stream(), AST_T38_NEGOTIATED, AST_T38_TERMINATED, ast_test_flag, ast_unreal_lock_all(), AST_UNREAL_MOH_INTERCEPT, ast_unreal_pvt::chan_old_topology, LOG_ERROR, NULL, ast_unreal_pvt::owner_old_topology, ast_control_t38_parameters::request_response, unreal_colp_redirect_indicate(), unreal_colp_stream_topology_request_change(), and unreal_queue_indicate().

623 {
624  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
625  int res = 0;
626  struct ast_channel *chan = NULL;
627  struct ast_channel *owner = NULL;
628  const struct ast_control_t38_parameters *parameters;
629 
630  if (!p) {
631  return -1;
632  }
633 
634  ao2_ref(p, 1); /* ref for unreal_queue_frame */
635 
636  switch (condition) {
638  /*
639  * Always block this because this is the channel being
640  * masqueraded; not anything down the chain.
641  */
642  break;
645  res = unreal_colp_redirect_indicate(p, ast, condition);
646  break;
647  case AST_CONTROL_HOLD:
649  ast_moh_start(ast, data, NULL);
650  break;
651  }
652  res = unreal_queue_indicate(p, ast, condition, data, datalen);
653  break;
654  case AST_CONTROL_UNHOLD:
656  ast_moh_stop(ast);
657  break;
658  }
659  res = unreal_queue_indicate(p, ast, condition, data, datalen);
660  break;
661  case AST_CONTROL_RINGING:
662  /* Don't queue ringing frames if the channel is not in a "ring" state. Otherwise,
663  * the real channel on the other end will likely start a playtones generator. It is
664  * possible that this playtones generator will never be stopped under certain
665  * circumstances.
666  */
667  if (ast_channel_state(ast) == AST_STATE_RING) {
668  res = unreal_queue_indicate(p, ast, condition, data, datalen);
669  } else {
670  res = -1;
671  }
672  break;
674  /* Return -1 so that asterisk core will correctly set up hangupcauses. */
675  unreal_queue_indicate(p, ast, condition, data, datalen);
676  res = -1;
677  break;
679  if (ast_channel_is_multistream(ast)) {
680  res = unreal_colp_stream_topology_request_change(p, ast, data);
681  }
682  break;
684  parameters = data;
685  if (parameters->request_response == AST_T38_NEGOTIATED) {
686  struct ast_stream *stream;
687  struct ast_stream_topology *new_topology;
688 
689  stream = ast_stream_alloc("local_fax", AST_MEDIA_TYPE_IMAGE);
690  if (!stream) {
691  ast_log(LOG_ERROR, "Failed to allocate memory for stream.\n");
692  res = -1;
693  break;
694  }
695  new_topology = ast_stream_topology_alloc();
696  if (!new_topology) {
697  ast_log(LOG_ERROR, "Failed to allocate memory for stream topology.\n");
698  ast_free(stream);
699  res = -1;
700  break;
701  }
702  ast_stream_topology_append_stream(new_topology, stream);
703 
704  /*
705  * Lock both parts of the local channel so we can store their topologies and replace them with
706  * one that has a stream with type IMAGE. We can just hold the reference on the unreal_pvt
707  * structure and bump it, then steal the ref later when we are restoring the topology.
708  *
709  * We use ast_unreal_lock_all here because we don't know if the ;1 or ;2 side will get the
710  * signaling and we need to be sure that the locking order is the same to prevent possible
711  * deadlocks.
712  */
713  ast_channel_unlock(ast);
714  ast_unreal_lock_all(p, &chan, &owner);
715 
716  if (owner) {
718  ast_channel_set_stream_topology(owner, new_topology);
719  }
720 
721  if (chan) {
723 
724  /* Bump the ref for new_topology, since it will be used by both sides of the local channel */
725  ao2_ref(new_topology, +1);
726  ast_channel_set_stream_topology(chan, new_topology);
727  }
728 
729  ao2_unlock(p);
730  ast_channel_lock(ast);
731  } else if (parameters->request_response == AST_T38_TERMINATED) {
732  /*
733  * Lock both parts of the local channel so we can restore their topologies to the original.
734  * The topology should be on the unreal_pvt structure, with a ref that we can steal. Same
735  * conditions as above.
736  */
737  ast_channel_unlock(ast);
738  ast_unreal_lock_all(p, &chan, &owner);
739 
740  if (owner) {
743  }
744 
745  if (chan) {
747  p->chan_old_topology = NULL;
748  }
749 
750  ao2_unlock(p);
751  ast_channel_lock(ast);
752  }
753 
754  /*
755  * We unlock ast_unreal_pvt in the above conditionals since there's no way to
756  * tell if it's been unlocked already or not when we get to this point, but
757  * if either of these are not NULL, we know that they are locked and need to
758  * unlock them.
759  */
760  if (owner) {
761  ast_channel_unlock(owner);
762  ast_channel_unref(owner);
763  }
764 
765  if (chan) {
766  ast_channel_unlock(chan);
767  ast_channel_unref(chan);
768  }
769  /* Fall through for all T38 conditions */
770  default:
771  res = unreal_queue_indicate(p, ast, condition, data, datalen);
772  break;
773  }
774 
775  ao2_ref(p, -1);
776  return res;
777 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
static int unreal_colp_stream_topology_request_change(struct ast_unreal_pvt *p, struct ast_channel *ast, const struct ast_stream_topology *topology)
Definition: core_unreal.c:555
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.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ast_test_flag(p, flag)
Definition: utils.h:63
enum ast_control_t38 request_response
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static int unreal_colp_redirect_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
Definition: core_unreal.c:477
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
#define AST_UNREAL_MOH_INTERCEPT
Definition: core_unreal.h:109
#define ao2_bump(obj)
Definition: astobj2.h:491
struct ast_stream_topology * chan_old_topology
Definition: core_unreal.h:102
#define ast_log
Definition: astobj2.c:42
static int unreal_queue_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition, const void *data, size_t datalen)
Definition: core_unreal.c:427
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_stream_topology * owner_old_topology
Definition: core_unreal.h:101
#define LOG_ERROR
Definition: logger.h:285
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.
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7866
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
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

◆ ast_unreal_lock_all()

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.

Note
NO locks should be held prior to calling this function
The pvt must have a ref held before calling this function
if outchan or outowner is set != NULL after calling this function those channels are locked and reffed.
Batman.

Definition at line 47 of file core_unreal.c.

References ao2_lock, ao2_unlock, ast_channel_lock, ast_channel_lock_both, ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_unreal_pvt::chan, NULL, and ast_unreal_pvt::owner.

Referenced by ast_local_lock_all(), ast_unreal_hangup(), ast_unreal_indicate(), local_call(), publish_local_bridge_message(), stasis_app_channel_unreal_set_internal(), unreal_colp_redirect_indicate(), and unreal_colp_stream_topology_request_change().

48 {
49  struct ast_channel *chan = NULL;
50  struct ast_channel *owner = NULL;
51 
52  ao2_lock(p);
53  for (;;) {
54  if (p->chan) {
55  chan = p->chan;
56  ast_channel_ref(chan);
57  }
58  if (p->owner) {
59  owner = p->owner;
60  ast_channel_ref(owner);
61  }
62  ao2_unlock(p);
63 
64  /* if we don't have both channels, then this is very easy */
65  if (!owner || !chan) {
66  if (owner) {
67  ast_channel_lock(owner);
68  } else if(chan) {
69  ast_channel_lock(chan);
70  }
71  } else {
72  /* lock both channels first, then get the pvt lock */
73  ast_channel_lock_both(chan, owner);
74  }
75  ao2_lock(p);
76 
77  /* Now that we have all the locks, validate that nothing changed */
78  if (p->owner != owner || p->chan != chan) {
79  if (owner) {
80  ast_channel_unlock(owner);
81  owner = ast_channel_unref(owner);
82  }
83  if (chan) {
84  ast_channel_unlock(chan);
85  chan = ast_channel_unref(chan);
86  }
87  continue;
88  }
89 
90  break;
91  }
92  *outowner = p->owner;
93  *outchan = p->chan;
94 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_channel * owner
Definition: core_unreal.h:93
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_channel * chan
Definition: core_unreal.h:94
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970

◆ ast_unreal_new_channels()

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.

Since
12.0.0
Parameters
pUnreal channel private struct.
techChannel technology to use.
semi1_stateState to start the semi1(owner) channel in.
semi2_stateState to start the semi2(outgoing chan) channel in.
extenExten to start the chennels in. (NULL if s)
contextContext to start the channels in. (NULL if default)
requestorChannel requesting creation. (NULL if none)
callidThread callid to use.
Return values
semi1_channelon success.
NULLon error.

Definition at line 1162 of file core_unreal.c.

References ao2_cleanup, ao2_ref, ast_alloca, ast_atomic_fetchadd_int(), ast_channel_alloc, ast_channel_callid_set(), ast_channel_cc_params_init(), ast_channel_flags(), ast_channel_get_cc_config_params(), ast_channel_is_multistream(), ast_channel_nativeformats_set(), ast_channel_release(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_stream_topology(), ast_channel_set_writeformat(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_unlock, AST_FLAG_DISABLE_DEVSTATE_CACHE, ast_format_cap_get_format(), ast_jb_configure(), ast_log, ast_set_flag, ast_stream_topology_clone(), ast_stream_topology_free(), ast_strlen_zero, ast_unreal_pvt::chan, ast_unreal_pvt::jb_conf, LOG_WARNING, ast_unreal_pvt::name, name_sequence, NULL, ast_unreal_pvt::owner, RAII_VAR, ast_unreal_pvt::reqcap, ast_unreal_pvt::reqtopology, ast_channel_tech::type, ast_assigned_ids::uniqueid, and ast_assigned_ids::uniqueid2.

Referenced by announce_request(), local_request_with_stream_topology(), and media_request_helper().

1166 {
1167  struct ast_channel *owner;
1168  struct ast_channel *chan;
1169  RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
1170  struct ast_assigned_ids id1 = {NULL, NULL};
1171  struct ast_assigned_ids id2 = {NULL, NULL};
1172  int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
1173  struct ast_stream_topology *topology;
1174 
1175  /* set unique ids for the two channels */
1176  if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
1177  id1.uniqueid = assignedids->uniqueid;
1178  id2.uniqueid = assignedids->uniqueid2;
1179  }
1180 
1181  /* if id1 given but not id2, use default of id1;2 */
1182  if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
1183  char *uniqueid2;
1184 
1185  uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 3);
1186  strcpy(uniqueid2, id1.uniqueid);/* Safe */
1187  strcat(uniqueid2, ";2");/* Safe */
1188  id2.uniqueid = uniqueid2;
1189  }
1190 
1191  /* We need to create a topology to place on the first channel, as we can't
1192  * share a single one between both.
1193  */
1194  topology = ast_stream_topology_clone(p->reqtopology);
1195  if (!topology) {
1196  return NULL;
1197  }
1198 
1199  /*
1200  * Allocate two new Asterisk channels
1201  *
1202  * Make sure that the ;2 channel gets the same linkedid as ;1.
1203  * You can't pass linkedid to both allocations since if linkedid
1204  * isn't set, then each channel will generate its own linkedid.
1205  */
1206  owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
1207  exten, context, &id1, requestor, 0,
1208  "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
1209  if (!owner) {
1210  ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
1211  ast_stream_topology_free(topology);
1212  return NULL;
1213  }
1214 
1215  if (callid) {
1216  ast_channel_callid_set(owner, callid);
1217  }
1218 
1219  ast_channel_tech_set(owner, tech);
1220  ao2_ref(p, +1);
1221  ast_channel_tech_pvt_set(owner, p);
1222 
1224 
1225  if (ast_channel_is_multistream(owner)) {
1226  ast_channel_set_stream_topology(owner, topology);
1227  }
1228 
1229  /* Determine our read/write format and set it on each channel */
1230  fmt = ast_format_cap_get_format(p->reqcap, 0);
1231  if (!fmt) {
1232  ast_channel_tech_pvt_set(owner, NULL);
1233  ao2_ref(p, -1);
1234  ast_channel_unlock(owner);
1235  ast_channel_release(owner);
1236  return NULL;
1237  }
1238 
1239  ast_channel_set_writeformat(owner, fmt);
1240  ast_channel_set_rawwriteformat(owner, fmt);
1241  ast_channel_set_readformat(owner, fmt);
1242  ast_channel_set_rawreadformat(owner, fmt);
1243 
1245 
1246  ast_jb_configure(owner, &p->jb_conf);
1247 
1248  if (ast_channel_cc_params_init(owner, requestor
1249  ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
1250  ast_channel_tech_pvt_set(owner, NULL);
1251  ao2_ref(p, -1);
1252  ast_channel_tech_pvt_set(owner, NULL);
1253  ast_channel_unlock(owner);
1254  ast_channel_release(owner);
1255  return NULL;
1256  }
1257 
1258  p->owner = owner;
1259  ast_channel_unlock(owner);
1260 
1261  chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
1262  exten, context, &id2, owner, 0,
1263  "%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
1264  if (!chan) {
1265  ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
1266  ast_channel_tech_pvt_set(owner, NULL);
1267  ao2_ref(p, -1);
1268  ast_channel_tech_pvt_set(owner, NULL);
1269  ast_channel_release(owner);
1270  return NULL;
1271  }
1272 
1273  if (callid) {
1274  ast_channel_callid_set(chan, callid);
1275  }
1276 
1277  ast_channel_tech_set(chan, tech);
1278  ao2_ref(p, +1);
1279  ast_channel_tech_pvt_set(chan, p);
1280 
1282 
1283  if (ast_channel_is_multistream(chan)) {
1285  p->reqtopology = NULL;
1286  }
1287 
1288  /* Format was already determined when setting up owner */
1289  ast_channel_set_writeformat(chan, fmt);
1290  ast_channel_set_rawwriteformat(chan, fmt);
1291  ast_channel_set_readformat(chan, fmt);
1292  ast_channel_set_rawreadformat(chan, fmt);
1293 
1295 
1296  p->chan = chan;
1297  ast_channel_unlock(chan);
1298 
1299  return owner;
1300 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
const char *const type
Definition: channel.h:630
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
struct ast_channel * owner
Definition: core_unreal.h:93
struct ast_jb_conf jb_conf
Definition: core_unreal.h:96
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
Definition of a media format.
Definition: format.c:43
const char * uniqueid
Definition: channel.h:606
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static unsigned int name_sequence
Definition: core_unreal.c:45
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10675
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
#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:911
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
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.
Definition: channel.c:10652
struct ast_channel * chan
Definition: core_unreal.h:94
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
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.
char name[AST_MAX_EXTENSION+AST_MAX_CONTEXT+2]
Definition: core_unreal.h:99
#define ast_channel_unlock(chan)
Definition: channel.h:2946
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.
Definition: abstract_jb.c:593
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 ao2_cleanup(obj)
Definition: astobj2.h:1958
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100
const char * uniqueid2
Definition: channel.h:607
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)

◆ ast_unreal_queryoption()

int ast_unreal_queryoption ( struct ast_channel ast,
int  option,
void *  data,
int *  datalen 
)

Unreal channel framework struct ast_channel_tech.queryoption callback

Definition at line 166 of file core_unreal.c.

References ao2_lock, ao2_unlock, ast_channel_bridge_peer(), ast_channel_lock, ast_channel_queryoption(), ast_channel_ref, ast_channel_tech_pvt(), ast_channel_unlock, ast_channel_unref, AST_OPTION_T38_STATE, AST_UNREAL_IS_OUTBOUND, ast_unreal_pvt::chan, and ast_unreal_pvt::owner.

167 {
168  struct ast_unreal_pvt *p;
169  struct ast_channel *peer;
170  struct ast_channel *other;
171  int res = 0;
172 
173  if (option != AST_OPTION_T38_STATE) {
174  /* AST_OPTION_T38_STATE is the only supported option at this time */
175  return -1;
176  }
177 
178  /* for some reason the channel is not locked in channel.c when this function is called */
179  if (!(p = ast_channel_tech_pvt(ast))) {
180  return -1;
181  }
182 
183  ao2_lock(p);
184  other = AST_UNREAL_IS_OUTBOUND(ast, p) ? p->owner : p->chan;
185  if (!other) {
186  ao2_unlock(p);
187  return -1;
188  }
189  ast_channel_ref(other);
190  ao2_unlock(p);
191  ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
192 
193  peer = ast_channel_bridge_peer(other);
194  if (peer) {
195  res = ast_channel_queryoption(peer, option, data, datalen, 0);
196  ast_channel_unref(peer);
197  }
198  ast_channel_unref(other);
199  ast_channel_lock(ast); /* Lock back before we leave */
200 
201  return res;
202 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
Definition: channel.c:7542
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
const char * data
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_channel * chan
Definition: core_unreal.h:94
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10765
#define AST_OPTION_T38_STATE

◆ ast_unreal_read()

struct ast_frame* ast_unreal_read ( struct ast_channel ast)

Unreal channel framework struct ast_channel_tech.read and struct ast_channel_tech.exception callback

Definition at line 313 of file core_unreal.c.

References ast_null_frame.

314 {
315  return &ast_null_frame;
316 }
struct ast_frame ast_null_frame
Definition: main/frame.c:79

◆ ast_unreal_sendhtml()

int ast_unreal_sendhtml ( struct ast_channel ast,
int  subclass,
const char *  data,
int  datalen 
)

Unreal channel framework struct ast_channel_tech.send_html callback

Definition at line 846 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_channel_tech_pvt(), AST_FRAME_HTML, AST_UNREAL_IS_OUTBOUND, ast_frame::data, ast_frame::datalen, ast_frame_subclass::integer, ast_frame::ptr, ast_frame::subclass, and unreal_queue_frame().

847 {
848  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
849  int res = -1;
850  struct ast_frame f = { AST_FRAME_HTML, };
851  int isoutbound;
852 
853  if (!p) {
854  return -1;
855  }
856 
857  ao2_ref(p, 1); /* ref for unreal_queue_frame */
858  ao2_lock(p);
859  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
861  f.data.ptr = (char *)data;
862  f.datalen = datalen;
863  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
864  ao2_unlock(p);
865  ao2_ref(p, -1);
866 
867  return res;
868 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
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
Definition: core_unreal.c:213
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ast_frame_subclass subclass
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.
union ast_frame::@263 data

◆ ast_unreal_sendtext()

int ast_unreal_sendtext ( struct ast_channel ast,
const char *  text 
)

Unreal channel framework struct ast_channel_tech.send_text callback

Definition at line 824 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_channel_tech_pvt(), AST_FRAME_TEXT, AST_UNREAL_IS_OUTBOUND, ast_frame::data, ast_frame::datalen, ast_frame::ptr, and unreal_queue_frame().

825 {
826  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
827  int res = -1;
828  struct ast_frame f = { AST_FRAME_TEXT, };
829  int isoutbound;
830 
831  if (!p) {
832  return -1;
833  }
834 
835  ao2_ref(p, 1); /* ref for unreal_queue_frame */
836  ao2_lock(p);
837  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
838  f.data.ptr = (char *) text;
839  f.datalen = strlen(text) + 1;
840  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
841  ao2_unlock(p);
842  ao2_ref(p, -1);
843  return res;
844 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
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
Definition: core_unreal.c:213
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
char * text
Definition: app_queue.c:1508
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.
union ast_frame::@263 data

◆ ast_unreal_setoption()

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

Unreal channel framework struct ast_channel_tech.setoption callback

Definition at line 97 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, AST_CHAN_WRITE_INFO_T_VERSION, ast_channel_lock, ast_channel_ref, ast_channel_tech_pvt(), ast_channel_unlock, ast_channel_unref, ast_log, AST_OPTION_CHANNEL_WRITE, ast_unreal_pvt::chan, ast_chan_write_info_t::chan, ast_channel::data, ast_chan_write_info_t::data, ast_chan_write_info_t::function, if(), LOG_ERROR, NULL, ast_unreal_pvt::owner, ast_chan_write_info_t::value, ast_chan_write_info_t::version, and ast_chan_write_info_t::write_fn.

Referenced by local_setoption().

98 {
99  int res = 0;
100  struct ast_unreal_pvt *p;
101  struct ast_channel *otherchan = NULL;
102  ast_chan_write_info_t *write_info;
103  char *info_data;
104 
105  if (option != AST_OPTION_CHANNEL_WRITE) {
106  return -1;
107  }
108 
109  write_info = data;
110 
111  if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
112  ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
113  return -1;
114  }
115 
116  info_data = write_info->data;
117  if (!strcmp(write_info->function, "CHANNEL")) {
118  if (!strncasecmp(info_data, "hangup_handler_", 15)) {
119  /* Block CHANNEL(hangup_handler_xxx) writes to the other unreal channel. */
120  return 0;
121  }
122 
123  /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
124  if (!strcasecmp(info_data, "accountcode")) {
125  info_data = "peeraccount";
126  } else if (!strcasecmp(info_data, "peeraccount")) {
127  info_data = "accountcode";
128  }
129  }
130 
131  /* get the tech pvt */
132  if (!(p = ast_channel_tech_pvt(ast))) {
133  return -1;
134  }
135  ao2_ref(p, 1);
136  ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
137 
138  /* get the channel we are supposed to write to */
139  ao2_lock(p);
140  otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
141  if (!otherchan || otherchan == write_info->chan) {
142  res = -1;
143  otherchan = NULL;
144  ao2_unlock(p);
145  goto setoption_cleanup;
146  }
147  ast_channel_ref(otherchan);
148 
149  /* clear the pvt lock before grabbing the channel */
150  ao2_unlock(p);
151 
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);
155 
156 setoption_cleanup:
157  ao2_ref(p, -1);
158  if (otherchan) {
159  ast_channel_unref(otherchan);
160  }
161  ast_channel_lock(ast); /* Lock back before we leave */
162  return res;
163 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
const char * function
Definition: channel.h:596
Main Channel structure associated with a channel.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_channel * owner
Definition: core_unreal.h:93
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
const char * data
const char * value
Definition: channel.h:598
#define ast_log
Definition: astobj2.c:42
struct ast_channel * chan
Definition: channel.h:595
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_channel * chan
Definition: core_unreal.h:94
ast_acf_write_fn_t write_fn
Definition: channel.h:594
#define LOG_ERROR
Definition: logger.h:285
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:592
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#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.
Definition: channel.h:590
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970

◆ ast_unreal_write()

int ast_unreal_write ( struct ast_channel ast,
struct ast_frame f 
)

Unreal channel framework struct ast_channel_tech.write callback

Definition at line 318 of file core_unreal.c.

References ast_unreal_write_stream().

319 {
320  return ast_unreal_write_stream(ast, -1, f);
321 }
int ast_unreal_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)
Definition: core_unreal.c:323

◆ ast_unreal_write_stream()

int ast_unreal_write_stream ( struct ast_channel ast,
int  stream_num,
struct ast_frame f 
)

Unreal channel framework struct ast_channel_tech.write_stream callback

Definition at line 323 of file core_unreal.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_channel_get_default_stream(), ast_channel_tech_pvt(), AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_UNREAL_IS_OUTBOUND, ast_frame::frametype, got_optimized_out(), ast_frame_subclass::integer, ast_frame::stream_num, ast_frame::subclass, and unreal_queue_frame().

Referenced by ast_unreal_write().

324 {
325  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
326  int res = -1;
327 
328  if (!p) {
329  return -1;
330  }
331 
332  /* If we are told to write a frame with a type that has no corresponding
333  * stream on the channel then drop it.
334  */
335  if (f->frametype == AST_FRAME_VOICE) {
337  return 0;
338  }
339  } else if (f->frametype == AST_FRAME_VIDEO ||
342  return 0;
343  }
344  }
345 
346  /* Update the frame to reflect the stream */
347  f->stream_num = stream_num;
348 
349  /* Just queue for delivery to the other side */
350  ao2_ref(p, 1);
351  ao2_lock(p);
352  switch (f->frametype) {
353  case AST_FRAME_VOICE:
354  case AST_FRAME_VIDEO:
355  if (got_optimized_out(ast, p)) {
356  break;
357  }
358  /* fall through */
359  default:
360  res = unreal_queue_frame(p, AST_UNREAL_IS_OUTBOUND(ast, p), f, ast, 1);
361  break;
362  }
363  ao2_unlock(p);
364  ao2_ref(p, -1);
365 
366  return res;
367 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
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
Definition: core_unreal.c:213
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ast_frame_subclass subclass
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.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
Definition: core_unreal.c:295
#define ao2_lock(a)
Definition: astobj2.h:718
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
enum ast_frame_type frametype

◆ got_optimized_out()

static int got_optimized_out ( struct ast_channel ast,
struct ast_unreal_pvt p 
)
static

Definition at line 295 of file core_unreal.c.

References ast_bridge_unreal_optimize_out(), ast_test_flag, AST_UNREAL_NO_OPTIMIZATION, ast_unreal_pvt::chan, and ast_unreal_pvt::owner.

Referenced by ast_unreal_write_stream().

296 {
297  int res = 0;
298 
299  /* Do a few conditional checks early on just to see if this optimization is possible */
300  if (ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION) || !p->chan || !p->owner) {
301  return res;
302  }
303 
304  if (ast == p->owner) {
305  res = ast_bridge_unreal_optimize_out(p->owner, p->chan, p);
306  } else if (ast == p->chan) {
307  res = ast_bridge_unreal_optimize_out(p->chan, p->owner, p);
308  }
309 
310  return res;
311 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_NO_OPTIMIZATION
Definition: core_unreal.h:108
struct ast_channel * chan
Definition: core_unreal.h:94
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.
Definition: bridge.c:2968

◆ unreal_colp_redirect_indicate()

static int unreal_colp_redirect_indicate ( struct ast_unreal_pvt p,
struct ast_channel ast,
int  condition 
)
static

Definition at line 477 of file core_unreal.c.

References ao2_unlock, ast_channel_caller(), ast_channel_connected(), ast_channel_lock, ast_channel_redirecting(), ast_channel_unlock, ast_channel_unref, ast_connected_line_build_data(), ast_connected_line_copy_to_caller(), AST_CONTROL_CONNECTED_LINE, AST_FRAME_CONTROL, ast_redirecting_build_data(), AST_UNREAL_IS_OUTBOUND, ast_unreal_lock_all(), ast_unreal_pvt::chan, ast_frame::datalen, ast_frame::frametype, NULL, ast_unreal_pvt::owner, and unreal_queue_frame().

Referenced by ast_unreal_indicate().

478 {
479  struct ast_channel *my_chan;
480  struct ast_channel *my_owner;
481  struct ast_channel *this_channel;
482  struct ast_channel *the_other_channel;
483  int isoutbound;
484  int res = 0;
485  unsigned char frame_data[1024];
486  struct ast_frame f = {
488  .subclass.integer = condition,
489  .data.ptr = frame_data,
490  };
491 
492  /*
493  * A connected line update frame may only contain a partial
494  * amount of data, such as just a source, or just a ton, and not
495  * the full amount of information. However, the collected
496  * information is all stored in the outgoing channel's
497  * connectedline structure, so when receiving a connected line
498  * update on an outgoing unreal channel, we need to transmit the
499  * collected connected line information instead of whatever
500  * happens to be in this control frame. The same applies for
501  * redirecting information, which is why it is handled here as
502  * well.
503  */
504  ast_channel_unlock(ast);
505  ast_unreal_lock_all(p, &my_chan, &my_owner);
506  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
507  if (isoutbound) {
508  this_channel = p->chan;
509  the_other_channel = p->owner;
510  } else {
511  this_channel = p->owner;
512  the_other_channel = p->chan;
513  }
514  if (the_other_channel) {
515  if (condition == AST_CONTROL_CONNECTED_LINE) {
517  ast_channel_connected(this_channel));
518  f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data),
519  ast_channel_connected(this_channel), NULL);
520  } else {
521  f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data),
522  ast_channel_redirecting(this_channel), NULL);
523  }
524  }
525  if (my_chan) {
526  ast_channel_unlock(my_chan);
527  ast_channel_unref(my_chan);
528  }
529  if (my_owner) {
530  ast_channel_unlock(my_owner);
531  ast_channel_unref(my_owner);
532  }
533  if (the_other_channel) {
534  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
535  }
536  ao2_unlock(p);
537  ast_channel_lock(ast);
538 
539  return res;
540 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2945
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.
Definition: channel.c:8793
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
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
Definition: core_unreal.c:213
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
struct ast_channel * chan
Definition: core_unreal.h:94
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
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
Data structure associated with a single frame of data.
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.
Definition: channel.c:8396
enum ast_frame_type frametype
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.
Definition: channel.c:9363

◆ unreal_colp_stream_topology_request_change()

static int unreal_colp_stream_topology_request_change ( struct ast_unreal_pvt p,
struct ast_channel ast,
const struct ast_stream_topology topology 
)
static

Definition at line 555 of file core_unreal.c.

References ao2_unlock, ast_channel_lock, ast_channel_set_stream_topology(), ast_channel_stream_topology_changed_externally(), ast_channel_unlock, ast_channel_unref, AST_CONTROL_STREAM_TOPOLOGY_CHANGED, ast_queue_control(), ast_stream_get_state(), ast_stream_set_state(), AST_STREAM_STATE_RECVONLY, AST_STREAM_STATE_SENDONLY, ast_stream_topology_clone(), ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), AST_UNREAL_IS_OUTBOUND, ast_unreal_lock_all(), ast_unreal_pvt::chan, and ast_unreal_pvt::owner.

Referenced by ast_unreal_indicate().

556 {
557  struct ast_stream_topology *this_channel_topology;
558  struct ast_stream_topology *the_other_channel_topology;
559  int i;
560  struct ast_stream *stream;
561  struct ast_channel *my_chan;
562  struct ast_channel *my_owner;
563  struct ast_channel *this_channel;
564  struct ast_channel *the_other_channel;
565  int res = 0;
566 
567  this_channel_topology = ast_stream_topology_clone(topology);
568  if (!this_channel_topology) {
569  return -1;
570  }
571 
572  the_other_channel_topology = ast_stream_topology_clone(topology);
573  if (!the_other_channel_topology) {
574  ast_stream_topology_free(this_channel_topology);
575  return -1;
576  }
577 
578  /* We swap the stream state on the other channel because it is as if the channel is
579  * connected to an external endpoint, so the perspective changes.
580  */
581  for (i = 0; i < ast_stream_topology_get_count(the_other_channel_topology); ++i) {
582  stream = ast_stream_topology_get_stream(the_other_channel_topology, i);
583 
586  } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
588  }
589  }
590 
591  ast_channel_unlock(ast);
592  ast_unreal_lock_all(p, &my_chan, &my_owner);
593  if (AST_UNREAL_IS_OUTBOUND(ast, p)) {
594  this_channel = p->chan;
595  the_other_channel = p->owner;
596  } else {
597  this_channel = p->owner;
598  the_other_channel = p->chan;
599  }
600  if (this_channel) {
601  ast_channel_set_stream_topology(this_channel, this_channel_topology);
603  }
604  if (the_other_channel) {
605  ast_channel_set_stream_topology(the_other_channel, the_other_channel_topology);
607  }
608  if (my_chan) {
609  ast_channel_unlock(my_chan);
610  ast_channel_unref(my_chan);
611  }
612  if (my_owner) {
613  ast_channel_unlock(my_owner);
614  ast_channel_unref(my_owner);
615  }
616  ao2_unlock(p);
617  ast_channel_lock(ast);
618 
619  return res;
620 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define ao2_unlock(a)
Definition: astobj2.h:730
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
struct ast_channel * chan
Definition: core_unreal.h:94
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_channel_unlock(chan)
Definition: channel.h:2946
Set when the stream is sending media only.
Definition: stream.h:86
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
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
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
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
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...
Definition: channel.c:11209
Set when the stream is receiving media only.
Definition: stream.h:90
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373

◆ unreal_queue_frame()

static int unreal_queue_frame ( struct ast_unreal_pvt p,
int  isoutbound,
struct ast_frame f,
struct ast_channel us,
int  us_locked 
)
static

queue a frame onto either the p->owner or p->chan

Note
the ast_unreal_pvt MUST have it's ref count bumped before entering this function and decremented after this function is called. This is a side effect of the deadlock avoidance that is necessary to lock 2 channels and a tech_pvt. Without a ref counted ast_unreal_pvt, it is impossible to guarantee it will not be destroyed by another thread during deadlock avoidance.

Definition at line 213 of file core_unreal.c.

References ao2_lock, ao2_unlock, ast_channel_generator(), ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_queue_frame(), ast_setstate(), AST_STATE_RINGING, ast_unreal_pvt::chan, ast_frame::frametype, ast_frame_subclass::integer, ast_unreal_pvt::owner, and ast_frame::subclass.

Referenced by ast_unreal_answer(), ast_unreal_digit_begin(), ast_unreal_digit_end(), ast_unreal_sendhtml(), ast_unreal_sendtext(), ast_unreal_write_stream(), unreal_colp_redirect_indicate(), and unreal_queue_indicate().

215 {
216  struct ast_channel *other;
217 
218  /* Recalculate outbound channel */
219  other = isoutbound ? p->owner : p->chan;
220  if (!other) {
221  return 0;
222  }
223 
224  /* do not queue media frames if a generator is on both unreal channels */
225  if (us
227  && ast_channel_generator(us)
228  && ast_channel_generator(other)) {
229  return 0;
230  }
231 
232  /* grab a ref on the channel before unlocking the pvt,
233  * other can not go away from us now regardless of locking */
234  ast_channel_ref(other);
235  if (us && us_locked) {
236  ast_channel_unlock(us);
237  }
238  ao2_unlock(p);
239 
242  }
243  ast_queue_frame(other, f);
244 
245  other = ast_channel_unref(other);
246  if (us && us_locked) {
247  ast_channel_lock(us);
248  }
249  ao2_lock(p);
250 
251  return 0;
252 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_channel * owner
Definition: core_unreal.h:93
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ast_frame_subclass subclass
#define ao2_lock(a)
Definition: astobj2.h:718
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
struct ast_channel * chan
Definition: core_unreal.h:94
struct ast_generator * ast_channel_generator(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
enum ast_frame_type frametype

◆ unreal_queue_indicate()

static int unreal_queue_indicate ( struct ast_unreal_pvt p,
struct ast_channel ast,
int  condition,
const void *  data,
size_t  datalen 
)
static

Definition at line 427 of file core_unreal.c.

References ao2_lock, ao2_unlock, AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, AST_T38_REQUEST_PARMS, ast_test_flag, AST_UNREAL_IS_OUTBOUND, AST_UNREAL_NO_OPTIMIZATION, ast_frame::frametype, ast_control_t38_parameters::request_response, and unreal_queue_frame().

Referenced by ast_unreal_indicate().

428 {
429  int res = 0;
430  int isoutbound;
431 
432  ao2_lock(p);
433  /*
434  * Block -1 stop tones events if we are to be optimized out. We
435  * don't need a flurry of these events on an unreal channel chain
436  * when initially connected to slow the optimization process.
437  */
438  if (0 <= condition || ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION)) {
439  struct ast_frame f = {
441  .subclass.integer = condition,
442  .data.ptr = (void *) data,
443  .datalen = datalen,
444  };
445 
446  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
447  res = unreal_queue_frame(p, isoutbound, &f, ast, 1);
448  if (!res
449  && condition == AST_CONTROL_T38_PARAMETERS
450  && datalen == sizeof(struct ast_control_t38_parameters)) {
451  const struct ast_control_t38_parameters *parameters = data;
452 
453  if (parameters->request_response == AST_T38_REQUEST_PARMS) {
454  res = AST_T38_REQUEST_PARMS;
455  }
456  }
457  } else {
458  ast_debug(4, "Blocked indication %d\n", condition);
459  }
460  ao2_unlock(p);
461 
462  return res;
463 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
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
Definition: core_unreal.c:213
#define AST_UNREAL_NO_OPTIMIZATION
Definition: core_unreal.h:108
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
enum ast_control_t38 request_response
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_lock(a)
Definition: astobj2.h:718
Data structure associated with a single frame of data.
union ast_frame::@263 data
enum ast_frame_type frametype

Variable Documentation

◆ name_sequence

unsigned int name_sequence = 0
static

Definition at line 45 of file core_unreal.c.

Referenced by ast_unreal_new_channels().