[svn-commits] rmudgett: branch rmudgett/parking r330819 - /team/rmudgett/parking/main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Aug 3 11:37:49 CDT 2011


Author: rmudgett
Date: Wed Aug  3 11:37:45 2011
New Revision: 330819

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=330819
Log:
Factored manage_parked_call() out of manage_parkinglot() to eliminate
using ast_strdupa() within in a loop in a function.

Modified:
    team/rmudgett/parking/main/features.c

Modified: team/rmudgett/parking/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/features.c?view=diff&rev=330819&r1=330818&r2=330819
==============================================================================
--- team/rmudgett/parking/main/features.c (original)
+++ team/rmudgett/parking/main/features.c Wed Aug  3 11:37:45 2011
@@ -4122,214 +4122,252 @@
 	return options;
 }
 
+/*!
+ * \internal
+ * \brief Run management on a parked call.
+ *
+ * \note The parkinglot parkings list is locked on entry.
+ *
+ * \retval TRUE if the parking completed.
+ */
+static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
+{
+	struct ast_channel *chan = pu->chan;	/* shorthand */
+	int tms;        /* timeout for this item */
+	int x;          /* fd index in channel */
+	struct ast_context *con;
+	int parking_complete = 0;
+
+	tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+	if (tms > pu->parkingtime) {
+/* BUGBUG stop MOH or RINGING depending on what was last sent */
+		/*
+		 * Call has been parked too long.
+		 * Stop music on hold
+		 */
+		ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+
+		/* Get chan, exten from derived kludge */
+		if (pu->peername[0]) {
+			char *peername;
+			char *dash;
+			char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
+			int i;
+
+			peername = ast_strdupa(pu->peername);
+			dash = strrchr(peername, '-');
+			if (dash) {
+				*dash = '\0';
+			}
+
+			peername_flat = ast_strdupa(peername);
+			for (i = 0; peername_flat[i]; i++) {
+				if (peername_flat[i] == '/') {
+					peername_flat[i] = '_';
+				}
+			}
+
+			con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
+			if (!con) {
+				ast_log(LOG_ERROR,
+					"Parking dial context '%s' does not exist and unable to create\n",
+					parking_con_dial);
+			} else {
+				char returnexten[AST_MAX_EXTENSION];
+				struct ast_datastore *features_datastore;
+				struct ast_dial_features *dialfeatures;
+
+				if (!strncmp(peername, "Parked/", 7)) {
+					peername += 7;
+				}
+
+				ast_channel_lock(chan);
+				features_datastore = ast_channel_datastore_find(chan, &dial_features_info,
+					NULL);
+				if (features_datastore && (dialfeatures = features_datastore->data)) {
+					char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
+
+					snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername,
+						callback_dialoptions(&(dialfeatures->features_callee),
+							&(dialfeatures->features_caller), buf, sizeof(buf)));
+				} else { /* Existing default */
+					ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
+						chan->name);
+					snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
+				}
+				ast_channel_unlock(chan);
+
+				ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial",
+					ast_strdup(returnexten), ast_free_ptr, registrar);
+			}
+			if (pu->options_specified) {
+				/*
+				 * Park() was called with overriding return arguments, respect
+				 * those arguments.
+				 */
+				set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+			} else if (comebacktoorigin) {
+				set_c_e_p(chan, parking_con_dial, peername_flat, 1);
+			} else {
+				char parkingslot[AST_MAX_EXTENSION];
+
+				snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+				pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
+				set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
+			}
+		} else {
+			/*
+			 * They've been waiting too long, send them back to where they
+			 * came.  Theoretically they should have their original
+			 * extensions and such, but we copy to be on the safe side.
+			 */
+			set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+		}
+		post_manager_event("ParkedCallTimeOut", pu);
+		ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
+
+		ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n",
+			pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context,
+			pu->chan->exten, pu->chan->priority);
+
+		/* Start up the PBX, or hang them up */
+		if (ast_pbx_start(chan))  {
+			ast_log(LOG_WARNING,
+				"Unable to restart the PBX for user on '%s', hanging them up...\n",
+				pu->chan->name);
+			ast_hangup(chan);
+		}
+
+		/* And take them out of the parking lot */
+		parking_complete = 1;
+	} else {	/* still within parking time, process descriptors */
+		for (x = 0; x < AST_MAX_FDS; x++) {
+			struct ast_frame *f;
+			int y;
+
+			if (chan->fds[x] == -1) {
+				continue;	/* nothing on this descriptor */
+			}
+
+			for (y = 0; y < nfds; y++) {
+				if (pfds[y].fd == chan->fds[x]) {
+					/* Found poll record! */
+					break;
+				}
+			}
+			if (y == nfds) {
+				/* Not found */
+				continue;
+			}
+
+			if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
+				/* Next x */
+				continue;
+			}
+
+			if (pfds[y].revents & POLLPRI) {
+				ast_set_flag(chan, AST_FLAG_EXCEPTION);
+			} else {
+				ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+			}
+			chan->fdno = x;
+
+			/* See if they need servicing */
+			f = ast_read(pu->chan);
+			/* Hangup? */
+			if (!f || (f->frametype == AST_FRAME_CONTROL
+				&& f->subclass.integer == AST_CONTROL_HANGUP)) {
+				if (f) {
+					ast_frfree(f);
+				}
+				post_manager_event("ParkedCallGiveUp", pu);
+				ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp",
+					NULL);
+
+				/* There's a problem, hang them up */
+				ast_verb(2, "%s got tired of being parked\n", chan->name);
+				ast_hangup(chan);
+
+				/* And take them out of the parking lot */
+				parking_complete = 1;
+				break;
+			} else {
+				/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
+				ast_frfree(f);
+				if (pu->moh_trys < 3 && !chan->generatordata) {
+					ast_debug(1,
+						"MOH on parked call stopped by outside source.  Restarting on channel %s.\n",
+						chan->name);
+					ast_indicate_data(chan, AST_CONTROL_HOLD,
+						S_OR(pu->parkinglot->cfg.mohclass, NULL),
+						(!ast_strlen_zero(pu->parkinglot->cfg.mohclass)
+							? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0));
+					pu->moh_trys++;
+				}
+				goto std;	/* XXX Ick: jumping into an else statement??? XXX */
+			}
+		} /* End for */
+		if (x >= AST_MAX_FDS) {
+std:		for (x = 0; x < AST_MAX_FDS; x++) {	/* mark fds for next round */
+				if (chan->fds[x] > -1) {
+					void *tmp = ast_realloc(*new_pfds,
+						(*new_nfds + 1) * sizeof(struct pollfd));
+
+					if (!tmp) {
+						continue;
+					}
+					*new_pfds = tmp;
+					(*new_pfds)[*new_nfds].fd = chan->fds[x];
+					(*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
+					(*new_pfds)[*new_nfds].revents = 0;
+					(*new_nfds)++;
+				}
+			}
+			/* Keep track of our shortest wait */
+			if (tms < *ms || *ms < 0) {
+				*ms = tms;
+			}
+		}
+	}
+
+	return parking_complete;
+}
+
 /*! \brief Run management on parkinglots, called once per parkinglot */
-static int manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, const int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
+static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
 {
 	struct parkeduser *pu;
-	int res = 0;
-
-	/* Lock parking list */
+	struct ast_context *con;
+
+	/* Lock parkings list */
 	AST_LIST_LOCK(&curlot->parkings);
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
-		struct ast_channel *chan = pu->chan;	/* shorthand */
-		int tms;        /* timeout for this item */
-		int x;          /* fd index in channel */
-		struct ast_context *con;
-
 		if (pu->notquiteyet) { /* Pretend this one isn't here yet */
 			continue;
 		}
-		tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
-		if (tms > pu->parkingtime) {
-/* BUGBUG stop MOH or RINGING depending on what was configured */
-			/* Stop music on hold */
-			ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
-			/* Get chan, exten from derived kludge */
-			if (pu->peername[0]) {
-/* BUGBUG allocating from the stack within a loop here! */
-				char *peername = ast_strdupa(pu->peername);
-				char *dash = strrchr(peername, '-');
-				char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
-				int i;
-
-				if (dash) {
-					*dash = '\0';
-				}
-
-/* BUGBUG again allocating from the stack within a loop here! */
-				peername_flat = ast_strdupa(peername);
-				for (i = 0; peername_flat[i]; i++) {
-					if (peername_flat[i] == '/') {
-						peername_flat[i] = '_';
-					}
-				}
-
-				con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
-				if (!con) {
-					ast_log(LOG_ERROR,
-						"Parking dial context '%s' does not exist and unable to create\n",
-						parking_con_dial);
-				} else {
-					char returnexten[AST_MAX_EXTENSION];
-					struct ast_datastore *features_datastore;
-					struct ast_dial_features *dialfeatures = NULL;
-
-					ast_channel_lock(chan);
-
-					if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
-						dialfeatures = features_datastore->data;
-
-					ast_channel_unlock(chan);
-
-					if (!strncmp(peername, "Parked/", 7)) {
-						peername += 7;
-					}
-
-					if (dialfeatures) {
-						char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
-						snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
-					} else { /* Existing default */
-						ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n", chan->name);
-						snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
-					}
-
-					ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
-				}
-				if (pu->options_specified) {
-					/* Park() was called with overriding return arguments, respect those arguments */
-					set_c_e_p(chan, pu->context, pu->exten, pu->priority);
-				} else {
-					if (comebacktoorigin) {
-						set_c_e_p(chan, parking_con_dial, peername_flat, 1);
-					} else {
-						char parkingslot[AST_MAX_EXTENSION];
-
-						snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
-						pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
-						set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
-					}
-				}
-			} else {
-				/* They've been waiting too long, send them back to where they came.  Theoretically they
-				   should have their original extensions and such, but we copy to be on the safe side */
-				set_c_e_p(chan, pu->context, pu->exten, pu->priority);
-			}
-			post_manager_event("ParkedCallTimeOut", pu);
-			ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
-
-			ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
-			/* Start up the PBX, or hang them up */
-			if (ast_pbx_start(chan))  {
-				ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
-				ast_hangup(chan);
-			}
-			/* And take them out of the parking lot */
+		if (manage_parked_call(pu, pfds, nfds, new_pfds, new_nfds, ms)) {
+			/* Parking is complete for this call so remove it from the parking lot. */
 			con = ast_context_find(pu->parkinglot->cfg.parking_con);
 			if (con) {
-				if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
-					ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
-				else
-					notify_metermaids(pu->parkingexten, curlot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
-			} else
-				ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+				if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
+					ast_log(LOG_WARNING,
+						"Whoa, failed to remove the parking extension %s@%s!\n",
+						pu->parkingexten, pu->parkinglot->cfg.parking_con);
+				}
+				notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con,
+					AST_DEVICE_NOT_INUSE);
+			} else {
+				ast_log(LOG_WARNING,
+					"Whoa, parking lot '%s' context '%s' does not exist.\n",
+					pu->parkinglot->name, pu->parkinglot->cfg.parking_con);
+			}
 			AST_LIST_REMOVE_CURRENT(list);
 			parkinglot_unref(pu->parkinglot);
 			ast_free(pu);
-		} else {	/* still within parking time, process descriptors */
-			for (x = 0; x < AST_MAX_FDS; x++) {
-				struct ast_frame *f;
-				int y;
-
-				if (chan->fds[x] == -1) {
-					continue;	/* nothing on this descriptor */
-				}
-
-				for (y = 0; y < nfds; y++) {
-					if (pfds[y].fd == chan->fds[x]) {
-						/* Found poll record! */
-						break;
-					}
-				}
-				if (y == nfds) {
-					/* Not found */
-					continue;
-				}
-
-				if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
-					/* Next x */
-					continue;
-				}
-
-				if (pfds[y].revents & POLLPRI) {
-					ast_set_flag(chan, AST_FLAG_EXCEPTION);
-				} else {
-					ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-				}
-				chan->fdno = x;
-
-				/* See if they need servicing */
-				f = ast_read(pu->chan);
-				/* Hangup? */
-				if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer ==  AST_CONTROL_HANGUP))) {
-					if (f)
-						ast_frfree(f);
-					post_manager_event("ParkedCallGiveUp", pu);
-					ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp", NULL);
-
-					/* There's a problem, hang them up*/
-					ast_verb(2, "%s got tired of being parked\n", chan->name);
-					ast_hangup(chan);
-					/* And take them out of the parking lot */
-					con = ast_context_find(curlot->cfg.parking_con);
-					if (con) {
-						if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
-							ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
-						else
-							notify_metermaids(pu->parkingexten, curlot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
-					} else
-						ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
-					AST_LIST_REMOVE_CURRENT(list);
-					parkinglot_unref(pu->parkinglot);
-					ast_free(pu);
-					break;
-				} else {
-					/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
-					ast_frfree(f);
-					if (pu->moh_trys < 3 && !chan->generatordata) {
-						ast_debug(1, "MOH on parked call stopped by outside source.  Restarting on channel %s.\n", chan->name);
-						ast_indicate_data(chan, AST_CONTROL_HOLD, 
-							S_OR(curlot->cfg.mohclass, NULL),
-							(!ast_strlen_zero(curlot->cfg.mohclass) ? strlen(curlot->cfg.mohclass) + 1 : 0));
-						pu->moh_trys++;
-					}
-					goto std;	/* XXX Ick: jumping into an else statement??? XXX */
-				}
-			} /* End for */
-			if (x >= AST_MAX_FDS) {
-std:			for (x = 0; x < AST_MAX_FDS; x++) {	/* mark fds for next round */
-					if (chan->fds[x] > -1) {
-						void *tmp = ast_realloc(*new_pfds, (*new_nfds + 1) * sizeof(struct pollfd));
-						if (!tmp) {
-							continue;
-						}
-						*new_pfds = tmp;
-						(*new_pfds)[*new_nfds].fd = chan->fds[x];
-						(*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
-						(*new_pfds)[*new_nfds].revents = 0;
-						(*new_nfds)++;
-					}
-				}
-				/* Keep track of our shortest wait */
-				if (tms < *ms || *ms < 0) {
-					*ms = tms;
-				}
-			}
 		}
 	}
 	AST_LIST_TRAVERSE_SAFE_END;
 	AST_LIST_UNLOCK(&curlot->parkings);
-
-	return res;
 }
 
 /*! 




More information about the svn-commits mailing list