summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-06-28 17:31:33 +0000
committerMatthew Jordan <mjordan@digium.com>2013-06-28 17:31:33 +0000
commitca61a05506c778e155f557c2ffefbf5707874473 (patch)
tree742a804fe4a25e30258d21f544fac4ea3b1fd256
parenteba573947059f42f8778f09e2e8640050fb8b444 (diff)
Handle an originated channel being sent into a non-empty bridge
Originated channels are a bit odd - they are technically a dialed channel (thus the party B or peer) but, since there is no caller, they are treated as the party A. When entering into a bridge that already contains participants, the CDR engine - if the CDR record is in the Dial state - attempts to match the person entering the bridge with an existing participant. The idea is that if you dialed someone and the person you dialed is already in the bridge, you don't need a new CDR record, the existing CDR record describes the relationship. Unfortunately, for an originated channel, there is no Party B. If no one was in the bridge this didn't cause any issues; however, if participants were in the bridge the CDR engine would attempt to match a non-existant Party B on the channel's CDR record and explode. This patch fixes that, and a unit test has been added to cover this case. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393164 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--main/cdr.c5
-rw-r--r--tests/test_cdr.c103
2 files changed, 107 insertions, 1 deletions
diff --git a/main/cdr.c b/main/cdr.c
index dbce8e5c4..d2e033839 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -1601,6 +1601,11 @@ static int dial_state_process_bridge_enter(struct cdr_object *cdr, struct ast_br
continue;
}
+ /* If we don't have a Party B (originated channel), skip it */
+ if (!cdr->party_b.snapshot) {
+ continue;
+ }
+
/* Skip any records that aren't our Party B */
if (strcmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {
continue;
diff --git a/tests/test_cdr.c b/tests/test_cdr.c
index c9621a450..a60f78e2c 100644
--- a/tests/test_cdr.c
+++ b/tests/test_cdr.c
@@ -494,6 +494,102 @@ AST_TEST_DEFINE(test_cdr_unanswered_outbound_call)
return result;
}
+AST_TEST_DEFINE(test_cdr_outbound_bridged_call)
+{
+ RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
+ RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
+ RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
+ ao2_cleanup);
+ struct timespec to_sleep = {1, 0};
+ enum ast_test_result_state result = AST_TEST_NOT_RUN;
+
+ struct ast_party_caller caller = ALICE_CALLERID;
+ struct ast_cdr alice_expected = {
+ .clid = "\"Alice\" <100>",
+ .src = "100",
+ .dst = "100",
+ .dcontext = "default",
+ .channel = CHANNEL_TECH_NAME "/Alice",
+ .dstchannel = CHANNEL_TECH_NAME "/Bob",
+ .lastapp = "",
+ .lastdata = "",
+ .amaflags = AST_AMA_DOCUMENTATION,
+ .billsec = 1,
+ .disposition = AST_CDR_ANSWERED,
+ .accountcode = "100",
+ .peeraccount = "200",
+ };
+ struct ast_cdr bob_expected = {
+ .clid = "\"\" <>",
+ .src = "",
+ .dst = "s",
+ .dcontext = "default",
+ .channel = CHANNEL_TECH_NAME "/Bob",
+ .dstchannel = "",
+ .lastapp = "AppDial",
+ .lastdata = "(Outgoing Line)",
+ .amaflags = AST_AMA_DOCUMENTATION,
+ .billsec = 1,
+ .disposition = AST_CDR_ANSWERED,
+ .accountcode = "200",
+ .peeraccount = "",
+ .next = &alice_expected,
+ };
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = __func__;
+ info->category = TEST_CATEGORY;
+ info->summary = "Test dialing, answering, and going into a 2-party bridge";
+ info->description =
+ "The most 'basic' of scenarios\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ SWAP_CONFIG(config, debug_cdr_config);
+
+ CREATE_ALICE_CHANNEL(chan_alice, &caller, &alice_expected);
+ ast_channel_state_set(chan_alice, AST_STATE_UP);
+
+ bridge = ast_bridge_basic_new();
+ ast_test_validate(test, bridge != NULL);
+ while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
+
+ ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
+
+ chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_alice), 0, CHANNEL_TECH_NAME "/Bob");
+ ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid));
+ ast_copy_string(bob_expected.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected.uniqueid));
+ ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
+ ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_ORIGINATED);
+ EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
+
+ ast_channel_publish_dial(NULL, chan_bob, "Bob", NULL);
+ ast_channel_state_set(chan_bob, AST_STATE_RINGING);
+ ast_channel_publish_dial(NULL, chan_bob, NULL, "ANSWER");
+
+ ast_channel_state_set(chan_bob, AST_STATE_UP);
+
+ while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
+
+ ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
+
+ while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
+
+ ast_bridge_depart(chan_bob);
+ ast_bridge_depart(chan_alice);
+
+ HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
+ HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
+
+ result = verify_mock_cdr_record(test, &bob_expected, 2);
+ return result;
+}
+
+
AST_TEST_DEFINE(test_cdr_single_party)
{
RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
@@ -511,7 +607,7 @@ AST_TEST_DEFINE(test_cdr_single_party)
.lastapp = "VoiceMailMain",
.lastdata = "1",
.billsec = 1,
- .amaflags = AST_AMA_DOCUMENTATION,
+ .amaflags = AST_AMA_DOCUMENTATION,
.disposition = AST_CDR_ANSWERED,
.accountcode = "100",
};
@@ -2338,6 +2434,7 @@ static int unload_module(void)
AST_TEST_UNREGISTER(test_cdr_channel_creation);
AST_TEST_UNREGISTER(test_cdr_unanswered_inbound_call);
AST_TEST_UNREGISTER(test_cdr_unanswered_outbound_call);
+
AST_TEST_UNREGISTER(test_cdr_single_party);
AST_TEST_UNREGISTER(test_cdr_single_bridge);
AST_TEST_UNREGISTER(test_cdr_single_bridge_continue);
@@ -2345,6 +2442,8 @@ static int unload_module(void)
AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_b);
AST_TEST_UNREGISTER(test_cdr_single_multiparty_bridge);
+ AST_TEST_UNREGISTER(test_cdr_outbound_bridged_call);
+
AST_TEST_UNREGISTER(test_cdr_dial_unanswered);
AST_TEST_UNREGISTER(test_cdr_dial_congestion);
AST_TEST_UNREGISTER(test_cdr_dial_busy);
@@ -2384,6 +2483,8 @@ static int load_module(void)
AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_b);
AST_TEST_REGISTER(test_cdr_single_multiparty_bridge);
+ AST_TEST_REGISTER(test_cdr_outbound_bridged_call);
+
AST_TEST_REGISTER(test_cdr_dial_unanswered);
AST_TEST_REGISTER(test_cdr_dial_congestion);
AST_TEST_REGISTER(test_cdr_dial_busy);