[asterisk-commits] murf: branch murf/bug11210 r97535 - in /team/murf/bug11210: ./ apps/ channels...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 9 12:24:39 CST 2008


Author: murf
Date: Wed Jan  9 12:24:39 2008
New Revision: 97535

URL: http://svn.digium.com/view/asterisk?view=rev&rev=97535
Log:
Merged revisions 97125,97153-97154,97193,97196-97200,97203,97208,97248 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r97125 | tilghman | 2008-01-08 12:06:27 -0700 (Tue, 08 Jan 2008) | 11 lines

Merged revisions 97077 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r97077 | tilghman | 2008-01-08 12:02:13 -0600 (Tue, 08 Jan 2008) | 3 lines

Apply multiple crash fixes, found in issue #11386, but not completely
closing that issue.

........

................
r97153 | file | 2008-01-08 12:55:56 -0700 (Tue, 08 Jan 2008) | 12 lines

Merged revisions 97152 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r97152 | file | 2008-01-08 15:53:52 -0400 (Tue, 08 Jan 2008) | 4 lines

If no group has been provided to the GROUP_COUNT dialplan function then use the first one specific to the channel.
(closes issue #11077)
Reported by: m4him

........

................
r97154 | file | 2008-01-08 13:06:52 -0700 (Tue, 08 Jan 2008) | 6 lines

Move common code for setting T38 capabilities and fix a bug with fax detection in the SIP RTP read callback. It's still sort of silly... but more on that later.
(closes issue #11239)
Reported by: dimas
Patches:
      sipt38prop.patch uploaded by dimas (license 88)

................
r97193 | mmichelson | 2008-01-08 13:45:59 -0700 (Tue, 08 Jan 2008) | 17 lines

Merged revisions 97192 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r97192 | mmichelson | 2008-01-08 14:42:07 -0600 (Tue, 08 Jan 2008) | 9 lines

Making some changes designed to not allow for a corrupted mailstream for a vm_state.

1. Add locking to the vm_state retrieval functions so that no linked list corruption occurs.
2. Make sure to always grab the persistent vm_state when mailstream access is necessary.
3. Correct an incorrect return value in the init_mailstream function.

(closes issue #11304, reported by dwhite)


........

................
r97196 | file | 2008-01-08 13:50:57 -0700 (Tue, 08 Jan 2008) | 14 lines

Merged revisions 97195 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r97195 | file | 2008-01-08 16:48:20 -0400 (Tue, 08 Jan 2008) | 6 lines

Fix various DTMF issues in chan_mgcp.
(closes issue #11443)
Reported by: eferro
Patches:
      dtmf_control_hybrid-inband-mode.patch uploaded by eferro (license 337)

........

................
r97197 | file | 2008-01-08 13:52:07 -0700 (Tue, 08 Jan 2008) | 2 lines

One line documentation ftw!

................
r97198 | tilghman | 2008-01-08 13:56:38 -0700 (Tue, 08 Jan 2008) | 11 lines

Merged revisions 97194 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r97194 | tilghman | 2008-01-08 14:47:07 -0600 (Tue, 08 Jan 2008) | 3 lines

Increase constants to where we're less likely to hit them while debugging.
(Closes issue #11694)

........

................
r97199 | oej | 2008-01-08 13:58:56 -0700 (Tue, 08 Jan 2008) | 2 lines

Iksemel is alive in a new home. Release 1.3 is out with bug fixes.

................
r97200 | oej | 2008-01-08 14:01:46 -0700 (Tue, 08 Jan 2008) | 4 lines

Change reference to external library so it appears on the extref listing
http://www.asterisk.org/doxygen/trunk/extref.html


................
r97203 | mmichelson | 2008-01-08 14:18:32 -0700 (Tue, 08 Jan 2008) | 8 lines

Adding the option of specifying a second interface in a member definition for a queue. app_queue
will monitor this second device's state for the member, even though it actually calls the first
interface. This ability has been added for statically defined queue members, realtime queue members,
and dynamic queue members added through the CLI, dialplan, or manager.

(closes issue #11603, reported by acidv)


................
r97208 | mmichelson | 2008-01-08 14:28:04 -0700 (Tue, 08 Jan 2008) | 10 lines

Blocked revisions 97206 via svnmerge

........
r97206 | mmichelson | 2008-01-08 15:24:48 -0600 (Tue, 08 Jan 2008) | 3 lines

Some coding guidelines-related cleanup


........

................
r97248 | twilson | 2008-01-08 14:56:57 -0700 (Tue, 08 Jan 2008) | 2 lines

Initialize new variable to NULL

................

Modified:
    team/murf/bug11210/   (props changed)
    team/murf/bug11210/CHANGES
    team/murf/bug11210/apps/app_queue.c
    team/murf/bug11210/apps/app_voicemail.c
    team/murf/bug11210/channels/chan_console.c
    team/murf/bug11210/channels/chan_mgcp.c
    team/murf/bug11210/channels/chan_sip.c
    team/murf/bug11210/configs/queues.conf.sample
    team/murf/bug11210/funcs/func_groupcount.c
    team/murf/bug11210/main/asterisk.c
    team/murf/bug11210/main/autoservice.c
    team/murf/bug11210/main/utils.c
    team/murf/bug11210/res/res_jabber.c

Propchange: team/murf/bug11210/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/murf/bug11210/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/murf/bug11210/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Jan  9 12:24:39 2008
@@ -1,1 +1,1 @@
-/trunk:1-97108
+/trunk:1-97275

Modified: team/murf/bug11210/CHANGES
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/CHANGES?view=diff&rev=97535&r1=97534&r2=97535
==============================================================================
--- team/murf/bug11210/CHANGES (original)
+++ team/murf/bug11210/CHANGES Wed Jan  9 12:24:39 2008
@@ -265,6 +265,9 @@
   * Added new channel variable QUEUE_MIN_PENALTY
   * QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY may be adjusted in mid-call by defining
      rules in queuerules.conf. See configs/queuerules.conf.sample for details
+  * Added a new parameter for member definition, called state_interface. This may be
+    used so that a member may be called via one interface but have a different interface's
+	device state reported.
 
 MeetMe Changes
 --------------

Modified: team/murf/bug11210/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/apps/app_queue.c?view=diff&rev=97535&r1=97534&r2=97535
==============================================================================
--- team/murf/bug11210/apps/app_queue.c (original)
+++ team/murf/bug11210/apps/app_queue.c Wed Jan  9 12:24:39 2008
@@ -352,7 +352,8 @@
 };
 
 struct member {
-	char interface[80];                 /*!< Technology/Location */
+	char interface[80];                 /*!< Technology/Location to dial to reach this member*/
+	char state_interface[80];           /*!< Technology/Location from which to read devicestate changes */
 	char membername[80];                /*!< Member name to use in queue logs */
 	int penalty;                        /*!< Are we a last resort? */
 	int calls;                          /*!< Number of calls serviced by this member */
@@ -690,7 +691,7 @@
 		while ((cur = ao2_iterator_next(&mem_iter))) {
 			char *interface;
 			char *slash_pos;
-			interface = ast_strdupa(cur->interface);
+			interface = ast_strdupa(cur->state_interface);
 			if ((slash_pos = strchr(interface, '/')))
 				if ((slash_pos = strchr(slash_pos + 1, '/')))
 					*slash_pos = '\0';
@@ -815,7 +816,7 @@
 	statechange_queue(device, state);
 }
 
-static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused)
+static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
 {
 	struct member *cur;
 	
@@ -823,6 +824,10 @@
 		cur->penalty = penalty;
 		cur->paused = paused;
 		ast_copy_string(cur->interface, interface, sizeof(cur->interface));
+		if (!ast_strlen_zero(state_interface))
+			ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
+		else
+			ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
 		if (!ast_strlen_zero(membername))
 			ast_copy_string(cur->membername, membername, sizeof(cur->membername));
 		else
@@ -958,20 +963,20 @@
 {
 	struct call_queue *q;
 	struct member *mem, tmpmem;
-	struct ao2_iterator queue_iter;
+	struct ao2_iterator queue_iter, mem_iter;
 	int ret = 0;
 
 	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
 	queue_iter = ao2_iterator_init(queues, 0);
 	while ((q = ao2_iterator_next(&queue_iter))) {
-
 		ao2_lock(q);
-		if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
-			ao2_ref(mem, -1);
-			ao2_unlock(q);
-			queue_unref(q);
-			ret = 1;
-			break;
+		mem_iter = ao2_iterator_init(q->members, 0);
+		while ((mem = ao2_iterator_next(&mem_iter))) { 
+			if (!strcasecmp(mem->state_interface, interface)) {
+				ao2_ref(mem, -1);
+				ret = 1;
+				break;
+			}
 		}
 		ao2_unlock(q);
 		queue_unref(q);
@@ -991,7 +996,7 @@
 				ast_debug(1, "Removing %s from the list of interfaces that make up all of our queue members.\n", interface);
 				AST_LIST_REMOVE_CURRENT(list);
 				ast_free(curint);
-			}
+			} 
 			break;
 		}
 	}
@@ -1256,7 +1261,7 @@
 	}
 }
 
-static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str)
+static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface)
 {
 	struct member *m, tmpmem;
 	int penalty = 0;
@@ -1280,10 +1285,10 @@
 
 	/* Create a new one if not found, else update penalty */
 	if (!m) {
-		if ((m = create_queue_member(interface, membername, penalty, paused))) {
+		if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
 			m->dead = 0;
 			m->realtime = 1;
-			add_to_interfaces(interface);
+			add_to_interfaces(state_interface);
 			ao2_link(q->members, m);
 			ao2_ref(m, -1);
 			m = NULL;
@@ -1293,6 +1298,11 @@
 		m->dead = 0;	/* Do not delete this one. */
 		if (paused_str)
 			m->paused = paused;
+		if (strcasecmp(state_interface, m->state_interface)) {
+			remove_from_interfaces(m->state_interface);
+			ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
+			add_to_interfaces(m->state_interface);
+		}
 		m->penalty = penalty;
 		ao2_ref(m, -1);
 	}
@@ -1307,7 +1317,7 @@
 	while ((cur = ao2_iterator_next(&mem_iter))) {
 		if (all || !cur->dynamic) {
 			ao2_unlink(q->members, cur);
-			remove_from_interfaces(cur->interface);
+			remove_from_interfaces(cur->state_interface);
 			q->membercount--;
 		}
 		ao2_ref(cur, -1);
@@ -1436,7 +1446,8 @@
 		rt_handle_member_record(q, interface,
 			ast_variable_retrieve(member_config, interface, "membername"),
 			ast_variable_retrieve(member_config, interface, "penalty"),
-			ast_variable_retrieve(member_config, interface, "paused"));
+			ast_variable_retrieve(member_config, interface, "paused"),
+			ast_variable_retrieve(member_config, interface, "state_interface"));
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
@@ -1444,9 +1455,7 @@
 	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->dead) {
 			ao2_unlink(q->members, m);
-			ao2_unlock(q);
-			remove_from_interfaces(m->interface);
-			ao2_lock(q);
+			remove_from_interfaces(m->state_interface);
 			q->membercount--;
 		}
 		ao2_ref(m, -1);
@@ -1549,7 +1558,8 @@
 		rt_handle_member_record(q, interface,
 			S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
 			ast_variable_retrieve(member_config, interface, "penalty"),
-			ast_variable_retrieve(member_config, interface, "paused"));
+			ast_variable_retrieve(member_config, interface, "paused"),
+			ast_variable_retrieve(member_config, interface, "state_interface"));
 	}
 
 	/* Delete all realtime members that have been deleted in DB. */
@@ -1557,9 +1567,7 @@
 	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->dead) {
 			ao2_unlink(q->members, m);
-			ao2_unlock(q);
-			remove_from_interfaces(m->interface);
-			ao2_lock(q);
+			remove_from_interfaces(m->state_interface);
 			q->membercount--;
 		}
 		ao2_ref(m, -1);
@@ -3578,6 +3586,7 @@
 				"MemberName: %s\r\n",
 				q->name, mem->interface, mem->membername);
 			ao2_unlink(q->members, mem);
+			remove_from_interfaces(mem->state_interface);
 			ao2_ref(mem, -1);
 
 			if (queue_persistent_members)
@@ -3591,14 +3600,11 @@
 		queue_unref(q);
 	}
 
-	if (res == RES_OKAY)
-		remove_from_interfaces(interface);
-
 	return res;
 }
 
 
-static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump)
+static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
 {
 	struct call_queue *q;
 	struct member *new_member, *old_member;
@@ -3613,8 +3619,8 @@
 
 	ao2_lock(q);
 	if ((old_member = interface_exists(q, interface)) == NULL) {
-		add_to_interfaces(interface);
-		if ((new_member = create_queue_member(interface, membername, penalty, paused))) {
+		if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) {
+			add_to_interfaces(state_interface);
 			new_member->dynamic = 1;
 			ao2_link(q->members, new_member);
 			q->membercount++;
@@ -3797,6 +3803,7 @@
 	char *member;
 	char *interface;
 	char *membername = NULL;
+	char *state_interface;
 	char *penalty_tok;
 	int penalty = 0;
 	char *paused_tok;
@@ -3846,6 +3853,7 @@
 			penalty_tok = strsep(&member, ";");
 			paused_tok = strsep(&member, ";");
 			membername = strsep(&member, ";");
+			state_interface = strsep(&member, ";");
 
 			if (!penalty_tok) {
 				ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
@@ -3866,12 +3874,10 @@
 				ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
 				break;
 			}
-			if (ast_strlen_zero(membername))
-				membername = interface;
 
 			ast_debug(1, "Reload Members: Queue: %s  Member: %s  Name: %s  Penalty: %d  Paused: %d\n", queue_name, interface, membername, penalty, paused);
 			
-			if (add_to_queue(queue_name, interface, membername, penalty, paused, 0) == RES_OUTOFMEMORY) {
+			if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
 				ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
 				break;
 			}
@@ -4020,6 +4026,7 @@
 		AST_APP_ARG(penalty);
 		AST_APP_ARG(options);
 		AST_APP_ARG(membername);
+		AST_APP_ARG(state_interface);
 	);
 	int penalty = 0;
 
@@ -4046,7 +4053,7 @@
 		}
 	}
 
-	switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members)) {
+	switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
 	case RES_OKAY:
 		ast_queue_log(args.queuename, chan->uniqueid, args.interface, "ADDMEMBER", "%s", "");
 		ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
@@ -4803,7 +4810,7 @@
 	int new;
 	const char *general_val = NULL;
 	char parse[80];
-	char *interface;
+	char *interface, *state_interface;
 	char *membername = NULL;
 	int penalty;
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
@@ -4812,6 +4819,7 @@
 		AST_APP_ARG(interface);
 		AST_APP_ARG(penalty);
 		AST_APP_ARG(membername);
+		AST_APP_ARG(state_interface);
 	);
 
 	/*First things first. Let's load queuerules.conf*/
@@ -4880,8 +4888,10 @@
 				/* Check if a queue with this name already exists */
 				if (q->found) {
 					ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", cat);
-					if (!new)
+					if (!new) {
 						ao2_unlock(q);
+						queue_unref(q);
+					}
 					continue;
 				}
 				/* Due to the fact that the "linear" strategy will have a different allocation
@@ -4933,11 +4943,22 @@
 							while (*membername && *membername < 33) membername++;
 						}
 
+						if (!ast_strlen_zero(args.state_interface)) {
+							state_interface = args.state_interface;
+							while (*state_interface && *state_interface < 33) state_interface++;
+						} else
+							state_interface = interface;
+
 						/* Find the old position in the list */
 						ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
 						cur = ao2_find(q->members, &tmpmem, OBJ_POINTER | OBJ_UNLINK);
-
-						newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0);
+						/* Only attempt removing from interfaces list if the new state_interface is different than the old one */
+						if (cur && strcasecmp(cur->state_interface, state_interface)) {
+							remove_from_interfaces(cur->state_interface);
+						}
+						newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface);
+						if (!cur || (cur && strcasecmp(cur->state_interface, state_interface)))
+							add_to_interfaces(state_interface);
 						ao2_link(q->members, newm);
 						ao2_ref(newm, -1);
 						newm = NULL;
@@ -4945,8 +4966,6 @@
 						if (cur)
 							ao2_ref(cur, -1);
 						else {
-							/* Add them to the master int list if necessary */
-							add_to_interfaces(interface);
 							q->membercount++;
 						}
 					} else {
@@ -4961,16 +4980,16 @@
 						ao2_ref(cur, -1);
 						continue;
 					}
-
-					remove_from_interfaces(cur->interface);
+					ast_log(LOG_DEBUG, "%s in queue marked as delme, we should be deleting...\n", cur->interface);
 					q->membercount--;
 					ao2_unlink(q->members, cur);
+					remove_from_interfaces(cur->interface);
 					ao2_ref(cur, -1);
 				}
 
 				if (new) {
 					ao2_link(queues, q);
-				} else
+				} else 
 					ao2_unlock(q);
 				queue_unref(q);
 			}
@@ -5352,7 +5371,7 @@
 
 static int manager_add_queue_member(struct mansession *s, const struct message *m)
 {
-	const char *queuename, *interface, *penalty_s, *paused_s, *membername;
+	const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
 	int paused, penalty = 0;
 
 	queuename = astman_get_header(m, "Queue");
@@ -5360,6 +5379,7 @@
 	penalty_s = astman_get_header(m, "Penalty");
 	paused_s = astman_get_header(m, "Paused");
 	membername = astman_get_header(m, "MemberName");
+	state_interface = astman_get_header(m, "StateInterface");
 
 	if (ast_strlen_zero(queuename)) {
 		astman_send_error(s, m, "'Queue' not specified.");
@@ -5381,7 +5401,7 @@
 	else
 		paused = abs(ast_true(paused_s));
 
-	switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members)) {
+	switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
 	case RES_OKAY:
 		ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
 		astman_send_ack(s, m, "Added interface to queue");
@@ -5537,26 +5557,28 @@
 
 static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	char *queuename, *interface, *membername = NULL;
+	char *queuename, *interface, *membername = NULL, *state_interface = NULL;
 	int penalty;
 
 	switch ( cmd ) {
 	case CLI_INIT:
 		e->command = "queue add member";
 		e->usage =
-			"Usage: queue add member <channel> to <queue> [penalty <penalty>]\n"; 
+			"Usage: queue add member <channel> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]\n"; 
 		return NULL;
 	case CLI_GENERATE:
 		return complete_queue_add_member(a->line, a->word, a->pos, a->n);
 	}
 
-	if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10)) {
+	if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
 		return CLI_SHOWUSAGE;
 	} else if (strcmp(a->argv[4], "to")) {
 		return CLI_SHOWUSAGE;
-	} else if ((a->argc == 8) && strcmp(a->argv[6], "penalty")) {
+	} else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
 		return CLI_SHOWUSAGE;
-	} else if ((a->argc == 10) && strcmp(a->argv[8], "as")) {
+	} else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
+		return CLI_SHOWUSAGE;
+	} else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
 		return CLI_SHOWUSAGE;
 	}
 
@@ -5580,7 +5602,11 @@
 		membername = a->argv[9];
 	}
 
-	switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members)) {
+	if (a->argc >= 12) {
+		state_interface = a->argv[11];
+	}
+
+	switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
 	case RES_OKAY:
 		ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
 		ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);

Modified: team/murf/bug11210/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/apps/app_voicemail.c?view=diff&rev=97535&r1=97534&r2=97535
==============================================================================
--- team/murf/bug11210/apps/app_voicemail.c (original)
+++ team/murf/bug11210/apps/app_voicemail.c Wed Jan  9 12:24:39 2008
@@ -2743,11 +2743,11 @@
 {
 	struct vm_state *sendvms = NULL, *destvms = NULL;
 	char messagestring[10]; /*I guess this could be a problem if someone has more than 999999999 messages...*/
-	if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 2))) {
+	if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
 		ast_log(LOG_ERROR, "Couldn't get vm_state for originator's mailbox!!\n");
 		return -1;
 	}
-	if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 2))) {
+	if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 0))) {
 		ast_log(LOG_ERROR, "Couldn't get vm_state for destination mailbox!\n");
 		return -1;
 	}
@@ -4936,7 +4936,7 @@
 		stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
 		if (stream == NIL) {
 			ast_log (LOG_ERROR, "Can't connect to imap server %s\n", tmp);
-			return NIL;
+			return -1;
 		}
 		get_mailbox_delimiter(stream);
 		/* update delimiter in imapfolder */

Modified: team/murf/bug11210/channels/chan_console.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_console.c?view=diff&rev=97535&r1=97534&r2=97535
==============================================================================
--- team/murf/bug11210/channels/chan_console.c (original)
+++ team/murf/bug11210/channels/chan_console.c Wed Jan  9 12:24:39 2008
@@ -29,7 +29,7 @@
  * 
  * \ingroup channel_drivers
  *
- * \arg http://www.portaudio.com/
+ * \extref Portaudio http://www.portaudio.com/
  *
  * To install portaudio v19 from svn, check it out using the following command:
  *  - svn co https://www.portaudio.com/repos/portaudio/branches/v19-devel

Modified: team/murf/bug11210/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_mgcp.c?view=diff&rev=97535&r1=97534&r2=97535
==============================================================================
--- team/murf/bug11210/channels/chan_mgcp.c (original)
+++ team/murf/bug11210/channels/chan_mgcp.c Wed Jan  9 12:24:39 2008
@@ -428,6 +428,7 @@
 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
 static int mgcp_devicestate(void *data);
+static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
 
 static const struct ast_channel_tech mgcp_tech = {
 	.type = "MGCP",
@@ -1300,23 +1301,50 @@
 
 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
 {
-	/* Let asterisk play inband indications */
-	return -1;
+	struct mgcp_subchannel *sub = ast->tech_pvt;
+	struct mgcp_endpoint *p = sub->parent;
+	int res = 0;
+
+	ast_mutex_lock(&sub->lock);
+	if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
+		ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
+		res = -1; /* Let asterisk play inband indications */
+	} else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+		ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
+		ast_rtp_senddigit_begin(sub->rtp, digit);
+	} else {
+		ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+	}
+	ast_mutex_unlock(&sub->lock);
+
+	return res;
 }
 
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
 	struct mgcp_subchannel *sub = ast->tech_pvt;
+	struct mgcp_endpoint *p = sub->parent;
+	int res = 0;
 	char tmp[4];
 
-	tmp[0] = 'D';
-	tmp[1] = '/';
-	tmp[2] = digit;
-	tmp[3] = '\0';
 	ast_mutex_lock(&sub->lock);
-	transmit_notify_request(sub, tmp);
+	if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
+		ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
+		res = -1; /* Tell Asterisk to stop inband indications */
+	} else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+		ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
+		tmp[0] = 'D';
+		tmp[1] = '/';
+		tmp[2] = digit;
+		tmp[3] = '\0';
+		transmit_notify_request(sub, tmp);
+                ast_rtp_senddigit_end(sub->rtp, digit);
+	} else {
+		ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+	}
 	ast_mutex_unlock(&sub->lock);
-	return -1; /* Return non-zero so that Asterisk will stop the inband indications */
+
+	return res;
 }
 
 /*!
@@ -2209,7 +2237,7 @@
 		add_header(&resp, "R", "L/hd(N)");
 		break;
 	case MGCP_OFFHOOK:
-		add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+		add_header_offhook(sub, &resp);
 		break;
 	}
 	if (!ast_strlen_zero(tone)) {
@@ -2251,7 +2279,7 @@
 		add_header(&resp, "R", "L/hd(N)");
 		break;
 	case MGCP_OFFHOOK:
-		add_header(&resp, "R",  (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+		add_header_offhook(sub, &resp);
 		break;
 	}
 	if (!ast_strlen_zero(tone2)) {
@@ -2292,7 +2320,7 @@
 		add_header(&resp, "R", "L/hd(N)");
 		break;
 	case MGCP_OFFHOOK:
-		add_header(&resp, "R",  (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+		add_header_offhook(sub, &resp);
 		break;
 	}
 	/* fill in new fields */
@@ -2301,6 +2329,16 @@
 	return send_request(p, sub, &resp, oseq); /* SC */
 }
 
+
+static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp)
+{
+	struct mgcp_endpoint *p = sub->parent;
+
+	if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
+		add_header(resp, "R", "L/hu(N),L/hf(N)");
+	else
+		add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
+}
 
 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
 {

Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=97535&r1=97534&r2=97535
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Wed Jan  9 12:24:39 2008
@@ -139,6 +139,7 @@
 #include "asterisk/translate.h"
 #include "asterisk/version.h"
 #include "asterisk/event.h"
+#include "asterisk/astobj2.h"
 
 /* remove when someone fixes this */
 const char *ast_get_version(void);
@@ -1163,7 +1164,7 @@
 	struct ast_rtp *rtp;			/*!< RTP Session */
 	struct ast_rtp *vrtp;			/*!< Video RTP session */
 	struct ast_rtp *trtp;			/*!< Text RTP session */
-	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
+	struct ao2_container *packets;		/*!< Packets scheduled for re-transmission */
 	struct sip_history_head *history;	/*!< History of this SIP dialog */
 	size_t history_entries;			/*!< Number of entires in the history */
 	struct ast_variable *chanvars;		/*!< Channel variables to set for inbound call */
@@ -1259,7 +1260,6 @@
  * require retransmissions.
  */
 struct sip_pkt {
-	struct sip_pkt *next;			/*!< Next packet in linked list */
 	int retrans;				/*!< Retransmission number */
 	int method;				/*!< SIP method for this packet */
 	int seqno;				/*!< Sequence number */
@@ -1368,7 +1368,7 @@
 	char rt_fromcontact;		/*!< P: copy fromcontact from realtime */
 	char host_dynamic;		/*!< P: Dynamic Peers register with Asterisk */
 	char selfdestruct;		/*!< P: Automatic peers need to destruct themselves */
-	char theMark;           /*!< moved out of ASTOBJ into struct proper; That with bears theMark should be deleted! */
+	char theMark;           /*!< moved out of ASTOBJ into struct proper; That which bears theMark should be deleted! */
 
 	int expire;			/*!<  When to expire this peer registration */
 	int capability;			/*!<  Codec capability */
@@ -1717,7 +1717,7 @@
 static struct sip_pvt *sip_destroy(struct sip_pvt *p);
 static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist);
 static void *registry_unref(struct sip_registry *reg, char *tag);
-static void __sip_destroy(struct sip_pvt *p);
+static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist);
 static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);
 static void __sip_pretend_ack(struct sip_pvt *p);
 static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);
@@ -2482,12 +2482,15 @@
 /*! \brief Retransmit SIP message if no answer (Called from scheduler) */
 static int retrans_pkt(const void *data)
 {
-	struct sip_pkt *pkt = (struct sip_pkt *)data, *prev, *cur = NULL;
+	struct sip_pkt *pkt = (struct sip_pkt *)data, *prev;
 	int reschedule = DEFAULT_RETRANS;
 	int xmitres = 0;
 	
+	ao2_ref(pkt, 1); /* Make sure this cannot go away while we're using it */
+
 	/* Lock channel PVT */
-	sip_pvt_lock(pkt->owner);
+	if (pkt->owner)
+		sip_pvt_lock(pkt->owner);
 
 	if (pkt->retrans < MAX_RETRANS) {
 		pkt->retrans++;
@@ -2514,7 +2517,7 @@
  			ast_debug(4, "** SIP timers: Rescheduling retransmission %d to %d ms (t1 %d ms (Retrans id #%d)) \n", pkt->retrans +1, siptimer_a, pkt->timer_t1, pkt->retransid);
  		} 
 
-		if (sip_debug_test_pvt(pkt->owner)) {
+		if (pkt->owner && sip_debug_test_pvt(pkt->owner)) {
 			const struct sockaddr_in *dst = sip_real_dst(pkt->owner);
 			ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n",
 				pkt->retrans, sip_nat_mode(pkt->owner),
@@ -2524,11 +2527,14 @@
 
 		append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
 		xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
-		sip_pvt_unlock(pkt->owner);
+		if (pkt->owner)
+			sip_pvt_unlock(pkt->owner);
 		if (xmitres == XMIT_ERROR)
-			ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner->callid);
-		else 
+			ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner ? pkt->owner->callid : "<unknown>");
+		else {
+			ao2_ref(pkt, -1);
 			return  reschedule;
+		}
 	} 
 	/* Too many retries */
 	if (pkt->owner && pkt->method != SIP_OPTIONS && xmitres == 0) {
@@ -2536,29 +2542,31 @@
 			ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s)\n",
 				pkt->owner->callid, pkt->seqno,
 				pkt->is_fatal ? "Critical" : "Non-critical", pkt->is_resp ? "Response" : "Request");
-	} else if (pkt->method == SIP_OPTIONS && sipdebug) {
-			ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) \n", pkt->owner->callid);
+	} else if (pkt->owner && (pkt->method == SIP_OPTIONS) && sipdebug) {
+		ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) \n", pkt->owner->callid);
 
 	} 
-	if (xmitres == XMIT_ERROR) {
-		ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission on Call ID %s\n", pkt->owner->callid);
-		append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
-	} else 
-		append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
- 		
+	if (pkt->owner) {
+		if (xmitres == XMIT_ERROR) {
+			ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission of transaction in call id %s \n", pkt->owner->callid);
+			append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
+		} else
+			append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
+ 	}
 	pkt->retransid = -1;
 
 	if (pkt->is_fatal) {
-		while(pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) {
+		while (pkt->owner && pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) {
 			sip_pvt_unlock(pkt->owner);	/* SIP_PVT, not channel */
 			usleep(1);
-			sip_pvt_lock(pkt->owner);
-		}
-
-		if (pkt->owner->owner && !pkt->owner->owner->hangupcause) 
+			if (pkt->owner)
+				sip_pvt_lock(pkt->owner);
+		}
+
+		if (pkt->owner && pkt->owner->owner && !pkt->owner->owner->hangupcause) 
 			pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE;
 		
-		if (pkt->owner->owner) {
+		if (pkt->owner && pkt->owner->owner) {
 			sip_alreadygone(pkt->owner);
 			ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet.\n", pkt->owner->callid);
 			ast_queue_hangup(pkt->owner->owner);
@@ -2567,7 +2575,7 @@
 			/* If no channel owner, destroy now */
 
 			/* Let the peerpoke system expire packets when the timer expires for poke_noanswer */
-			if (pkt->method != SIP_OPTIONS && pkt->method != SIP_REGISTER) {
+			if (pkt->owner && pkt->method != SIP_OPTIONS && pkt->method != SIP_REGISTER) {
 				pkt->owner->needdestroy = 1;
 				sip_alreadygone(pkt->owner);
 				append_history(pkt->owner, "DialogKill", "Killing this failed dialog immediately");
@@ -2575,7 +2583,7 @@
 		}
 	}
 
-	if (pkt->method == SIP_BYE) {
+	if (pkt->owner && pkt->method == SIP_BYE) {
 		/* We're not getting answers on SIP BYE's.  Tear down the call anyway. */
 		if (pkt->owner->owner) 
 			ast_channel_unlock(pkt->owner->owner);
@@ -2584,18 +2592,23 @@
 	}
 
 	/* Remove the packet */
-	for (prev = NULL, cur = pkt->owner->packets; cur; prev = cur, cur = cur->next) {
-		if (cur == pkt) {
-			UNLINK(cur, pkt->owner->packets, prev);
+	if (pkt->owner && (prev = ao2_t_find(pkt->owner->packets, pkt, OBJ_UNLINK | OBJ_POINTER,"find packet in table"))) {
+		/* Destroy the container's reference (inherited) */
+		ao2_ref(prev, -1);
+		sip_pvt_unlock(pkt->owner);
+		/* Now destroy our initial reference */
+		ao2_ref(pkt, -1);
+		/* And destroy the sched ref */
+		ao2_ref(pkt, -1);
+		return 0;
+	} else {
+		ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
+		if (pkt->owner)
 			sip_pvt_unlock(pkt->owner);
-			ast_free(pkt);
-			return 0;
-		}
-	}
-	/* error case */
-	ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
-	sip_pvt_unlock(pkt->owner);
-	return 0;
+		ao2_ref(pkt, -1); /* Initial ref */
+		ao2_ref(pkt, -1); /* Sched ref */
+		return 0;
+	}
 }
 
 /*! \brief Transmit packet with retransmits 
@@ -2607,7 +2620,7 @@
 	int siptimer_a = DEFAULT_RETRANS;
 	int xmitres = 0;
 
-	if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1)))
+	if (!(pkt = ao2_alloc(sizeof(*pkt) + len + 1, ast_free)))
 		return AST_FAILURE;
 	/* copy data, add a terminator and save length */
 	memcpy(pkt->data, data, len);
@@ -2619,17 +2632,13 @@
 	pkt->is_resp = resp;
 	pkt->is_fatal = fatal;
 	pkt->owner = dialog_ref(p,"__sip_reliable_xmit: setting pkt->owner");
-	pkt->next = p->packets;
-	p->packets = pkt;
 	pkt->timer_t1 = p->timer_t1;	/* Set SIP timer T1 */
 	if (pkt->timer_t1)
 		siptimer_a = pkt->timer_t1 * 2;
 
-	/* Schedule retransmission */
-	pkt->retransid = ast_sched_replace_variable(pkt->retransid, sched, 
-		siptimer_a, retrans_pkt, pkt, 1);
-	if (sipdebug)
-		ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id  #%d\n", pkt->retransid);
+	if (option_debug > 3 && sipdebug)
+		ast_log(LOG_DEBUG, "*** SIP TIMER: Initializing retransmit timer on packet: Id  #%d\n", pkt->retransid);
+
 	if (sipmethod == SIP_INVITE) {
 		/* Note this is a pending invite */
 		p->pendinginvite = seqno;
@@ -2639,11 +2648,25 @@
 
 	if (xmitres == XMIT_ERROR) {	/* Serious network trouble, no need to try again */
 		append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
-		ast_sched_del(sched, pkt->retransid);	/* No more retransmission */
 		pkt->retransid = -1;
+		ao2_ref(pkt, -1);	/* and deallocate */
 		return AST_FAILURE;
-	} else
+	} else {
+		/* Add refcount for scheduler pointer */
+		ao2_ref(pkt, 1);
+		/* Schedule retransmission */
+		pkt->retransid = ast_sched_add_variable(sched, siptimer_a, retrans_pkt, pkt, 1);
+		/* Link into the list of packets */
+		ao2_link(p->packets, pkt);
 		return AST_SUCCESS;
+	}
+}
+
+static int __deref_ao2_owner_cb(void *obj, void *unused, int flags)
+{
+	struct sip_pkt *pkt = obj;
+	pkt->owner = NULL;
+	return 0;
 }
 
 /*! \brief Kill a SIP dialog (called only by the scheduler)
@@ -2664,11 +2687,11 @@
 		return 10000;	/* Reschedule this destruction so that we know that it's gone */
 	}
 
-	/* If there are packets still waiting for delivery, delay the destruction */
-	if (p->packets) {
-		ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
-		append_history(p, "ReliableXmit", "timeout");
-		return 10000;
+	/* If there are packets still waiting for delivery, make sure they can't callback to us anymore. */
+	if (ao2_container_count(p->packets)) {
+		sip_pvt_lock(p);
+		ao2_callback(p->packets, 0, __deref_ao2_owner_cb, NULL);
+		sip_pvt_unlock(p);
 	}
 
 	if (p->subscribed == MWI_NOTIFICATION)
@@ -2744,7 +2767,8 @@
 /*! \brief Acknowledges receipt of a packet and stops retransmission */
 static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod)
 {
-	struct sip_pkt *cur, *prev = NULL;
+	struct sip_pkt *cur;
+	struct ao2_iterator ao2i;
 	const char *msg = "Not Found";	/* used only for debugging */
 
 	sip_pvt_lock(p);
@@ -2757,7 +2781,8 @@
 	if (p->outboundproxy && !p->outboundproxy->force)
 		p->outboundproxy = NULL;
 
-	for (cur = p->packets; cur; prev = cur, cur = cur->next) {
+	ao2i = ao2_iterator_init(p->packets, 0);
+	while ((cur = ao2_iterator_next(&ao2i))) {
 		if (cur->seqno != seqno || cur->is_resp != resp)
 			continue;
 		if (cur->is_resp || cur->method == sipmethod) {
@@ -2769,57 +2794,65 @@
 			if (cur->retransid > -1) {
 				if (sipdebug)
 					ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
-				ast_sched_del(sched, cur->retransid);
+				if (!ast_sched_del(sched, cur->retransid))
+					ao2_ref(cur, -1); /* scheduler deref */
 				cur->retransid = -1;
 			}
-			UNLINK(cur, p->packets, prev);
-			cur->owner = dialog_unref(cur->owner,"dialog ptd to by sip_pkt->owner is to be freed");
-			ast_free(cur);
+
+			/* Remove it from the list */
+			ao2_t_unlink(p->packets, cur,"remove pkt from packets list");
+			ao2_t_ref(cur, -1, "drop ref to iterator"); /* iterator deref */
 			break;
 		}
+
+		ao2_ref(cur, -1); /* iterator deref */
 	}
 	sip_pvt_unlock(p);
 	ast_debug(1, "Stopping retransmission on '%s' of %s %d: Match %s\n",
 		p->callid, resp ? "Response" : "Request", seqno, msg);
 }
 
-/*! \brief Pretend to ack all packets
- * maybe the lock on p is not strictly necessary but there might be a race */
+static int __sip_pretend_ack_cb(void *obj, void *vp, int flags)
+{
+	struct sip_pvt *p = vp;
+	struct sip_pkt *pkt = obj;
+	__sip_ack(p, pkt->seqno, pkt->is_resp, pkt->method ? pkt->method : find_sip_method(pkt->data));
+	return 0;
+}
+
+/*! \brief Pretend to ack all packets */
 static void __sip_pretend_ack(struct sip_pvt *p)
 {
-	struct sip_pkt *cur = NULL;
-
-	while (p->packets) {
-		int method;
-		if (cur == p->packets) {
-			ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text);
-			return;
-		}

[... 558 lines stripped ...]



More information about the asterisk-commits mailing list