[asterisk-commits] mjordan: trunk r393164 - in /trunk: main/cdr.c tests/test_cdr.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jun 28 12:31:53 CDT 2013


Author: mjordan
Date: Fri Jun 28 12:31:33 2013
New Revision: 393164

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393164
Log:
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.


Modified:
    trunk/main/cdr.c
    trunk/tests/test_cdr.c

Modified: trunk/main/cdr.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/cdr.c?view=diff&rev=393164&r1=393163&r2=393164
==============================================================================
--- trunk/main/cdr.c (original)
+++ trunk/main/cdr.c Fri Jun 28 12:31:33 2013
@@ -1601,6 +1601,11 @@
 				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;

Modified: trunk/tests/test_cdr.c
URL: http://svnview.digium.com/svn/asterisk/trunk/tests/test_cdr.c?view=diff&rev=393164&r1=393163&r2=393164
==============================================================================
--- trunk/tests/test_cdr.c (original)
+++ trunk/tests/test_cdr.c Fri Jun 28 12:31:33 2013
@@ -494,6 +494,102 @@
 	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 @@
 		.lastapp = "VoiceMailMain",
 		.lastdata = "1",
 		.billsec = 1,
-		.amaflags = AST_AMA_DOCUMENTATION,
+	.amaflags = AST_AMA_DOCUMENTATION,
 		.disposition = AST_CDR_ANSWERED,
 		.accountcode = "100",
 	};
@@ -2338,12 +2434,15 @@
 	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);
 	AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_a);
 	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);
@@ -2384,6 +2483,8 @@
 	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);




More information about the asterisk-commits mailing list