[svn-commits] mvanbaak: branch group/multiparking r104052 - /team/group/multiparking/main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Feb 23 09:54:37 CST 2008


Author: mvanbaak
Date: Sat Feb 23 09:54:36 2008
New Revision: 104052

URL: http://svn.digium.com/view/asterisk?view=rev&rev=104052
Log:
create manager function for parked calls in parking lots

Modified:
    team/group/multiparking/main/features.c

Modified: team/group/multiparking/main/features.c
URL: http://svn.digium.com/view/asterisk/team/group/multiparking/main/features.c?view=diff&rev=104052&r1=104051&r2=104052
==============================================================================
--- team/group/multiparking/main/features.c (original)
+++ team/group/multiparking/main/features.c Sat Feb 23 09:54:36 2008
@@ -2257,6 +2257,174 @@
 		);
 }
 
+/*! \brief Run management on parkinglots, collad once per parkinglot */
+int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds)
+{
+
+	int ms = -1;	/* select timeout, uninitialized */
+	int max = -1;	/* max fd, none there yet */
+	struct parkeduser *pu, *pl = NULL, *pt = NULL;
+	int res = 0;
+
+	parkinglot_addref(curlot);
+	pu = curlot->occupiedlots;
+	while(pu) {
+		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 */
+			pl = pu;
+			pu = pu->next;
+			continue;
+		}
+		tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+		if (tms > pu->parkingtime) {
+			/* Stop music on hold */
+			ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+			/* Get chan, exten from derived kludge */
+			if (pu->peername[0]) {
+				char *peername = ast_strdupa(pu->peername);
+				char *cp = strrchr(peername, '-');
+				char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
+				int i;
+
+
+				if (cp) 
+					*cp = 0;
+				ast_copy_string(peername_flat,peername,sizeof(peername_flat));
+				for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
+					if (peername_flat[i] == '/') 
+						peername_flat[i]= '0';
+				}
+				con = ast_context_find(pu->parkinglot->parking_con_dial);
+				if (!con) {
+					con = ast_context_create(NULL, pu->parkinglot->parking_con_dial, registrar);
+					if (!con) 
+						ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
+				}
+
+				if (con)
+					ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
+
+				if (comebacktoorigin)
+					set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername, 1);
+				else {
+					char parkingslot[AST_MAX_EXTENSION];
+					ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
+					snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+					pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
+					set_c_e_p(chan, "parkedcallstimeout", peername, 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_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 (pl) 
+				pl->next = pu->next;
+			else
+				curlot->occupiedlots = pu->next;
+			pt = pu;
+			pu = pu->next;
+			con = ast_context_find(pt->parkinglot->parking_con);
+			if (con) {
+				if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+					ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+				else
+					notify_metermaids(pt->parkingexten, curlot->parking_con);
+			} else
+				ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+			free(pt);
+			parkinglot_unref(curlot);
+		} else {	/* still within parking time, process descriptors */
+			for (x = 0; x < AST_MAX_FDS; x++) {
+				struct ast_frame *f;
+
+				if ((chan->fds[x] == -1) && (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds))) 
+					continue;
+
+				if (FD_ISSET(chan->fds[x], efds))
+					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 ==  AST_CONTROL_HANGUP))) {
+					if (f)
+						ast_frfree(f);
+					post_manager_event("ParkedCallGiveUp", pu);
+
+					/* 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 */
+					if (pl) 
+						pl->next = pu->next;
+					else
+						curlot->occupiedlots = pu->next;
+					pt = pu;
+					pu = pu->next;
+					con = ast_context_find(curlot->parking_con);
+					if (con) {
+						if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+							ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+						else
+							notify_metermaids(pt->parkingexten, curlot->parking_con);
+					} else
+						ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
+					free(pt);
+					parkinglot_unref(curlot);
+					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(parkmohclass, NULL),
+							!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 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) {
+						FD_SET(chan->fds[x], nrfds);
+						FD_SET(chan->fds[x], nefds);
+						if (chan->fds[x] > max)
+							max = chan->fds[x];
+					}
+				}
+				/* Keep track of our shortest wait */
+				if (tms < ms || ms < 0)
+					ms = tms;
+				pl = pu;
+				pu = pu->next;
+			}
+		}
+	}
+	return res;
+}
+
 /*! 
  * \brief Take care of parked calls and unpark them if needed 
  * \param ignore unused var.
@@ -2274,146 +2442,19 @@
 	FD_ZERO(&efds);
 
 	for (;;) {
-SKREP
-		struct parkeduser *pu;
+		int res = 0;
 		int ms = -1;	/* select timeout, uninitialized */
 		int max = -1;	/* max fd, none there yet */
 		fd_set nrfds, nefds;	/* args for the next select */
 		FD_ZERO(&nrfds);
 		FD_ZERO(&nefds);
 
-		AST_LIST_LOCK(&parkings);
-		AST_LIST_TRAVERSE_SAFE_BEGIN(&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) {
-				ast_indicate(chan, AST_CONTROL_UNHOLD);
-				/* Get chan, exten from derived kludge */
-				if (pu->peername[0]) {
-					char *peername = ast_strdupa(pu->peername);
-					char *cp = strrchr(peername, '-');
-					char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
-					int i;
-
-					if (cp) 
-						*cp = 0;
-					ast_copy_string(peername_flat,peername,sizeof(peername_flat));
-					for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
-						if (peername_flat[i] == '/') 
-							peername_flat[i]= '0';
-					}
-					con = ast_context_find(parking_con_dial);
-					if (!con) {
-						con = ast_context_create(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);
-					}
-					if (con) {
-						ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
-					}
-					if (comebacktoorigin) { 
-						set_c_e_p(chan, parking_con_dial, peername_flat, 1);
-					} else {
-						ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
-						snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
-						pbx_builtin_setvar_helper(pu->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_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, 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", chan->name);
-					ast_hangup(chan);
-				}
-				/* And take them out of the parking lot */
-				AST_LIST_REMOVE_CURRENT(list);
-				con = ast_context_find(parking_con);
-				if (con) {
-					if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
-						ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
-					else
-						notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
-				} else
-					ast_log(LOG_WARNING, "Whoa, no parking context?\n");
-				ast_free(pu);
-			} else {	/* still within parking time, process descriptors */
-				for (x = 0; x < AST_MAX_FDS; x++) {
-					struct ast_frame *f;
-
-					if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
-						continue;	/* nothing on this descriptor */
-
-					if (FD_ISSET(chan->fds[x], &efds))
-						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(chan);
-					if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass ==  AST_CONTROL_HANGUP)) {
-						if (f)
-							ast_frfree(f);
-						post_manager_event("ParkedCallGiveUp", pu);
-
-						/* 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 */
-						AST_LIST_REMOVE_CURRENT(list);
-						con = ast_context_find(parking_con);
-						if (con) {
-							if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
-								ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
-							else
-								notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
-						} else
-							ast_log(LOG_WARNING, "Whoa, no parking context?\n");
-						ast_free(pu);
-						break;
-					} else {
-						/*! \todo 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.\n");
-							ast_indicate_data(chan, AST_CONTROL_HOLD, 
-								S_OR(parkmohclass, NULL),
-								!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
-							pu->moh_trys++;
-						}
-						goto std;	/*! \todo 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) {
-							FD_SET(chan->fds[x], &nrfds);
-							FD_SET(chan->fds[x], &nefds);
-							if (chan->fds[x] > max)
-								max = chan->fds[x];
-						}
-					}
-					/* Keep track of our shortest wait */
-					if (tms < ms || ms < 0)
-						ms = tms;
-				}
-			}
-		} /* end while */
+		ASTOBJ_CONTAINER_TRAVERSE(&parkinglots, 1, do {
+			
+			ASTOBJ_WRLOCK(iterator);
+			res = manage_parkinglot(iterator, &rfds, &efds, &nrfds, &nefds);
+			ASTOBJ_UNLOCK(iterator);
+		} while (0) );
 		AST_LIST_TRAVERSE_SAFE_END
 		AST_LIST_UNLOCK(&parkings);
 		rfds = nrfds;




More information about the svn-commits mailing list