Asterisk - The Open Source Telephony Project  21.4.1
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"

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

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.
Returns
pvt on success.
Return values
NULLon error.

Definition at line 1109 of file core_unreal.c.

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

1110 {
1111  struct ast_stream_topology *topology;
1112  struct ast_unreal_pvt *unreal;
1113 
1115  if (!topology) {
1116  return NULL;
1117  }
1118 
1119  unreal = ast_unreal_alloc_stream_topology(size, destructor, topology);
1120 
1121  ast_stream_topology_free(topology);
1122 
1123  return unreal;
1124 }
struct ast_unreal_pvt * ast_unreal_alloc_stream_topology(size_t size, ao2_destructor_fn destructor, struct ast_stream_topology *topology)
Allocate the base unreal struct for a derivative.
Definition: core_unreal.c:1126
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
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
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.
topology
Returns
pvt on success.
Return values
NULLon error.

Definition at line 1126 of file core_unreal.c.

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

Referenced by ast_unreal_alloc(), and local_alloc().

1127 {
1128  struct ast_unreal_pvt *unreal;
1129 
1130  static const struct ast_jb_conf jb_conf = {
1131  .flags = 0,
1132  .max_size = -1,
1133  .resync_threshold = -1,
1134  .impl = "",
1135  .target_extra = -1,
1136  };
1137 
1138  unreal = ao2_alloc(size, destructor);
1139  if (!unreal) {
1140  return NULL;
1141  }
1142 
1143  unreal->reqtopology = ast_stream_topology_clone(topology);
1144  if (!unreal->reqtopology) {
1145  ao2_ref(unreal, -1);
1146  return NULL;
1147  }
1148 
1149  unreal->reqcap = ast_stream_topology_get_formats(topology);
1150  if (!unreal->reqcap) {
1151  ao2_ref(unreal, -1);
1152  return NULL;
1153  }
1154 
1155  memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
1156 
1157  return unreal;
1158 }
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
long resync_threshold
Definition: jitterbuf.h:70
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
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
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_ref, AST_CONTROL_ANSWER, AST_FRAME_CONTROL, 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 */
269  struct ast_frame answer = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
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 }
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 ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.
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.

Definition at line 870 of file core_unreal.c.

References ast_channel_cc_params_init(), ast_channel_datastore_inherit(), ast_channel_get_cc_config_params(), ast_channel_publish_varset(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_connected_line_copy_from_caller(), ast_connected_line_copy_to_caller(), AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_party_dialed_copy(), and ast_party_redirecting_copy().

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  */
882  ast_party_redirecting_copy(ast_channel_redirecting(semi2), ast_channel_redirecting(semi1));
883 
884  ast_party_dialed_copy(ast_channel_dialed(semi2), ast_channel_dialed(semi1));
885 
886  /* Crossover the CallerID and conected-line to cross the unreal bridge. */
887  ast_connected_line_copy_to_caller(ast_channel_caller(semi2), ast_channel_connected(semi1));
888  ast_connected_line_copy_from_caller(ast_channel_connected(semi2), ast_channel_caller(semi1));
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  */
904  if (ast_channel_hangupcause(semi1) == AST_CAUSE_ANSWERED_ELSEWHERE) {
905  ast_channel_hangupcause_set(semi2, AST_CAUSE_ANSWERED_ELSEWHERE);
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  */
915  AST_LIST_TRAVERSE(ast_channel_varshead(semi1), varptr, entries) {
916  clone_var = ast_var_assign(varptr->name, varptr->value);
917  if (clone_var) {
918  AST_LIST_INSERT_TAIL(ast_channel_varshead(semi2), clone_var, entries);
919  ast_channel_publish_varset(semi2, ast_var_full_name(clone_var),
920  ast_var_value(clone_var));
921  }
922  }
923  ast_channel_datastore_inherit(semi1, semi2);
924 
926 }
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:10474
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2368
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
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:10451
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
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:8293
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:8300
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
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
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_ref, ast_bridge_features_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_bridge_lock, ast_bridge_unlock, ast_channel_callid_set(), ast_channel_ref, ast_channel_unref, AST_UNREAL_CARETAKER_THREAD, ast_bridge::callid, ast_unreal_pvt::chan, ast_bridge_features::feature_flags, lock, ast_unreal_pvt::owner, RAII_VAR, SCOPED_AO2LOCK, and SCOPED_CHANNELLOCK.

Referenced by ast_ari_bridges_record().

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);
1010  ast_set_flag(p, AST_UNREAL_CARETAKER_THREAD);
1011  ao2_unlock(p);
1012 
1013  ast_channel_unref(chan);
1014 
1015  return 0;
1016 }
Main Channel structure associated with a channel.
struct ast_flags flags
Structure that contains features information.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
ast_callid callid
Definition: bridge.h:361
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
struct ast_flags feature_flags
ast_mutex_t lock
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1878
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
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:3683
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:470
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
void ast_unreal_destructor ( void *  vdoomed)

struct ast_unreal_pvt destructor.

Since
12.0.0
Parameters
vdoomedObject to destroy.

Definition at line 1097 of file core_unreal.c.

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

1098 {
1099  struct ast_unreal_pvt *doomed = vdoomed;
1100 
1101  ao2_cleanup(doomed->reqcap);
1102  doomed->reqcap = NULL;
1104  doomed->reqtopology = NULL;
1105  ao2_cleanup(doomed->owner_old_topology);
1106  ao2_cleanup(doomed->chan_old_topology);
1107 }
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
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
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_ref, AST_FRAME_DTMF_BEGIN, 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 }
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_frame_subclass subclass
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.
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_ref, AST_FRAME_DTMF_END, 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 }
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_frame_subclass subclass
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
Data structure associated with a single frame of data.
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 ast_check_hangup(), ast_queue_hangup(), ast_unreal_pvt::chan, 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
struct ast_channel * owner
Definition: core_unreal.h:93
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:349
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
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, ast_channel_unref, ast_debug, ast_hangup(), ast_queue_hangup_with_cause(), AST_UNREAL_CARETAKER_THREAD, ast_unreal_lock_all(), ast_unreal_pvt::chan, ast_unreal_pvt::owner, pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

Referenced by local_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  if (ast == p->chan) {
1040  /* Outgoing side is hanging up. */
1041  ast_clear_flag(p, AST_UNREAL_CARETAKER_THREAD);
1042  p->chan = NULL;
1043  if (p->owner) {
1044  const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
1045 
1046  if (status) {
1047  ast_channel_hangupcause_set(p->owner, cause);
1048  pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
1049  }
1051  }
1052  } else {
1053  /* Owner side is hanging up. */
1054  p->owner = NULL;
1055  if (p->chan) {
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));
1060  }
1061  if (!ast_test_flag(p, AST_UNREAL_CARETAKER_THREAD)) {
1062  /*
1063  * Need to actually hangup p->chan since nothing else is taking
1064  * care of it.
1065  */
1066  hangup_chan = 1;
1067  } else {
1068  ast_queue_hangup_with_cause(p->chan, cause);
1069  }
1070  }
1071  }
1072 
1073  /* this is one of our locked channels, doesn't matter which */
1074  ast_channel_tech_pvt_set(ast, NULL);
1075  ao2_ref(p, -1);
1076 
1077 unreal_hangup_cleanup:
1078  ao2_unlock(p);
1079  if (owner) {
1080  ast_channel_unlock(owner);
1081  ast_channel_unref(owner);
1082  }
1083  if (chan) {
1084  ast_channel_unlock(chan);
1085  if (hangup_chan) {
1086  ast_hangup(chan);
1087  }
1088  ast_channel_unref(chan);
1089  }
1090 
1091  /* leave with the channel locked that came in */
1092  ast_channel_lock(ast);
1093 
1094  return res;
1095 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
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 ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_channel * chan
Definition: core_unreal.h:94
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
int cause
Definition: bridge.h:386
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...
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
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, ast_channel_get_stream_topology(), ast_channel_is_multistream(), ast_channel_set_stream_topology(), 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_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_unreal_lock_all(), AST_UNREAL_MOH_INTERCEPT, ast_unreal_pvt::chan_old_topology, ast_unreal_pvt::owner_old_topology, and ast_control_t38_parameters::request_response.

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:
648  if (ast_test_flag(p, AST_UNREAL_MOH_INTERCEPT)) {
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:
655  if (ast_test_flag(p, AST_UNREAL_MOH_INTERCEPT)) {
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) {
742  p->owner_old_topology = NULL;
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 }
Main Channel structure associated with a channel.
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.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
enum ast_control_t38 request_response
ast_channel_state
ast_channel states
Definition: channelstate.h:35
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:7776
#define AST_UNREAL_MOH_INTERCEPT
Definition: core_unreal.h:109
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
struct ast_stream_topology * chan_old_topology
Definition: core_unreal.h:102
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_stream_topology * owner_old_topology
Definition: core_unreal.h:101
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:7766
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
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 ast_channel_lock_both, ast_channel_ref, ast_channel_unref, ast_unreal_pvt::chan, and ast_unreal_pvt::owner.

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

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 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * owner
Definition: core_unreal.h:93
struct ast_channel * chan
Definition: core_unreal.h:94
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
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)
assignedids
requestorChannel requesting creation. (NULL if none)
callidThread callid to use.
Returns
semi1_channel on success.
Return values
NULLon error.

Definition at line 1160 of file core_unreal.c.

References ao2_ref, ast_alloca, ast_atomic_fetchadd_int(), ast_channel_alloc, ast_channel_callid_set(), ast_channel_cc_params_init(), ast_channel_get_cc_config_params(), ast_channel_is_multistream(), ast_channel_release(), ast_channel_set_stream_topology(), AST_FLAG_DISABLE_DEVSTATE_CACHE, ast_format_cap_get_format(), ast_jb_configure(), 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_pvt::chan, ast_unreal_pvt::jb_conf, ast_unreal_pvt::name, ast_unreal_pvt::owner, RAII_VAR, ast_unreal_pvt::reqcap, and ast_unreal_pvt::reqtopology.

Referenced by local_request_with_stream_topology().

1164 {
1165  struct ast_channel *owner;
1166  struct ast_channel *chan;
1167  RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
1168  struct ast_assigned_ids id1 = {NULL, NULL};
1169  struct ast_assigned_ids id2 = {NULL, NULL};
1170  int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
1171  int i;
1172  struct ast_stream_topology *chan_topology;
1173  struct ast_stream *stream;
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 second channel, as we can't
1192  * share a single one between both.
1193  */
1194  chan_topology = ast_stream_topology_clone(p->reqtopology);
1195  if (!chan_topology) {
1196  return NULL;
1197  }
1198 
1199  for (i = 0; i < ast_stream_topology_get_count(chan_topology); ++i) {
1200  stream = ast_stream_topology_get_stream(chan_topology, i);
1201  /* We need to make sure that the ;2 channel has the opposite stream topology
1202  * of the first channel if the stream is one-way. I.e. if the first channel
1203  * is recvonly, the second channel has to be sendonly and vice versa.
1204  */
1207  } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
1209  }
1210  }
1211 
1212  /*
1213  * Allocate two new Asterisk channels
1214  *
1215  * Make sure that the ;2 channel gets the same linkedid as ;1.
1216  * You can't pass linkedid to both allocations since if linkedid
1217  * isn't set, then each channel will generate its own linkedid.
1218  */
1219  owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
1220  exten, context, &id1, requestor, 0,
1221  "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
1222  if (!owner) {
1223  ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
1224  ast_stream_topology_free(chan_topology);
1225  return NULL;
1226  }
1227 
1228  if (callid) {
1229  ast_channel_callid_set(owner, callid);
1230  }
1231 
1232  ast_channel_tech_set(owner, tech);
1233  ao2_ref(p, +1);
1234  ast_channel_tech_pvt_set(owner, p);
1235 
1236  ast_channel_nativeformats_set(owner, p->reqcap);
1237 
1238  if (ast_channel_is_multistream(owner)) {
1240  p->reqtopology = NULL;
1241  }
1242 
1243  /* Determine our read/write format and set it on each channel */
1244  fmt = ast_format_cap_get_format(p->reqcap, 0);
1245  if (!fmt) {
1246  ast_channel_tech_pvt_set(owner, NULL);
1247  ao2_ref(p, -1);
1248  ast_channel_unlock(owner);
1249  ast_channel_release(owner);
1250  return NULL;
1251  }
1252 
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);
1257 
1258  ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE);
1259 
1260  ast_jb_configure(owner, &p->jb_conf);
1261 
1262  if (ast_channel_cc_params_init(owner, requestor
1263  ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
1264  ast_channel_tech_pvt_set(owner, NULL);
1265  ao2_ref(p, -1);
1266  ast_channel_tech_pvt_set(owner, NULL);
1267  ast_channel_unlock(owner);
1268  ast_channel_release(owner);
1269  return NULL;
1270  }
1271 
1272  p->owner = owner;
1273  ast_channel_unlock(owner);
1274 
1275  chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
1276  exten, context, &id2, owner, 0,
1277  "%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
1278  if (!chan) {
1279  ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
1280  ast_channel_tech_pvt_set(owner, NULL);
1281  ao2_ref(p, -1);
1282  ast_channel_tech_pvt_set(owner, NULL);
1283  ast_channel_release(owner);
1284  return NULL;
1285  }
1286 
1287  if (callid) {
1288  ast_channel_callid_set(chan, callid);
1289  }
1290 
1291  ast_channel_tech_set(chan, tech);
1292  ao2_ref(p, +1);
1293  ast_channel_tech_pvt_set(chan, p);
1294 
1295  ast_channel_nativeformats_set(chan, p->reqcap);
1296 
1297  if (ast_channel_is_multistream(chan)) {
1298  ast_channel_set_stream_topology(chan, chan_topology);
1299  }
1300 
1301  /* Format was already determined when setting up owner */
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);
1306 
1307  ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE);
1308 
1309  p->chan = chan;
1310  ast_channel_unlock(chan);
1311 
1312  return owner;
1313 }
Main Channel structure associated with a channel.
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
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:604
Definition of a media format.
Definition: format.c:43
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
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:10474
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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:10451
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:288
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
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
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
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:1258
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100
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
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 ast_channel_bridge_peer(), ast_channel_queryoption(), ast_channel_ref, ast_channel_unref, 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 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
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:7442
struct ast_channel * owner
Definition: core_unreal.h:93
const char * data
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_ref(c)
Increase channel reference count.
Definition: channel.h:2947
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:10564
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
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_ref, AST_FRAME_HTML, ast_frame::data, ast_frame::datalen, ast_frame_subclass::integer, 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 }
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_frame_subclass subclass
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
union ast_frame::@224 data
Data structure associated with a single frame of data.
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_ref, AST_FRAME_TEXT, ast_frame::data, ast_frame::datalen, 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 }
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 ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
union ast_frame::@224 data
Data structure associated with a single frame of data.
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_ref, AST_CHAN_WRITE_INFO_T_VERSION, ast_channel_ref, ast_channel_unref, AST_OPTION_CHANNEL_WRITE, ast_unreal_pvt::chan, ast_channel::data, and ast_unreal_pvt::owner.

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 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * owner
Definition: core_unreal.h:93
const char * data
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_channel * chan
Definition: core_unreal.h:94
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:591
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
#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:589
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
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
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_ref, ast_channel_get_default_stream(), AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frame::frametype, 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) {
336  if (!ast_channel_get_default_stream(ast, AST_MEDIA_TYPE_AUDIO)) {
337  return 0;
338  }
339  } else if (f->frametype == AST_FRAME_VIDEO ||
341  if (!ast_channel_get_default_stream(ast, AST_MEDIA_TYPE_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 }
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_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)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
enum ast_frame_type frametype
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 ast_channel_ref, 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(), and ast_unreal_write_stream().

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 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * owner
Definition: core_unreal.h:93
struct ast_frame_subclass subclass
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
struct ast_channel * chan
Definition: core_unreal.h:94
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
enum ast_frame_type frametype