Asterisk - The Open Source Telephony Project GIT-master-7921072
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.
Returns
pvt on success.
Return values
NULLon error.

Definition at line 1109 of file core_unreal.c.

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
#define NULL
Definition: resample.c:96
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition: stream.c:848
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91

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().

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

Definition at line 1126 of file core_unreal.c.

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}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
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_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
General jitterbuffer configuration.
Definition: abstract_jb.h:70
struct ast_jb_conf jb_conf
Definition: core_unreal.h:96
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100
long resync_threshold
Definition: jitterbuf.h:70

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

Referenced by ast_unreal_alloc(), and local_alloc().

◆ 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.

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}
#define ast_log
Definition: astobj2.c:42
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
static int answer(void *data)
Definition: chan_pjsip.c:683
const char * ast_channel_name(const struct ast_channel *chan)
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
@ AST_FRAME_CONTROL
@ AST_CONTROL_ANSWER
#define LOG_WARNING
Data structure associated with a single frame of data.

References answer(), 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().

◆ 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.

Definition at line 870 of file core_unreal.c.

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}
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
struct varshead * ast_channel_varshead(struct ast_channel *chan)
const char * ast_channel_musicclass(const struct ast_channel *chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
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:10450
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
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
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_parkinglot(const struct ast_channel *chan)
const char * ast_channel_peeraccount(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
int ast_channel_hangupcause(const struct ast_channel *chan)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
const char * ast_channel_language(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:8292
struct ast_party_caller * ast_channel_caller(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:8299
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
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:10473
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
#define ast_var_assign(name, value)
Definition: chanvars.h:40
const char * ast_var_full_name(const struct ast_var_t *var)
Definition: chanvars.c:75
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
char name[0]
Definition: chanvars.h:31
char * value
Definition: chanvars.h:30
struct ast_var_t::@211 entries

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().

◆ 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.

929{
930 struct ast_bridge_features *features;
931 struct ast_channel *chan;
932 struct ast_channel *owner;
933 ast_callid bridge_callid;
935
937 bridge_callid = bridge->callid;
939
940 {
942 p = ast_channel_tech_pvt(ast);
943 if (!p) {
944 return -1;
945 }
946 ao2_ref(p, +1);
947 }
948
949 {
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}
ast_mutex_t lock
Definition: app_sla.c:331
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
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 ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:470
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:590
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
ast_callid ast_channel_callid(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
unsigned int ast_callid
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
Structure that contains features information.
struct ast_flags feature_flags
ast_callid callid
Definition: bridge.h:361
Main Channel structure associated with a channel.
struct ast_bridge * bridge
struct ast_flags flags
#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
#define ast_set_flag(p, flag)
Definition: utils.h:70

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_channel::bridge, ast_bridge::callid, ast_bridge_features::feature_flags, ast_channel::flags, lock, NULL, RAII_VAR, SCOPED_AO2LOCK, and SCOPED_CHANNELLOCK.

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

◆ ast_unreal_destructor()

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.

1098{
1099 struct ast_unreal_pvt *doomed = vdoomed;
1100
1101 ao2_cleanup(doomed->reqcap);
1102 doomed->reqcap = NULL;
1104 doomed->reqtopology = NULL;
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

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().

◆ 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.

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);
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
@ AST_FRAME_DTMF_BEGIN
struct ast_frame_subclass subclass

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().

◆ 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.

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);
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}
@ AST_FRAME_DTMF_END

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().

◆ 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.

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}
struct ast_bridge * ast_channel_internal_bridge(const struct ast_channel *chan)
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
Structure that contains information about a bridge.
Definition: bridge.h:349
struct ast_channel * chan
Definition: core_unreal.h:94
struct ast_channel * owner
Definition: core_unreal.h:93

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.

◆ 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.

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. */
1042 p->chan = NULL;
1043 if (p->owner) {
1044 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
1045
1046 if (status) {
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) {
1058 ast_debug(2, "%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
1060 }
1062 /*
1063 * Need to actually hangup p->chan since nothing else is taking
1064 * care of it.
1065 */
1066 hangup_chan = 1;
1067 } else {
1069 }
1070 }
1071 }
1072
1073 /* this is one of our locked channels, doesn't matter which */
1075 ao2_ref(p, -1);
1076
1077unreal_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}
jack_status_t status
Definition: app_jack.c:146
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
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
#define ast_debug(level,...)
Log a DEBUG message.
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 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.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_clear_flag(p, flag)
Definition: utils.h:77

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_queue_hangup_with_cause(), ast_test_flag, AST_UNREAL_CARETAKER_THREAD, ast_unreal_lock_all(), ast_unreal_pvt::chan, NULL, ast_unreal_pvt::owner, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and status.

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

◆ 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.

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;
656 ast_moh_stop(ast);
657 break;
658 }
659 res = unreal_queue_indicate(p, ast, condition, data, datalen);
660 break;
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;
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 */
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 */
738 ast_unreal_lock_all(p, &chan, &owner);
739
740 if (owner) {
743 }
744
745 if (chan) {
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_free(a)
Definition: astmm.h:180
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
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_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_MEDIA_TYPE_IMAGE
Definition: codec.h:34
static int unreal_colp_redirect_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
Definition: core_unreal.c:477
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
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
#define AST_UNREAL_MOH_INTERCEPT
Definition: core_unreal.h:109
@ AST_T38_TERMINATED
@ AST_T38_NEGOTIATED
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_T38_PARAMETERS
@ AST_CONTROL_RINGING
@ AST_CONTROL_HOLD
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_MASQUERADE_NOTIFY
@ AST_CONTROL_PVT_CAUSE_CODE
#define LOG_ERROR
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:7765
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7775
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
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
enum ast_control_t38 request_response

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().

◆ 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.

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) {
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_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929

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().

◆ 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)
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.

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
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) {
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);
1255 ast_channel_set_readformat(owner, fmt);
1257
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)) {
1265 ao2_ref(p, -1);
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");
1281 ao2_ref(p, -1);
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
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);
1304 ast_channel_set_readformat(chan, fmt);
1306
1308
1309 p->chan = chan;
1310 ast_channel_unlock(chan);
1311
1312 return owner;
1313}
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
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_rawwriteformat(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_readformat(struct ast_channel *chan, struct ast_format *format)
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1029
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
static unsigned int name_sequence
Definition: core_unreal.c:45
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
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
@ AST_STREAM_STATE_RECVONLY
Set when the stream is receiving media only.
Definition: stream.h:90
@ AST_STREAM_STATE_SENDONLY
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
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
const char * uniqueid2
Definition: channel.h:606
const char * uniqueid
Definition: channel.h:605
const char *const type
Definition: channel.h:629
Definition of a media format.
Definition: format.c:43
char name[AST_MAX_EXTENSION+AST_MAX_CONTEXT+2]
Definition: core_unreal.h:99

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_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_strlen_zero(), ast_unreal_pvt::chan, voicemailpwcheck::context, 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().

◆ 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.

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}
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:10563
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:7441
#define AST_OPTION_T38_STATE
const char * data

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, ast_channel::data, and ast_unreal_pvt::owner.

◆ 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.

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

References ast_null_frame.

◆ 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.

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}
@ AST_FRAME_HTML
union ast_frame::@226 data

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().

◆ 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.

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}
char * text
Definition: app_queue.c:1639
@ AST_FRAME_TEXT

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, text, and unreal_queue_frame().

◆ 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.

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
156setoption_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}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:591
#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
ast_acf_write_fn_t write_fn
Definition: channel.h:593
struct ast_channel * chan
Definition: channel.h:594
const char * value
Definition: channel.h:597
const char * function
Definition: channel.h:595

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_chan_write_info_t::chan, ast_unreal_pvt::chan, ast_chan_write_info_t::data, ast_channel::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().

◆ 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.

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

References ast_unreal_write_stream().

◆ 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.

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}
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.
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
Definition: core_unreal.c:295
@ AST_FRAME_VIDEO
@ AST_FRAME_VOICE
@ AST_CONTROL_VIDUPDATE
enum ast_frame_type frametype

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().

◆ 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.

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) {
306 } else if (ast == p->chan) {
308 }
309
310 return res;
311}
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:2920
#define AST_UNREAL_NO_OPTIMIZATION
Definition: core_unreal.h:108

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().

◆ 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.

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 */
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}
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:9267
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:8696

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().

◆ 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.

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
588 }
589 }
590
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}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
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:11007
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
struct ast_filestream * stream

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, ast_unreal_pvt::owner, and ast_channel::stream.

Referenced by ast_unreal_indicate().

◆ 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.

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
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) {
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) {
248 }
249 ao2_lock(p);
250
251 return 0;
252}
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_generator * ast_channel_generator(const struct ast_channel *chan)
@ AST_STATE_RINGING
Definition: channelstate.h:41
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7385

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().

◆ 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.

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) {
455 }
456 }
457 } else {
458 ast_debug(4, "Blocked indication %d\n", condition);
459 }
460 ao2_unlock(p);
461
462 return res;
463}
@ AST_T38_REQUEST_PARMS

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::data, ast_frame::datalen, ast_frame::frametype, ast_control_t38_parameters::request_response, and unreal_queue_frame().

Referenced by ast_unreal_indicate().

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().