[asterisk-commits] kmoore: branch 1.8 r324305 - /branches/1.8/apps/app_confbridge.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jun 21 11:09:18 CDT 2011


Author: kmoore
Date: Tue Jun 21 11:09:14 2011
New Revision: 324305

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=324305
Log:
ConfBridge does not handle hangup properly

When playing back a prompt to a channel, confbridge neglects to check for
hangup events causing lockup condititions for hangups that occur before
actually joining the conference.  This change ensures that the user is removed 
from the conference in the event of a premature hangup.

Review: https://reviewboard.asterisk.org/r/1277/

Modified:
    branches/1.8/apps/app_confbridge.c

Modified: branches/1.8/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/apps/app_confbridge.c?view=diff&rev=324305&r1=324304&r2=324305
==============================================================================
--- branches/1.8/apps/app_confbridge.c (original)
+++ branches/1.8/apps/app_confbridge.c Tue Jun 21 11:09:14 2011
@@ -198,30 +198,31 @@
  * \param conference_bridge Conference bridge to peek at
  * \param conference_bridge_user Caller
  *
- * \return Returns nothing
- */
-static void announce_user_count(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+ * \return Returns 0 on success, -1 if the user hung up
+ */
+static int announce_user_count(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
 {
 	if (conference_bridge->users == 1) {
 		/* Awww we are the only person in the conference bridge */
-		return;
+		return 0;
 	} else if (conference_bridge->users == 2) {
 		/* Eep, there is one other person */
 		if (ast_stream_and_wait(conference_bridge_user->chan, "conf-onlyone", "")) {
-			return;
+			return -1;
 		}
 	} else {
 		/* Alas multiple others in here */
 		if (ast_stream_and_wait(conference_bridge_user->chan, "conf-thereare", "")) {
-			return;
+			return -1;
 		}
 		if (ast_say_number(conference_bridge_user->chan, conference_bridge->users - 1, "", conference_bridge_user->chan->language, NULL)) {
-			return;
+			return -1;
 		}
 		if (ast_stream_and_wait(conference_bridge_user->chan, "conf-otherinparty", "")) {
-			return;
-		}
-	}
+			return -1;
+		}
+	}
+	return 0;
 }
 
 /*!
@@ -231,15 +232,17 @@
  * \param chan Channel to play audio prompt to
  * \param file Prompt to play
  *
- * \return Returns nothing
+ * \return Returns 0 on success, -1 if the user hung up
  *
  * \note This function assumes that conference_bridge is locked
  */
-static void play_prompt_to_channel(struct conference_bridge *conference_bridge, struct ast_channel *chan, const char *file)
-{
+static int play_prompt_to_channel(struct conference_bridge *conference_bridge, struct ast_channel *chan, const char *file)
+{
+	int res;
 	ao2_unlock(conference_bridge);
-	ast_stream_and_wait(chan, file, "");
+	res = ast_stream_and_wait(chan, file, "");
 	ao2_lock(conference_bridge);
+	return res;
 }
 
 /*!
@@ -248,16 +251,16 @@
  * \param conference_bridge Conference bridge being joined
  * \param conference_bridge_user Conference bridge user joining
  *
- * \return Returns nothing
- */
-static void post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+ * \return Returns 0 on success, -1 if the user hung up
+ */
+static int post_join_marked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
 {
 	if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER)) {
 		struct conference_bridge_user *other_conference_bridge_user = NULL;
 
 		/* If we are not the first marked user to join just bail out now */
 		if (conference_bridge->markedusers >= 2) {
-			return;
+			return 0;
 		}
 
 		/* Iterate through every participant stopping MOH on them if need be */
@@ -291,13 +294,16 @@
 	} else {
 		/* If a marked user already exists in the conference bridge we can just bail out now */
 		if (conference_bridge->markedusers) {
-			return;
+			return 0;
 		}
 		/* Be sure we are muted so we can't talk to anybody else waiting */
 		conference_bridge_user->features.mute = 1;
 		/* If we have not been quieted play back that they are waiting for the leader */
 		if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET)) {
-			play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-waitforleader");
+			if (play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-waitforleader")) {
+				/* user hung up while the sound was playing */
+				return -1;
+			}
 		}
 		/* Start music on hold if needed */
 		/* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially
@@ -307,6 +313,7 @@
 			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
 		}
 	}
+	return 0;
 }
 
 /*!
@@ -315,15 +322,18 @@
  * \param conference_bridge Conference bridge being joined
  * \param conference_bridge_user Conference bridge user joining
  *
- * \return Returns nothing
- */
-static void post_join_unmarked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+ * \return Returns 0 on success, -1 if the user hung up
+ */
+static int post_join_unmarked(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
 {
 	/* Play back audio prompt and start MOH if need be if we are the first participant */
 	if (conference_bridge->users == 1) {
 		/* If audio prompts have not been quieted or this prompt quieted play it on out */
 		if (!ast_test_flag(&conference_bridge_user->flags, OPTION_QUIET | OPTION_NOONLYPERSON)) {
-			play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-onlyperson");
+			if (play_prompt_to_channel(conference_bridge, conference_bridge_user->chan, "conf-onlyperson")) {
+				/* user hung up while the sound was playing */
+				return -1;
+			}
 		}
 		/* If we need to start music on hold on the channel do so now */
 		/* We need to re-check the number of users in the conference bridge here because another conference bridge
@@ -332,13 +342,16 @@
 		if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->flags, OPTION_MUSICONHOLD)) {
 			ast_moh_start(conference_bridge_user->chan, conference_bridge_user->opt_args[OPTION_MUSICONHOLD_CLASS], NULL);
 		}
-		return;
+		return 0;
 	}
 
 	/* Announce number of users if need be */
 	if (ast_test_flag(&conference_bridge_user->flags, OPTION_ANNOUNCEUSERCOUNT)) {
 		ao2_unlock(conference_bridge);
-		announce_user_count(conference_bridge, conference_bridge_user);
+		if (announce_user_count(conference_bridge, conference_bridge_user)) {
+			ao2_lock(conference_bridge);
+			return -1;
+		}
 		ao2_lock(conference_bridge);
 	}
 
@@ -352,6 +365,7 @@
 			ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
 		}
 	}
+	return 0;
 }
 
 /*!
@@ -382,6 +396,8 @@
 		conference_bridge->bridge = NULL;
 	}
 }
+
+static void leave_conference_bridge(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user);
 
 /*!
  * \brief Join a conference bridge
@@ -470,9 +486,17 @@
 
 	/* If the caller is a marked user or is waiting for a marked user to enter pass 'em off, otherwise pass them off to do regular joining stuff */
 	if (ast_test_flag(&conference_bridge_user->flags, OPTION_MARKEDUSER | OPTION_WAITMARKED)) {
-		post_join_marked(conference_bridge, conference_bridge_user);
+		if (post_join_marked(conference_bridge, conference_bridge_user)) {
+			ao2_unlock(conference_bridge);
+			leave_conference_bridge(conference_bridge, conference_bridge_user);
+			return NULL;
+		}
 	} else {
-		post_join_unmarked(conference_bridge, conference_bridge_user);
+		if (post_join_unmarked(conference_bridge, conference_bridge_user)) {
+			ao2_unlock(conference_bridge);
+			leave_conference_bridge(conference_bridge, conference_bridge_user);
+			return NULL;
+		}
 	}
 
 	ao2_unlock(conference_bridge);




More information about the asterisk-commits mailing list