54#define TEST_CATEGORY "/main/cel/"
56#define CHANNEL_TECH_NAME "CELTestChannel"
58#define TEST_BACKEND_NAME "CEL Test Logging"
81 .description =
"Mock channel technology for CEL tests",
93#define APPEND_EVENT(chan, ev_type, userevent, extra) do { \
94 if (append_expected_event(chan, ev_type, userevent, extra, NULL)) { \
95 return AST_TEST_FAIL; \
99#define APPEND_EVENT_PEER(chan, ev_type, userevent, extra, peer) do { \
100 if (append_expected_event(chan, ev_type, userevent, extra, peer)) { \
101 return AST_TEST_FAIL; \
105#define APPEND_EVENT_SNAPSHOT(snapshot, ev_type, userevent, extra, peer) do { \
106 if (append_expected_event_snapshot(snapshot, ev_type, userevent, extra, peer)) { \
107 return AST_TEST_FAIL; \
111#define APPEND_DUMMY_EVENT() do { \
112 if (append_dummy_event()) { \
113 return AST_TEST_FAIL; \
117#define BRIDGE_EXIT(channel, bridge) do { \
118 ast_test_validate(test, !ast_bridge_depart(channel)); \
119 BRIDGE_EXIT_EVENT(channel, bridge); \
123#define BRIDGE_EXIT_EVENT(channel, bridge) do { \
124 RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \
125 peer_str = test_cel_generate_peer_str(channel, bridge); \
126 ast_test_validate(test, peer_str != NULL); \
127 BRIDGE_EXIT_EVENT_PEER(channel, bridge, ast_str_buffer(peer_str)); \
130#define BRIDGE_EXIT_EVENT_PEER(channel, bridge, peer) do { \
131 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
132 extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \
133 ast_test_validate(test, extra != NULL); \
134 APPEND_EVENT_PEER(channel, AST_CEL_BRIDGE_EXIT, NULL, extra, peer); \
137#define BRIDGE_EXIT_SNAPSHOT(channel, bridge) do { \
138 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
139 RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \
140 peer_str = test_cel_generate_peer_str_snapshot(channel, bridge); \
141 ast_test_validate(test, peer_str != NULL); \
142 extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \
143 ast_test_validate(test, extra != NULL); \
144 APPEND_EVENT_SNAPSHOT(channel, AST_CEL_BRIDGE_EXIT, NULL, extra, ast_str_buffer(peer_str)); \
147#define BRIDGE_ENTER(channel, bridge) do { \
148 ast_test_validate(test, !ast_bridge_impart(bridge, channel, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); \
150 BRIDGE_ENTER_EVENT(channel, bridge); \
154#define BRIDGE_ENTER_EVENT(channel, bridge) do { \
155 RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \
156 peer_str = test_cel_generate_peer_str(channel, bridge); \
157 ast_test_validate(test, peer_str != NULL); \
158 BRIDGE_ENTER_EVENT_PEER(channel, bridge, ast_str_buffer(peer_str)); \
161#define BRIDGE_ENTER_EVENT_PEER(channel, bridge, peer) do { \
162 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
163 extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \
164 ast_test_validate(test, extra != NULL); \
165 APPEND_EVENT_PEER(channel, AST_CEL_BRIDGE_ENTER, NULL, extra, peer); \
168#define BLINDTRANSFER_EVENT(channel, bridge, extension, context) do { \
169 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
170 extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}", \
171 "extension", extension, \
172 "context", context, \
173 "bridge_id", bridge->uniqueid, \
174 "transferee_channel_name", "N/A", \
175 "transferee_channel_uniqueid", "N/A"); \
176 ast_test_validate(test, extra != NULL); \
177 APPEND_EVENT(channel, AST_CEL_BLINDTRANSFER, NULL, extra); \
180#define ATTENDEDTRANSFER_BRIDGE(channel1, bridge1, channel2, bridge2, channel3, channel4) do { \
181 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
182 extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}", \
183 "bridge1_id", bridge1->uniqueid, \
184 "channel2_name", ast_channel_name(channel2), \
185 "channel2_uniqueid", ast_channel_uniqueid(channel2), \
186 "bridge2_id", bridge2->uniqueid, \
187 "transferee_channel_name", ast_channel_name(channel4), \
188 "transferee_channel_uniqueid", ast_channel_uniqueid(channel4), \
189 "transfer_target_channel_name", ast_channel_name(channel3), \
190 "transfer_target_channel_uniqueid", ast_channel_uniqueid(channel3)); \
191 ast_test_validate(test, extra != NULL); \
192 APPEND_EVENT(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra); \
196#define ALICE_CALLERID { .id.name.str = "Alice", .id.name.valid = 1, .id.number.str = "100", .id.number.valid = 1, }
199#define BOB_CALLERID { .id.name.str = "Bob", .id.name.valid = 1, .id.number.str = "200", .id.number.valid = 1, }
202#define CHARLIE_CALLERID { .id.name.str = "Charlie", .id.name.valid = 1, .id.number.str = "300", .id.number.valid = 1, }
205#define DAVID_CALLERID { .id.name.str = "David", .id.name.valid = 1, .id.number.str = "400", .id.number.valid = 1, }
208#define SET_FORMATS(chan) do {\
209 struct ast_format_cap *caps;\
210 caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);\
211 ast_format_cap_append(caps, ast_format_ulaw, 0);\
212 ast_channel_nativeformats_set((chan), caps);\
213 ast_channel_set_writeformat((chan), ast_format_ulaw);\
214 ast_channel_set_rawwriteformat((chan), ast_format_ulaw);\
215 ast_channel_set_readformat((chan), ast_format_ulaw);\
216 ast_channel_set_rawreadformat((chan), ast_format_ulaw);\
221#define CREATE_ALICE_CHANNEL(channel_var, caller_id) do { \
222 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "100", "100", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Alice"); \
223 SET_FORMATS((channel_var));\
224 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
225 ast_channel_unlock((channel_var)); \
229#define CREATE_BOB_CHANNEL(channel_var, caller_id) do { \
230 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "200", "200", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Bob"); \
231 SET_FORMATS((channel_var));\
232 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
233 ast_channel_unlock((channel_var)); \
237#define CREATE_CHARLIE_CHANNEL(channel_var, caller_id) do { \
238 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "300", "300", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \
239 SET_FORMATS((channel_var));\
240 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
241 ast_channel_unlock((channel_var)); \
245#define CREATE_DAVID_CHANNEL(channel_var, caller_id) do { \
246 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "400", "400", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/David"); \
247 SET_FORMATS((channel_var));\
248 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
249 ast_channel_unlock((channel_var)); \
253#define EMULATE_APP_DATA(channel, priority, application, data) do { \
254 if ((priority) > 0) { \
255 ast_channel_priority_set((channel), (priority)); \
257 ast_channel_appl_set((channel), (application)); \
258 ast_channel_data_set((channel), (data)); \
259 ast_channel_publish_snapshot((channel)); \
262#define ANSWER_CHANNEL(chan) do { \
263 EMULATE_APP_DATA(chan, 1, "Answer", ""); \
264 ANSWER_NO_APP(chan); \
267#define ANSWER_NO_APP(chan) do { \
268 ast_setstate(chan, AST_STATE_UP); \
269 APPEND_EVENT(chan, AST_CEL_ANSWER, NULL, NULL); \
273#define HANGUP_CHANNEL(channel, cause, dialstatus) do { \
274 ast_channel_hangupcause_set((channel), (cause)); \
275 ao2_ref(channel, +1); \
276 ast_hangup((channel)); \
277 HANGUP_EVENT(channel, cause, dialstatus); \
278 APPEND_EVENT(channel, AST_CEL_CHANNEL_END, NULL, NULL); \
279 ao2_cleanup(ast_channel_snapshot_get_latest(ast_channel_uniqueid(channel))); \
280 ao2_cleanup(channel); \
284#define HANGUP_EVENT(channel, cause, dialstatus) do { \
285 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
286 extra = ast_json_pack("{s: i, s: s, s: s}", \
287 "hangupcause", cause, \
288 "hangupsource", "", \
289 "dialstatus", dialstatus); \
290 ast_test_validate(test, extra != NULL); \
291 APPEND_EVENT(channel, AST_CEL_HANGUP, NULL, extra); \
299 const char *userdefevname,
306 const char *userdefevname,
311static int append_dummy_event(
void);
318 char *current_chan =
NULL;
337 if (!current_snapshot) {
341 ast_str_append(&peer_str, 0,
"%s,", current_snapshot->base->name);
400 info->name = __func__;
402 info->summary =
"Test the CEL records created when a channel is created";
404 "Test the CEL records created when a channel is created";
424 info->name = __func__;
426 info->summary =
"Test inbound unanswered calls";
428 "Test CEL records for a call that is\n"
429 "inbound to Asterisk, executes some dialplan, but\n"
430 "is never answered.";
452 .id.number.valid = 1, };
456 info->name = __func__;
458 info->summary =
"Test outbound unanswered calls";
460 "Test CEL records for a call that is\n"
461 "outbound to Asterisk but is never answered.";
485 info->name = __func__;
487 info->summary =
"Test CEL for a single party";
489 "Test CEL records for a call that is\n"
490 "answered, but only involves a single channel";
514 info->name = __func__;
516 info->summary =
"Test CEL for a single party entering/leaving a bridge";
518 "Test CEL records for a call that is\n"
519 "answered, enters a bridge, and leaves it.";
525 ast_test_validate(
test, bridge !=
NULL);
552 info->name = __func__;
554 info->summary =
"Test CEL for a single party entering/leaving a bridge";
556 "Test CEL records for a call that is\n"
557 "answered, enters a bridge, and leaves it.";
563 ast_test_validate(
test, bridge !=
NULL);
595 info->name = __func__;
597 info->summary =
"Test CEL for a single party entering/leaving a bridge";
599 "Test CEL records for a call that is\n"
600 "answered, enters a bridge, and leaves it. In this scenario, the\n"
601 "Party A should answer the bridge first.";
607 ast_test_validate(
test, bridge !=
NULL);
643 info->name = __func__;
645 info->summary =
"Test CEL for a single party entering/leaving a bridge";
647 "Test CEL records for a call that is\n"
648 "answered, enters a bridge, and leaves it. In this scenario, the\n"
649 "Party B should answer the bridge first.";
655 ast_test_validate(
test, bridge !=
NULL);
697 info->name = __func__;
699 info->summary =
"Test CEL for a single party entering/leaving a multi-party bridge";
701 "Test CEL records for a call that is\n"
702 "answered, enters a bridge, and leaves it. A total of three\n"
703 "parties perform this action.";
709 ast_test_validate(
test, bridge !=
NULL);
745#define EMULATE_DIAL(channel, dialstring) do { \
746 EMULATE_APP_DATA(channel, 1, "Dial", dialstring); \
747 if (append_expected_event(channel, AST_CEL_APP_START, NULL, NULL, NULL)) { \
748 return AST_TEST_FAIL; \
752#define START_DIALED(caller, callee) \
753 START_DIALED_FULL(caller, callee, "200", "Bob")
755#define START_DIALED_FULL(caller, callee, number, name) do { \
756 callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, number, NULL, NULL, NULL, caller, 0, CHANNEL_TECH_NAME "/" name); \
757 SET_FORMATS(callee);\
758 ast_channel_unlock(callee); \
759 if (append_expected_event(callee, AST_CEL_CHANNEL_START, NULL, NULL, NULL)) { \
760 return AST_TEST_FAIL; \
762 ast_set_flag(ast_channel_flags(callee), AST_FLAG_OUTGOING); \
763 EMULATE_APP_DATA(callee, 0, "AppDial", "(Outgoing Line)"); \
764 ast_channel_publish_dial(caller, callee, name, NULL); \
775 info->name = __func__;
777 info->summary =
"Test CEL for a dial that isn't answered";
779 "Test CEL records for a channel that\n"
780 "performs a dial operation that isn't answered";
809 info->name = __func__;
811 info->summary =
"Test CEL for a dial that isn't answered";
813 "Test CEL records for a channel that\n"
814 "performs a dial operation that isn't answered";
844 info->name = __func__;
846 info->summary =
"Test CEL for a dial that results in a busy";
848 "Test CEL records for a channel that\n"
849 "performs a dial operation to an endpoint that's busy";
878 info->name = __func__;
880 info->summary =
"Test CEL for a dial that results in congestion";
882 "Test CEL records for a channel that\n"
883 "performs a dial operation to an endpoint that's congested";
912 info->name = __func__;
914 info->summary =
"Test CEL for a dial that results in unavailable";
916 "Test CEL records for a channel that\n"
917 "performs a dial operation to an endpoint that's unavailable";
946 info->name = __func__;
948 info->summary =
"Test CEL for a dial where the caller cancels";
950 "Test CEL records for a channel that\n"
951 "performs a dial operation to an endpoint but then decides\n"
952 "to hang up, cancelling the dial";
983 info->name = __func__;
985 info->summary =
"Test a parallel dial where all channels fail to answer";
987 "This tests dialing three parties: Bob, Charlie, David. Charlie\n"
988 "returns BUSY; David returns CONGESTION; Bob fails to answer and\n"
989 "Alice hangs up. Three records are created for Alice as a result.";
1034 info->name = __func__;
1036 info->summary =
"Test dialing, answering, and not going into a bridge.";
1038 "This is a weird one, but theoretically possible. You can perform\n"
1039 "a dial, then bounce both channels to different priorities and\n"
1040 "never have them enter a bridge together. Ew. This makes sure that\n"
1041 "when we answer, we get a CEL, it gets ended at that point, and\n"
1042 "that it gets finalized appropriately.";
1079 info->name = __func__;
1081 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
1083 "The most 'basic' of scenarios";
1089 ast_test_validate(
test, bridge !=
NULL);
1126 info->name = __func__;
1128 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
1130 "The most 'basic' of scenarios";
1136 ast_test_validate(
test, bridge !=
NULL);
1176 info->name = __func__;
1178 info->summary =
"Test dialing, answering, and going into a multi-party bridge";
1180 "A little tricky to get to do, but possible with some redirects.";
1186 ast_test_validate(
test, bridge !=
NULL);
1251 info->name = __func__;
1253 info->summary =
"Test blind transfers to an extension";
1255 "This test creates two channels, bridges them, and then"
1256 " blind transfers the bridge to an extension.";
1262 ast_test_validate(
test, bridge !=
NULL);
1275 "transfer_extension",
"transfer_context");
1276 if (!transfer_msg) {
1282 if (!transfer_msg->bridge) {
1321 info->name = __func__;
1323 info->summary =
"Test attended transfers between two pairs of bridged parties";
1325 "This test creates four channels, places each pair in"
1326 " a bridge, and then attended transfers the bridges"
1334 ast_test_validate(
test, bridge1 !=
NULL);
1346 ast_test_validate(
test, bridge2 !=
NULL);
1402 info->name = __func__;
1404 info->summary =
"Test attended transfers between two pairs of"
1405 " bridged parties that results in a bridge merge";
1407 "This test creates four channels, places each pair"
1408 " in a bridge, and then attended transfers the bridges"
1409 " together causing a bridge merge.";
1417 "test_cel",
"test_cel_atxfer_bridges_merge_1",
NULL);
1418 ast_test_validate(
test, bridge1 !=
NULL);
1431 "test_cel",
"test_cel_atxfer_bridges_merge_2",
NULL);
1432 ast_test_validate(
test, bridge2 !=
NULL);
1490 info->name = __func__;
1492 info->summary =
"Test attended transfers between two pairs of"
1493 " bridged parties that results in a bridge merge";
1495 "This test creates four channels, places each pair"
1496 " in a bridge, and then attended transfers the bridges"
1497 " together causing a bridge link.";
1507 "test_cel",
"test_cel_atxfer_bridges_link_1",
NULL);
1508 ast_test_validate(
test, bridge1 !=
NULL);
1523 "test_cel",
"test_cel_atxfer_bridges_link_2",
NULL);
1524 ast_test_validate(
test, bridge2 !=
NULL);
1571 info->name = __func__;
1573 info->summary =
"Test call pickup";
1575 "Test CEL records for a call that is\n"
1576 "inbound to Asterisk, executes some dialplan, and\n"
1599 ast_test_validate(
test, extra !=
NULL);
1631 info->name = __func__;
1633 info->summary =
"Test local channel optimization record generation";
1635 "Test CEL records for two local channels being optimized\n"
1636 "out by sending a messages indicating local optimization\n"
1644 ast_test_validate(
test, mc_blob !=
NULL);
1652 ast_test_validate(
test, alice_snapshot !=
NULL);
1657 ast_test_validate(
test, bob_snapshot !=
NULL);
1663 ast_test_validate(
test, local_opt_begin !=
NULL);
1666 ast_test_validate(
test, local_opt_end !=
NULL);
1671 extra =
ast_json_pack(
"{s: s, s: s}",
"local_two", bob_snapshot->base->name,
1672 "local_two_uniqueid", bob_snapshot->base->uniqueid);
1673 ast_test_validate(
test, extra !=
NULL);
1719 struct timespec
end = {
1720 .tv_sec = start.tv_sec + 15,
1721 .tv_nsec = start.tv_usec * 1000
1742static int append_dummy_event(
void)
1759 const char *userdefevname,
1775 const char *userdefevname,
1793 const char *chan_name;
1811 if (expected <= received) {
1862 if (!intersection) {
1866 while ((chan =
strsep(&str1_dup,
","))) {
1870 while ((chan =
strsep(&str2_dup,
","))) {
1923 if (!str1 && !str2) {
1936 return !strcmp(str1, str2);
1984 const char *ie_type_name;
1990 switch (ie_pltype) {
2020 " did not match number of received events (%d).\n",
2030 while (rx_event && ex_event) {
2043 ?
" (wildcard match)" :
"");
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ao2_iterator_next(iter)
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_MUTEX
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define ao2_alloc(data_size, destructor_fn)
struct ast_bridge * ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Create a new base class bridge.
#define ast_bridge_unlock(bridge)
Unlock the bridge.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
@ AST_BRIDGE_CAPABILITY_MULTIMIX
@ AST_BRIDGE_CAPABILITY_NATIVE
@ AST_BRIDGE_CAPABILITY_1TO1MIX
@ AST_BRIDGE_TRANSFER_SUCCESS
#define ast_bridge_lock(bridge)
Lock the bridge.
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Basic bridge subclass API.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_TO
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
@ AST_BRIDGE_FLAG_TRANSFER_PROHIBITED
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
Internal Asterisk hangup causes.
#define AST_CAUSE_CONGESTION
#define AST_CAUSE_NO_ROUTE_DESTINATION
#define AST_CAUSE_NO_ANSWER
void ast_cel_set_config(struct ast_cel_general_config *config)
Set the current CEL configuration.
struct ast_event * ast_cel_create_event(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const char *userdefevname, struct ast_json *extra, const char *peer_str)
Allocate and populate a CEL event structure.
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
ast_cel_event_type
CEL event types.
@ AST_CEL_CHANNEL_END
channel end
@ AST_CEL_ANSWER
A ringing phone is answered.
@ AST_CEL_BRIDGE_EXIT
channel exits a bridge
@ AST_CEL_HANGUP
hangup terminates connection
@ AST_CEL_PICKUP
a directed pickup was performed on this channel
@ AST_CEL_APP_START
an app starts
@ AST_CEL_CHANNEL_START
channel birth
@ AST_CEL_ATTENDEDTRANSFER
a transfer occurs
@ AST_CEL_BRIDGE_ENTER
channel enters a bridge
@ AST_CEL_BLINDTRANSFER
a transfer occurs
@ AST_CEL_LOCAL_OPTIMIZE
A local channel optimization occurred, this marks the end.
void * ast_cel_general_config_alloc(void)
Allocate a CEL configuration object.
struct ast_cel_general_config * ast_cel_get_config(void)
Obtain the current CEL configuration.
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
const char * ast_cel_get_type_name(enum ast_cel_event_type type)
Get the name of a CEL event type.
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
#define ast_channel_lock(chan)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state)
#define ast_channel_unlock(chan)
Local proxy channel special access.
struct stasis_message_type * ast_local_optimization_end_type(void)
Message type for when a local channel optimization completes.
struct stasis_message_type * ast_local_optimization_begin_type(void)
Message type for when a local channel optimization begins.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
size_t ast_event_get_size(const struct ast_event *event)
Get the size of an event.
const char * ast_event_get_ie_type_name(enum ast_event_ie_type ie_type)
Get the string representation of an information element type.
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
enum ast_event_ie_pltype ast_event_get_ie_pltype(enum ast_event_ie_type ie_type)
Get the payload type for a given information element type.
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator)
Get the type of the current IE in the iterator instance.
int ast_event_iterator_next(struct ast_event_iterator *iterator)
Move iterator instance to next IE.
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
int ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event)
Initialize an event iterator instance.
const char * ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
Get the value of the current IE in the iterator as a string payload.
uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator)
Get the value of the current IE in the iterator as an integer payload.
ast_event_ie_type
Event Information Element types.
@ AST_EVENT_IE_CEL_EVENT_TIME
Channel Event Time (seconds) Used by: AST_EVENT_CEL Payload type: UINT.
@ AST_EVENT_IE_CEL_CHANNAME
Channel Event channel name Used by: AST_EVENT_CEL Payload type: STR.
@ AST_EVENT_IE_CEL_EVENT_TIME_USEC
Channel Event Time (micro-seconds) Used by: AST_EVENT_CEL Payload type: UINT.
@ AST_EVENT_IE_CEL_EVENT_TYPE
Channel Event Type Used by: AST_EVENT_CEL Payload type: UINT.
@ AST_EVENT_IE_CEL_PEER
Channel Event Peer – for Things involving multiple channels, like BRIDGE Used by: AST_EVENT_CEL Paylo...
ast_event_ie_pltype
Payload types for event information elements.
@ AST_EVENT_IE_PLTYPE_RAW
@ AST_EVENT_IE_PLTYPE_UINT
@ AST_EVENT_IE_PLTYPE_BITFLAGS
@ AST_EVENT_IE_PLTYPE_STR
@ AST_EVENT_IE_PLTYPE_UNKNOWN
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate.
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
char * strsep(char **str, const char *delims)
Asterisk JSON abstraction layer.
struct ast_json * ast_json_null(void)
Get the JSON null value.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
A set of macros to manage forward-linked lists.
#define ast_cond_destroy(cond)
#define ast_cond_init(cond, attr)
#define ast_cond_timedwait(cond, mutex, time)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
pthread_cond_t ast_cond_t
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define ast_cond_signal(cond)
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
static int debug
Global debug status.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
void ast_bridge_publish_blind_transfer(struct ast_blind_transfer_message *transfer_message)
Publish a blind transfer event.
struct ast_bridge_snapshot * ast_bridge_get_snapshot(struct ast_bridge *bridge)
Returns the current snapshot for the bridge.
struct ast_bridge_snapshot * ast_bridge_snapshot_create(struct ast_bridge *bridge)
Generate a snapshot of the bridge state. This is an ao2 object, so ao2_cleanup() to deallocate.
struct ast_blind_transfer_message * ast_blind_transfer_message_create(int is_external, struct ast_channel *transferer, const char *exten, const char *context)
Create a blind transfer message to be published.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
void ast_str_container_remove(struct ao2_container *str_container, const char *remove)
Removes a string from a string container allocated by ast_str_container_alloc.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Message published during a blind transfer.
Structure that contains a snapshot of information about a bridge.
struct ao2_container * channels
Structure that contains information about a bridge.
A structure to hold CEL global configuration options.
struct ao2_container * apps
const ast_string_field uniqueid
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base
Structure to describe a channel "technology", ie a channel driver See for examples:
Main Channel structure associated with a channel.
supposed to be an opaque type
Abstract JSON element (object, array, string, int, ...).
A multi channel blob data structure for multi_channel_blob stasis messages.
Structure for mutex and tracking information.
Caller Party information.
struct ast_party_id id
Caller party ID.
struct ast_party_name name
Subscriber name.
char * str
Subscriber name (Malloced)
Support for dynamic strings.
Contains all the initialization information required to store a new test definition.
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define APPEND_EVENT(chan, ev_type, userevent, extra)
AST_TEST_DEFINE(test_cel_channel_creation)
#define CREATE_ALICE_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for Alice.
#define BRIDGE_EXIT_EVENT(channel, bridge)
static int append_expected_event_snapshot(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type type, const char *userdefevname, struct ast_json *extra, const char *peer)
ast_cond_t sync_out
Condition used for checking the end of test execution.
static int dump_event(struct ast_test *test, struct ast_event *event)
#define APPEND_EVENT_SNAPSHOT(snapshot, ev_type, userevent, extra, peer)
static struct ast_str * test_cel_generate_peer_str_snapshot(struct ast_channel_snapshot *chan, struct ast_bridge *bridge)
#define CREATE_BOB_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for Bob.
static struct ao2_container * cel_received_events
static struct ast_event * ao2_dup_event(const struct ast_event *event)
static int match_ie_val(const struct ast_event *event1, const struct ast_event *event2, enum ast_event_ie_type type)
Check an IE value from two events.
static int cel_verify_and_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
static void test_sub(struct ast_event *event)
static void safe_bridge_destroy(struct ast_bridge *bridge)
#define BOB_CALLERID
Bob's Caller ID.
int do_mid_test_sync
Flag used to trigger a mid-test synchronization, access controlled by mid_test_sync_lock.
static void do_sleep(void)
static int events_are_equal(struct ast_test *test, struct ast_event *received, struct ast_event *expected)
ast_mutex_t mid_test_sync_lock
Lock used for synchronizing test execution stages with received events.
#define BRIDGE_EXIT(channel, bridge)
#define CHANNEL_TECH_NAME
#define ALICE_CALLERID
Alice's Caller ID.
#define EMULATE_DIAL(channel, dialstring)
#define BRIDGE_ENTER(channel, bridge)
#define BRIDGE_EXIT_EVENT_PEER(channel, bridge, peer)
#define APPEND_DUMMY_EVENT()
static void safe_channel_release(struct ast_channel *chan)
#define CREATE_DAVID_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for David.
#define TEST_BACKEND_NAME
static struct ast_channel_tech test_cel_chan_tech
A channel technology used for the unit tests.
#define START_DIALED(caller, callee)
#define BRIDGE_ENTER_EVENT_PEER(channel, bridge, peer)
static int append_event(struct ast_event *ev)
#define ATTENDEDTRANSFER_BRIDGE(channel1, bridge1, channel2, bridge2, channel3, channel4)
#define START_DIALED_FULL(caller, callee, number, name)
#define BLINDTRANSFER_EVENT(channel, bridge, extension, context)
static int append_expected_event(struct ast_channel *chan, enum ast_cel_event_type type, const char *userdefevname, struct ast_json *extra, const char *peer)
#define CREATE_CHARLIE_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for Charlie.
static int check_events(struct ast_test *test, struct ao2_container *local_expected, struct ao2_container *local_received)
static int test_cel_peer_strings_match(const char *str1, const char *str2)
Check two peer strings for equality.
#define EMULATE_APP_DATA(channel, priority, application, data)
Emulate a channel entering into an application.
#define ANSWER_NO_APP(chan)
#define HANGUP_CHANNEL(channel, cause, dialstatus)
Hang up a test channel safely.
static int load_module(void)
ast_mutex_t sync_lock
Lock used with sync_out for checking the end of test execution.
static int unload_module(void)
static struct ast_cel_general_config * saved_config
A placeholder for Asterisk's 'real' CEL configuration.
static struct ast_str * __test_cel_generate_peer_str(struct ast_channel_snapshot *chan, struct ast_bridge_snapshot *bridge)
static struct ao2_container * cel_expected_events
static int test_cel_init_cb(struct ast_test_info *info, struct ast_test *test)
static void mid_test_sync(void)
#define ANSWER_CHANNEL(chan)
static struct ast_str * test_cel_generate_peer_str(struct ast_channel *chan, struct ast_bridge *bridge)
static struct ast_cel_general_config * cel_test_config
The CEL config used for CEL unit tests.
static struct timespec to_sleep
A 1 second sleep.
#define CHARLIE_CALLERID
Charlie's Caller ID.
Time-related functions and macros.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_clear_flag(p, flag)
#define ast_set_flag(p, flag)