Asterisk - The Open Source Telephony Project GIT-master-a63eec2
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions
core_unreal.h File Reference

Unreal channel derivative framework. More...

#include "asterisk/astobj2.h"
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
#include "asterisk/abstract_jb.h"
Include dependency graph for core_unreal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_unreal_pvt
 The base pvt structure for local channel derivatives. More...
 
struct  ast_unreal_pvt_callbacks
 Callbacks that can be provided by concrete implementations of the unreal channel driver that will be called when events occur in the unreal layer. More...
 

Macros

#define AST_UNREAL_CARETAKER_THREAD   (1 << 0)
 
#define AST_UNREAL_IS_OUTBOUND(a, b)   ((a) == (b)->chan ? 1 : 0)
 
#define AST_UNREAL_MOH_INTERCEPT   (1 << 2)
 
#define AST_UNREAL_NO_OPTIMIZATION   (1 << 1)
 
#define AST_UNREAL_OPTIMIZE_BEGUN   (1 << 3)
 

Enumerations

enum  ast_unreal_channel_indicator { AST_UNREAL_OWNER , AST_UNREAL_CHAN }
 

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.
 
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.
 
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.
 
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.
 
void ast_unreal_destructor (void *vdoomed)
 struct ast_unreal_pvt destructor.
 
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.
 
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.
 
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.
 
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 *chan, 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)
 

Detailed Description

Unreal channel derivative framework.

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

See Also:

Definition in file core_unreal.h.

Macro Definition Documentation

◆ AST_UNREAL_CARETAKER_THREAD

#define AST_UNREAL_CARETAKER_THREAD   (1 << 0)

The ;2 side launched a PBX, was pushed into a bridge, or was masqueraded into an application.

Definition at line 107 of file core_unreal.h.

◆ AST_UNREAL_IS_OUTBOUND

#define AST_UNREAL_IS_OUTBOUND (   a,
  b 
)    ((a) == (b)->chan ? 1 : 0)

Definition at line 105 of file core_unreal.h.

◆ AST_UNREAL_MOH_INTERCEPT

#define AST_UNREAL_MOH_INTERCEPT   (1 << 2)

Intercept and act on hold/unhold control frames

Definition at line 109 of file core_unreal.h.

◆ AST_UNREAL_NO_OPTIMIZATION

#define AST_UNREAL_NO_OPTIMIZATION   (1 << 1)

Do not optimize out the unreal channels

Definition at line 108 of file core_unreal.h.

◆ AST_UNREAL_OPTIMIZE_BEGUN

#define AST_UNREAL_OPTIMIZE_BEGUN   (1 << 3)

Indicates that an optimization attempt has been started

Definition at line 110 of file core_unreal.h.

Enumeration Type Documentation

◆ ast_unreal_channel_indicator

Enumerator
AST_UNREAL_OWNER 
AST_UNREAL_CHAN 

Definition at line 49 of file core_unreal.h.

49 {
52};
@ AST_UNREAL_CHAN
Definition core_unreal.h:51
@ AST_UNREAL_OWNER
Definition core_unreal.h:50

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 1110 of file core_unreal.c.

1111{
1112 struct ast_stream_topology *topology;
1113 struct ast_unreal_pvt *unreal;
1114
1116 if (!topology) {
1117 return NULL;
1118 }
1119
1120 unreal = ast_unreal_alloc_stream_topology(size, destructor, topology);
1121
1122 ast_stream_topology_free(topology);
1123
1124 return unreal;
1125}
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.
#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:746
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition stream.c:851
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 1127 of file core_unreal.c.

1128{
1129 struct ast_unreal_pvt *unreal;
1130
1131 static const struct ast_jb_conf jb_conf = {
1132 .flags = 0,
1133 .max_size = -1,
1134 .resync_threshold = -1,
1135 .impl = "",
1136 .target_extra = -1,
1137 };
1138
1139 unreal = ao2_alloc(size, destructor);
1140 if (!unreal) {
1141 return NULL;
1142 }
1143
1144 unreal->reqtopology = ast_stream_topology_clone(topology);
1145 if (!unreal->reqtopology) {
1146 ao2_ref(unreal, -1);
1147 return NULL;
1148 }
1149
1150 unreal->reqcap = ast_stream_topology_get_formats(topology);
1151 if (!unreal->reqcap) {
1152 ao2_ref(unreal, -1);
1153 return NULL;
1154 }
1155
1156 memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
1157
1158 return unreal;
1159}
#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:933
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition stream.c:670
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
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:687
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
#define AST_UNREAL_IS_OUTBOUND(a, b)
@ 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
891 ast_channel_language_set(semi2, ast_channel_language(semi1));
892 ast_channel_musicclass_set(semi2, ast_channel_musicclass(semi1));
893 ast_channel_parkinglot_set(semi2, ast_channel_parkinglot(semi1));
894
895 /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
896 ast_channel_accountcode_set(semi2, ast_channel_peeraccount(semi1));
897 ast_channel_peeraccount_set(semi2, ast_channel_accountcode(semi1));
898
900
901 /*
902 * Make sure we inherit the AST_CAUSE_ANSWERED_ELSEWHERE if it's
903 * set on the queue/dial call request in the dialplan.
904 */
907 }
908
909 /*
910 * Copy the channel variables from the semi1 channel to the
911 * outgoing channel.
912 *
913 * Note that due to certain assumptions, they MUST be in the
914 * same order.
915 */
917 clone_var = ast_var_assign(varptr->name, varptr->value);
918 if (clone_var) {
921 ast_var_value(clone_var));
922 }
923 }
924 ast_channel_datastore_inherit(semi1, semi2);
925
927}
#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:10465
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:2338
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_parkinglot(const struct ast_channel *chan)
ast_channel_adsicpe
Definition channel.h:888
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:1904
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:8307
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:8314
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe 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:10488
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:2103
#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.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
char name[0]
Definition chanvars.h:31
struct ast_var_t::@224 entries
char * value
Definition chanvars.h:30

References AST_CAUSE_ANSWERED_ELSEWHERE, ast_channel_accountcode(), ast_channel_adsicpe_set(), 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 929 of file core_unreal.c.

930{
931 struct ast_bridge_features *features;
932 struct ast_channel *chan;
933 struct ast_channel *owner;
934 ast_callid bridge_callid;
936
938 bridge_callid = bridge->callid;
940
941 {
943 p = ast_channel_tech_pvt(ast);
944 if (!p) {
945 return -1;
946 }
947 ao2_ref(p, +1);
948 }
949
950 {
952 chan = p->chan;
953 if (!chan) {
954 return -1;
955 }
956
957 owner = p->owner;
958 if (!owner) {
959 return -1;
960 }
961
962 ast_channel_ref(chan);
963 ast_channel_ref(owner);
964 }
965
966 if (bridge_callid) {
967 ast_callid chan_callid;
968 ast_callid owner_callid;
969
970 /* chan side call ID setting */
971 ast_channel_lock(chan);
972
973 chan_callid = ast_channel_callid(chan);
974 if (!chan_callid) {
975 ast_channel_callid_set(chan, bridge_callid);
976 }
977 ast_channel_unlock(chan);
978
979 /* owner side call ID setting */
980 ast_channel_lock(owner);
981
982 owner_callid = ast_channel_callid(owner);
983 if (!owner_callid) {
984 ast_channel_callid_set(owner, bridge_callid);
985 }
986
987 ast_channel_unlock(owner);
988 }
989
990 /* We are done with the owner now that its call ID matches the bridge */
991 ast_channel_unref(owner);
992 owner = NULL;
993
994 features = ast_bridge_features_new();
995 if (!features) {
996 ast_channel_unref(chan);
997 return -1;
998 }
999
1000 ast_set_flag(&features->feature_flags, flags);
1001
1002 /* Impart the semi2 channel into the bridge */
1003 if (ast_bridge_impart(bridge, chan, NULL, features,
1005 ast_channel_unref(chan);
1006 return -1;
1007 }
1008
1009 /* The bridge thread now controls the chan ref from the ast_unreal_pvt */
1010 ao2_lock(p);
1012 ao2_unlock(p);
1013
1014 ast_channel_unref(chan);
1015
1016 return 0;
1017}
ast_mutex_t lock
Definition app_sla.c:337
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition bridge.h:485
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition bridge.c:1947
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition bridge.h:474
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition bridge.h:594
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition bridge.c:3762
#define ast_channel_lock(chan)
Definition channel.h:2972
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:2997
ast_callid ast_channel_callid(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3008
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
#define ast_channel_unlock(chan)
Definition channel.h:2973
#define AST_UNREAL_CARETAKER_THREAD
unsigned int ast_callid
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition lock.h:611
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition lock.h:626
Structure that contains features information.
struct ast_flags feature_flags
ast_callid callid
Definition bridge.h:365
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:978
#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 1098 of file core_unreal.c.

1099{
1100 struct ast_unreal_pvt *doomed = vdoomed;
1101
1102 ao2_cleanup(doomed->reqcap);
1103 doomed->reqcap = NULL;
1105 doomed->reqtopology = NULL;
1108}
struct ast_stream_topology * chan_old_topology
struct ast_stream_topology * owner_old_topology

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:1181
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:353
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 1019 of file core_unreal.c.

1020{
1021 int hangup_chan = 0;
1022 int res = 0;
1023 int cause;
1024 struct ast_channel *owner = NULL;
1025 struct ast_channel *chan = NULL;
1026
1027 /* the pvt isn't going anywhere, it has a ref */
1028 ast_channel_unlock(ast);
1029
1030 /* lock everything */
1031 ast_unreal_lock_all(p, &chan, &owner);
1032
1033 if (ast != chan && ast != owner) {
1034 res = -1;
1035 goto unreal_hangup_cleanup;
1036 }
1037
1038 cause = ast_channel_hangupcause(ast);
1039
1040 if (ast == p->chan) {
1041 /* Outgoing side is hanging up. */
1043 p->chan = NULL;
1044 if (p->owner) {
1045 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
1046
1047 if (status) {
1049 pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
1050 }
1052 }
1053 } else {
1054 /* Owner side is hanging up. */
1055 p->owner = NULL;
1056 if (p->chan) {
1057 if (cause == AST_CAUSE_ANSWERED_ELSEWHERE) {
1059 ast_debug(2, "%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
1061 }
1063 /*
1064 * Need to actually hangup p->chan since nothing else is taking
1065 * care of it.
1066 */
1067 hangup_chan = 1;
1068 } else {
1070 }
1071 }
1072 }
1073
1074 /* this is one of our locked channels, doesn't matter which */
1076 ao2_ref(p, -1);
1077
1078unreal_hangup_cleanup:
1079 ao2_unlock(p);
1080 if (owner) {
1081 ast_channel_unlock(owner);
1082 ast_channel_unref(owner);
1083 }
1084 if (chan) {
1085 ast_channel_unlock(chan);
1086 if (hangup_chan) {
1087 ast_hangup(chan);
1088 }
1089 ast_channel_unref(chan);
1090 }
1091
1092 /* leave with the channel locked that came in */
1093 ast_channel_lock(ast);
1094
1095 return res;
1096}
jack_status_t status
Definition app_jack.c:149
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2511
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition channel.c:1205
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
@ AST_STATE_RING
@ 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)
static int unreal_queue_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition, const void *data, size_t datalen)
static int unreal_colp_stream_topology_request_change(struct ast_unreal_pvt *p, struct ast_channel *ast, const struct ast_stream_topology *topology)
#define AST_UNREAL_MOH_INTERCEPT
@ 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_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:7748
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7758
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition stream.c:652
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:751
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:2979

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 1161 of file core_unreal.c.

1165{
1166 struct ast_channel *owner;
1167 struct ast_channel *chan;
1168 RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
1169 struct ast_assigned_ids id1 = {NULL, NULL};
1170 struct ast_assigned_ids id2 = {NULL, NULL};
1171 int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
1172 int i;
1173 RAII_VAR(struct ast_stream_topology *, chan_topology, NULL, ast_stream_topology_free);
1174 struct ast_stream *stream;
1175
1176 /* set unique ids for the two channels */
1177 if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
1178 id1.uniqueid = assignedids->uniqueid;
1179 id2.uniqueid = assignedids->uniqueid2;
1180 }
1181
1182 /* if id1 given but not id2, use default of id1;2 */
1183 if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
1184 char *uniqueid2;
1185
1186 uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 3);
1187 strcpy(uniqueid2, id1.uniqueid);/* Safe */
1188 strcat(uniqueid2, ";2");/* Safe */
1189 id2.uniqueid = uniqueid2;
1190 }
1191
1192 /* We need to create a topology to place on the second channel, as we can't
1193 * share a single one between both.
1194 */
1195 chan_topology = ast_stream_topology_clone(p->reqtopology);
1196 if (!chan_topology) {
1197 return NULL;
1198 }
1199
1200 for (i = 0; i < ast_stream_topology_get_count(chan_topology); ++i) {
1201 stream = ast_stream_topology_get_stream(chan_topology, i);
1202 /* We need to make sure that the ;2 channel has the opposite stream topology
1203 * of the first channel if the stream is one-way. I.e. if the first channel
1204 * is recvonly, the second channel has to be sendonly and vice versa.
1205 */
1208 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
1210 }
1211 }
1212
1213 /*
1214 * Allocate two new Asterisk channels
1215 *
1216 * Make sure that the ;2 channel gets the same linkedid as ;1.
1217 * You can't pass linkedid to both allocations since if linkedid
1218 * isn't set, then each channel will generate its own linkedid.
1219 */
1220 owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
1221 exten, context, &id1, requestor, 0,
1222 "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
1223 if (!owner) {
1224 ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
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, ao2_bump(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.
#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:1299
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:1552
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition channel.h:1049
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:764
@ 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:791
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition stream.c:768
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition stream.c:373
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:606
const char * uniqueid2
Definition channel.h:608
const char * uniqueid
Definition channel.h:607
const char *const type
Definition channel.h:649
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_bump, 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, 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:10578
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:7424
#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}
union ast_frame::@239 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}

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}
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition channel.h:593
#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:591
ast_acf_write_fn_t write_fn
Definition channel.h:595
struct ast_channel * chan
Definition channel.h:596
const char * value
Definition channel.h:599
const char * function
Definition channel.h:597

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, 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)

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