[svn-commits] mjordan: trunk r370831 - in /trunk: ./ channels/ channels/misdn/ channels/sip...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Aug 7 07:46:43 CDT 2012


Author: mjordan
Date: Tue Aug  7 07:46:36 2012
New Revision: 370831

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=370831
Log:
Add named callgroups/pickupgroups

This patch adds named calledgroups/pickupgroups to Asterisk.  Named groups are
implemented in parallel to the existing numbered callgroup/pickupgroup
implementation.  However, unlike the existing implementation, which is limited
to a maximum of 64 defined groups, the number of defined groups allowed for
named callgroups/pickupgroups is effectively unlimited.

Named groups are configured with the keywords "namedcallgroup" and
"namedpickupgroup".  This corresponds to the numbered group definitions of
"callgroup" and "pickupgroup".  Note that as the implementation of named groups
coexists with the existing numbered implementation, a defined named group of
"4" does not equate to numbered group 4.

Support for the named groups has been added to the SIP, DAHDI, and mISDN channel
drivers.

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

Uploaded by:
	Guenther Kelleter(license #6372)


Modified:
    trunk/CHANGES
    trunk/channels/chan_dahdi.c
    trunk/channels/chan_misdn.c
    trunk/channels/chan_sip.c
    trunk/channels/misdn/chan_misdn_config.h
    trunk/channels/misdn_config.c
    trunk/channels/sip/include/sip.h
    trunk/configs/chan_dahdi.conf.sample
    trunk/configs/misdn.conf.sample
    trunk/configs/sip.conf.sample
    trunk/include/asterisk/channel.h
    trunk/main/channel.c
    trunk/main/channel_internal_api.c
    trunk/main/features.c

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Tue Aug  7 07:46:36 2012
@@ -109,11 +109,13 @@
  * Added 'm' option, which stores a copy of the recording as a voicemail in the
    indicated mailboxes.
 
+
 MySQL
 -------------------
  * The connect action in app_mysql now allows you to specify a port number to
    connect to.  This is useful if you run a MySQL server on a non-standard
    port number.
+
 
 OSP Applications
 -------------------
@@ -242,6 +244,9 @@
    send connected line information on initial connect; and update, to send
    information on any update during a call.  Default is update.
 
+ * Add options namedcallgroup and namedpickupgroup to support installations
+   where a higher number of groups (>64) is required.
+
 
 chan_motif
 ------------------
@@ -315,14 +320,19 @@
 
  * Add support for WebSocket transport. This can be configured using 'ws' or 'wss'
    as the transport.
+
  * Add options subminexpiry and submaxexpiry to set limits of subscription
    timer independently from registration timer settings. The setting of the
    registration timer limits still is done by options minexpiry, maxexpiry
    and defaultexpiry. For backwards compatibility the setting of minexpiry
    and maxexpiry also is used to configure the subscription timer limits if
    subminexpiry and submaxexpiry are not set in sip.conf.
+
  * Set registration timer limits to default values when reloading sip
    configuration and values are not set by configuration.
+
+ * Add options namedcallgroup and namedpickupgroup to support installations
+   where a higher number of groups (>64) is required.
 
  * When a MESSAGE request is received, the address the request was received from
    is now saved in the SIP_RECVADDR variable.
@@ -369,6 +379,12 @@
 
  * Added ability to pickup a call using features.conf defined value and
    on-screen key
+
+
+chan_mISDN:
+------------------
+ * Add options namedcallgroup and namedpickupgroup to support installations
+   where a higher number of groups (>64) is required.
 
 
 Core

Modified: trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Tue Aug  7 07:46:36 2012
@@ -1092,6 +1092,16 @@
 	 */
 	ast_group_t pickupgroup;
 	/*!
+	 * \brief Named call groups this belongs to.
+	 * \note The "namedcallgroup" string read in from chan_dahdi.conf
+	 */
+	struct ast_namedgroups *named_callgroups;
+	/*!
+	 * \brief Named pickup groups this belongs to.
+	 * \note The "namedpickupgroup" string read in from chan_dahdi.conf
+	 */
+	struct ast_namedgroups *named_pickupgroups;
+	/*!
 	 * \brief Channel variable list with associated values to set when a channel is created.
 	 * \note The "setvar" strings read in from chan_dahdi.conf
 	 */
@@ -5917,6 +5927,10 @@
 	if (p->cc_params) {
 		ast_cc_config_params_destroy(p->cc_params);
 	}
+
+	p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
+	p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
+
 	ast_mutex_destroy(&p->lock);
 	dahdi_close_sub(p, SUB_REAL);
 	if (p->owner)
@@ -9904,6 +9918,8 @@
 		/* Only FXO signalled stuff can be picked up */
 		ast_channel_callgroup_set(tmp, i->callgroup);
 		ast_channel_pickupgroup_set(tmp, i->pickupgroup);
+		ast_channel_named_callgroups_set(tmp, i->named_callgroups);
+		ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
 	}
 	if (!ast_strlen_zero(i->parkinglot))
 		ast_channel_parkinglot_set(tmp, i->parkinglot);
@@ -13159,6 +13175,10 @@
 		tmp->group = conf->chan.group;
 		tmp->callgroup = conf->chan.callgroup;
 		tmp->pickupgroup= conf->chan.pickupgroup;
+		ast_unref_namedgroups(tmp->named_callgroups);
+		tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
+		ast_unref_namedgroups(tmp->named_pickupgroups);
+		tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
 		if (conf->chan.vars) {
 			struct ast_variable *v, *tmpvar;
 	                for (v = conf->chan.vars ; v ; v = v->next) {
@@ -17557,6 +17577,10 @@
 				confp->chan.pickupgroup = 0;
 			else
 				confp->chan.pickupgroup = ast_get_group(v->value);
+		} else if (!strcasecmp(v->name, "namedcallgroup")) {
+			confp->chan.named_callgroups = ast_get_namedgroups(v->value);
+		} else if (!strcasecmp(v->name, "namedpickupgroup")) {
+			confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
 		} else if (!strcasecmp(v->name, "setvar")) {
 			char *varname = ast_strdupa(v->value), *varval = NULL;
 			struct ast_variable *tmpvar;
@@ -18541,6 +18565,11 @@
 		}
 		ast_cc_config_params_destroy(conf.chan.cc_params);
 	}
+
+	/* Since named callgroup and named pickup group are ref'd to dahdi_pvt at this point, unref container in confp's pvt. */
+	confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
+	confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
+
 	return 0;
 }
 

Modified: trunk/channels/chan_misdn.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_misdn.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/channels/chan_misdn.c (original)
+++ trunk/channels/chan_misdn.c Tue Aug  7 07:46:36 2012
@@ -5904,6 +5904,9 @@
 	char buf2[256];
 	ast_group_t pg;
 	ast_group_t cg;
+	struct ast_namedgroups *npg;
+	struct ast_namedgroups *ncg;
+	struct ast_str *tmp_str;
 
 	if (!ch) {
 		ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
@@ -5986,6 +5989,20 @@
 	chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
 	ast_channel_pickupgroup_set(ast, pg);
 	ast_channel_callgroup_set(ast, cg);
+
+	misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg));
+	misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg));
+
+	tmp_str = ast_str_create(1024);
+	if (tmp_str) {
+		chan_misdn_log(5, port, " --> * NamedCallGrp:%s\n", ast_print_namedgroups(&tmp_str, ncg));
+		ast_str_reset(tmp_str);
+		chan_misdn_log(5, port, " --> * NamedPickupGrp:%s\n", ast_print_namedgroups(&tmp_str, npg));
+		ast_free(tmp_str);
+	}
+
+	ast_channel_named_pickupgroups_set(ast, npg);
+	ast_channel_named_callgroups_set(ast, ncg);
 
 	if (ch->originator == ORG_AST) {
 		char callerid[BUFFERSIZE + 1];

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Tue Aug  7 07:46:36 2012
@@ -409,6 +409,12 @@
 					</enum>
 					<enum name="pickupgroup">
 						<para>The configured Pickupgroup.</para>
+					</enum>
+					<enum name="namedcallgroup">
+						<para>The configured Named Callgroup.</para>
+					</enum>
+					<enum name="namedpickupgroup">
+						<para>The configured Named Pickupgroup.</para>
 					</enum>
 					<enum name="codecs">
 						<para>The configured codecs.</para>
@@ -1453,6 +1459,7 @@
 static char *sip_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char *sip_show_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static void  print_group(int fd, ast_group_t group, int crlf);
+static void  print_named_groups(int fd, struct ast_namedgroups *groups, int crlf);
 static const char *dtmfmode2str(int mode) attribute_const;
 static int str2dtmfmode(const char *str) attribute_unused;
 static const char *insecure2str(int mode) attribute_const;
@@ -4907,6 +4914,9 @@
 		peer->socket.ws_session = NULL;
 	}
 
+	peer->named_callgroups = ast_unref_namedgroups(peer->named_callgroups);
+	peer->named_pickupgroups = ast_unref_namedgroups(peer->named_pickupgroups);
+
 	ast_cc_config_params_destroy(peer->cc_params);
 
 	ast_string_field_free_memory(peer);
@@ -5628,6 +5638,10 @@
 	ref_proxy(dialog, obproxy_get(dialog, peer));
 	dialog->callgroup = peer->callgroup;
 	dialog->pickupgroup = peer->pickupgroup;
+	ast_unref_namedgroups(dialog->named_callgroups);
+	dialog->named_callgroups = ast_ref_namedgroups(peer->named_callgroups);
+	ast_unref_namedgroups(dialog->named_pickupgroups);
+	dialog->named_pickupgroups = ast_ref_namedgroups(peer->named_pickupgroups);
 	ast_copy_string(dialog->zone, peer->zone, sizeof(dialog->zone));
 	dialog->allowtransfer = peer->allowtransfer;
 	dialog->jointnoncodeccapability = dialog->noncodeccapability;
@@ -6218,6 +6232,9 @@
 		ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
 		p->peerauth = NULL;
 	}
+
+	p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
+	p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
 
 	p->caps = ast_format_cap_destroy(p->caps);
 	p->jointcaps = ast_format_cap_destroy(p->jointcaps);
@@ -7570,6 +7587,10 @@
 
 	ast_channel_callgroup_set(tmp, i->callgroup);
 	ast_channel_pickupgroup_set(tmp, i->pickupgroup);
+
+	ast_channel_named_callgroups_set(tmp, i->named_callgroups);
+	ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
+
 	ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
 	ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
 	if (!ast_strlen_zero(i->parkinglot)) {
@@ -17344,6 +17365,10 @@
 		p->amaflags = peer->amaflags;
 		p->callgroup = peer->callgroup;
 		p->pickupgroup = peer->pickupgroup;
+		ast_unref_namedgroups(p->named_callgroups);
+		p->named_callgroups = ast_ref_namedgroups(peer->named_callgroups);
+		ast_unref_namedgroups(p->named_pickupgroups);
+		p->named_pickupgroups = ast_ref_namedgroups(peer->named_pickupgroups);
 		ast_format_cap_copy(p->caps, peer->caps);
 		ast_format_cap_copy(p->jointcaps, peer->caps);
 		p->prefs = peer->prefs;
@@ -18347,6 +18372,16 @@
 	ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) );
 }
 
+/*! \brief Print named call groups and pickup groups */
+static void print_named_groups(int fd, struct ast_namedgroups *group, int crlf)
+{
+	struct ast_str *buf = ast_str_create(1024);
+	if (buf) {
+		ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_namedgroups(&buf, group) );
+		ast_free(buf);
+	}
+}
+
 /*! \brief mapping between dtmf flags and strings */
 static const struct _map_x_s dtmfstr[] = {
 	{ SIP_DTMF_RFC2833,     "rfc2833" },
@@ -19002,6 +19037,10 @@
 		print_group(fd, peer->callgroup, 0);
 		ast_cli(fd, "  Pickupgroup  : ");
 		print_group(fd, peer->pickupgroup, 0);
+		ast_cli(fd, "  Named Callgr : ");
+		print_named_groups(fd, peer->named_callgroups, 0);
+		ast_cli(fd, "  Nam. Pickupgr: ");
+		print_named_groups(fd, peer->named_pickupgroups, 0);
 		peer_mailboxes_to_str(&mailbox_str, peer);
 		ast_cli(fd, "  MOH Suggest  : %s\n", peer->mohsuggest);
 		ast_cli(fd, "  Mailbox      : %s\n", mailbox_str->str);
@@ -19096,7 +19135,7 @@
 		peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer ptr");
 	} else  if (peer && type == 1) { /* manager listing */
 		char buffer[256];
-		struct ast_str *mailbox_str = ast_str_alloca(512);
+		struct ast_str *tmp_str = ast_str_alloca(512);
 		astman_append(s, "Channeltype: SIP\r\n");
 		astman_append(s, "ObjectName: %s\r\n", peer->name);
 		astman_append(s, "ChanObjectType: peer\r\n");
@@ -19118,9 +19157,15 @@
 		astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup));
 		astman_append(s, "Pickupgroup: ");
 		astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup));
+		astman_append(s, "Named Callgroup: ");
+		astman_append(s, "%s\r\n", ast_print_namedgroups(&tmp_str, peer->named_callgroups));
+		ast_str_reset(tmp_str);
+		astman_append(s, "Named Pickupgroup: ");
+		astman_append(s, "%s\r\n", ast_print_namedgroups(&tmp_str, peer->named_pickupgroups));
+		ast_str_reset(tmp_str);
 		astman_append(s, "MOHSuggest: %s\r\n", peer->mohsuggest);
-		peer_mailboxes_to_str(&mailbox_str, peer);
-		astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str);
+		peer_mailboxes_to_str(&tmp_str, peer);
+		astman_append(s, "VoiceMailbox: %s\r\n", tmp_str->str);
 		astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
 		astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
 		astman_append(s, "Maxforwards: %d\r\n", peer->maxforwards);
@@ -19287,6 +19332,10 @@
 		print_group(a->fd, user->callgroup, 0);
 		ast_cli(a->fd, "  Pickupgroup  : ");
 		print_group(a->fd, user->pickupgroup, 0);
+		ast_cli(a->fd, "  Named Callgr : ");
+		print_named_groups(a->fd, user->named_callgroups, 0);
+		ast_cli(a->fd, "  Nam. Pickupgr: ");
+		print_named_groups(a->fd, user->named_pickupgroups, 0);
 		ast_cli(a->fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), user->cid_name, user->cid_num, "<unspecified>"));
 		ast_cli(a->fd, "  ACL          : %s\n", AST_CLI_YESNO(ast_acl_list_is_empty(user->acl) == 0));
  		ast_cli(a->fd, "  Sess-Timers  : %s\n", stmode2str(user->stimer.st_mode_oper));
@@ -21039,6 +21088,18 @@
 		ast_print_group(buf, len, peer->callgroup);
 	} else  if (!strcasecmp(colname, "pickupgroup")) {
 		ast_print_group(buf, len, peer->pickupgroup);
+	} else  if (!strcasecmp(colname, "namedcallgroup")) {
+		struct ast_str *tmp_str = ast_str_create(1024);
+		if (tmp_str) {
+			ast_copy_string(buf, ast_print_namedgroups(&tmp_str, peer->named_callgroups), len);
+			ast_free(tmp_str);
+		}
+	} else  if (!strcasecmp(colname, "namedpickupgroup")) {
+		struct ast_str *tmp_str = ast_str_create(1024);
+		if (tmp_str) {
+			ast_copy_string(buf, ast_print_namedgroups(&tmp_str, peer->named_pickupgroups), len);
+			ast_free(tmp_str);
+		}
 	} else  if (!strcasecmp(colname, "useragent")) {
 		ast_copy_string(buf, peer->useragent, len);
 	} else  if (!strcasecmp(colname, "mailbox")) {
@@ -29430,6 +29491,10 @@
 			mailbox->delme = 1;
 		}
 	}
+
+	/* clear named callgroup and named pickup group container */
+	peer->named_callgroups = ast_unref_namedgroups(peer->named_callgroups);
+	peer->named_pickupgroups = ast_unref_namedgroups(peer->named_pickupgroups);
 
 	for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
 		if (!devstate_only) {
@@ -29668,6 +29733,10 @@
 				peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
 			} else if (!strcasecmp(v->name, "pickupgroup")) {
 				peer->pickupgroup = ast_get_group(v->value);
+			} else if (!strcasecmp(v->name, "namedcallgroup")) {
+				peer->named_callgroups = ast_get_namedgroups(v->value);
+			} else if (!strcasecmp(v->name, "namedpickupgroup")) {
+				peer->named_pickupgroups = ast_get_namedgroups(v->value);
 			} else if (!strcasecmp(v->name, "allow")) {
 				int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, TRUE);
 				if (error) {

Modified: trunk/channels/misdn/chan_misdn_config.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/misdn/chan_misdn_config.h?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/channels/misdn/chan_misdn_config.h (original)
+++ trunk/channels/misdn/chan_misdn_config.h Tue Aug  7 07:46:36 2012
@@ -89,6 +89,8 @@
 	MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD,              /* int */
 	MISDN_CFG_CALLGROUP,           /* ast_group_t */
 	MISDN_CFG_PICKUPGROUP,         /* ast_group_t */
+	MISDN_CFG_NAMEDCALLGROUP,      /* ast_namedgroups * */
+	MISDN_CFG_NAMEDPICKUPGROUP,    /* ast_namedgroups * */
 	MISDN_CFG_MAX_IN,              /* int */
 	MISDN_CFG_MAX_OUT,              /* int */
 	MISDN_CFG_L1_TIMEOUT,          /* int */

Modified: trunk/channels/misdn_config.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/misdn_config.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/channels/misdn_config.c (original)
+++ trunk/channels/misdn_config.c Tue Aug  7 07:46:36 2012
@@ -70,7 +70,8 @@
 	MISDN_CTYPE_BOOL,
 	MISDN_CTYPE_BOOLINT,
 	MISDN_CTYPE_MSNLIST,
-	MISDN_CTYPE_ASTGROUP
+	MISDN_CTYPE_ASTGROUP,
+	MISDN_CTYPE_ASTNAMEDGROUP
 };
 
 struct msn_list {
@@ -83,6 +84,7 @@
 	int *num;
 	struct msn_list *ml;
 	ast_group_t *grp;
+	struct ast_namedgroups *namgrp;
 	void *any;
 };
 
@@ -330,6 +332,10 @@
 		"Callgroup." },
 	{ "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE,
 		"Pickupgroup." },
+	{ "namedcallgroup", MISDN_CFG_NAMEDCALLGROUP, MISDN_CTYPE_ASTNAMEDGROUP, NO_DEFAULT, NONE,
+		"Named callgroup." },
+	{ "namedpickupgroup", MISDN_CFG_NAMEDPICKUPGROUP, MISDN_CTYPE_ASTNAMEDGROUP, NO_DEFAULT, NONE,
+		"Named pickupgroup." },
 	{ "max_incoming", MISDN_CFG_MAX_IN, MISDN_CTYPE_INT, "-1", NONE,
 		"Defines the maximum amount of incoming calls per port for this group.\n"
 		"\tCalls which exceed the maximum will be marked with the channel variable\n"
@@ -541,10 +547,13 @@
 	for (j = 0; free_list[j]; ++j) {
 		for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
 			if (free_list[j][i].any) {
-				if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
+				if (port_spec[i].type == MISDN_CTYPE_MSNLIST) {
 					_free_msn_list(free_list[j][i].ml);
-				else
+				} else if (port_spec[i].type == MISDN_CTYPE_ASTNAMEDGROUP) {
+					ast_unref_namedgroups(free_list[j][i].namgrp);
+				} else {
 					ast_free(free_list[j][i].any);
+				}
 			}
 		}
 	}
@@ -587,6 +596,17 @@
 						ast_copy_string(buf, port_cfg[0][place].str, bufsize);
 					} else
 						memset(buf, 0, bufsize);
+					break;
+				case MISDN_CTYPE_ASTNAMEDGROUP:
+					if (bufsize >= sizeof(struct ast_namedgroups *)) {
+						if (port_cfg[port][place].namgrp) {
+							*(struct ast_namedgroups **)buf = port_cfg[port][place].namgrp;
+						} else if (port_cfg[0][place].namgrp) {
+							*(struct ast_namedgroups **)buf = port_cfg[0][place].namgrp;
+						} else {
+							*(struct ast_namedgroups **)buf = NULL;
+						}
+					}
 					break;
 				default:
 					if (port_cfg[port][place].any)
@@ -831,6 +851,25 @@
 			else
 				snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
 			break;
+		case MISDN_CTYPE_ASTNAMEDGROUP:
+			if (port_cfg[port][place].namgrp) {
+				struct ast_str *tmp_str = ast_str_create(1024);
+				if (tmp_str) {
+					snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
+							ast_print_namedgroups(&tmp_str, port_cfg[port][place].namgrp));
+					ast_free(tmp_str);
+				}
+			} else if (port_cfg[0][place].namgrp) {
+				struct ast_str *tmp_str = ast_str_create(1024);
+				if (tmp_str) {
+					snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
+							ast_print_namedgroups(&tmp_str, port_cfg[0][place].namgrp));
+					ast_free(tmp_str);
+				}
+			} else {
+				snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+			}
+			break;
 		case MISDN_CTYPE_MSNLIST:
 			if (port_cfg[port][place].ml)
 				iter = port_cfg[port][place].ml;
@@ -983,6 +1022,9 @@
 			dest->grp = ast_malloc(sizeof(ast_group_t));
 		}
 		*(dest->grp) = ast_get_group(value);
+		break;
+	case MISDN_CTYPE_ASTNAMEDGROUP:
+		dest->namgrp = ast_get_namedgroups(value);
 		break;
 	}
 

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Tue Aug  7 07:46:36 2012
@@ -1062,6 +1062,8 @@
 	uint32_t init_icseq;                    /*!< Initial incoming seqno from first request */
 	ast_group_t callgroup;                  /*!< Call group */
 	ast_group_t pickupgroup;                /*!< Pickup group */
+	struct ast_namedgroups *named_callgroups;   /*!< Named call group */
+	struct ast_namedgroups *named_pickupgroups; /*!< Named pickup group */
 	uint32_t lastinvite;                    /*!< Last seqno of invite */
 	struct ast_flags flags[3];              /*!< SIP_ flags */
 
@@ -1328,6 +1330,8 @@
 	int rtpkeepalive;               /*!<  Send RTP packets for keepalive */
 	ast_group_t callgroup;          /*!<  Call group */
 	ast_group_t pickupgroup;        /*!<  Pickup group */
+	struct ast_namedgroups *named_callgroups;   /*!< Named call group */
+	struct ast_namedgroups *named_pickupgroups; /*!< Named pickup group */
 	struct sip_proxy *outboundproxy;/*!< Outbound proxy for this peer */
 	struct ast_dnsmgr_entry *dnsmgr;/*!<  DNS refresh manager for peer */
 	struct ast_sockaddr addr;        /*!<  IP address of peer */

Modified: trunk/configs/chan_dahdi.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/chan_dahdi.conf.sample?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/configs/chan_dahdi.conf.sample (original)
+++ trunk/configs/chan_dahdi.conf.sample Tue Aug  7 07:46:36 2012
@@ -841,6 +841,15 @@
 ;
 callgroup=1
 pickupgroup=1
+;
+; Named ring groups (a.k.a. named call groups) and named pickup groups.
+; If a phone is ringing and it is a member of a group which is one of your
+; named pickup groups, then you can answer it by picking up and dialing *8#.
+; For simple offices, just make these both the same.
+; The number of named groups is not limited.
+;
+;namedcallgroup=engineering,sales,netgroup,protgroup
+;namedpickupgroup=sales
 
 ; Channel variable to be set for all calls from this channel
 ;setvar=CHANNEL=42

Modified: trunk/configs/misdn.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/misdn.conf.sample?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/configs/misdn.conf.sample (original)
+++ trunk/configs/misdn.conf.sample Tue Aug  7 07:46:36 2012
@@ -390,6 +390,13 @@
 ;callgroup=1
 ;pickupgroup=1
 
+; Named pickup groups and named call groups
+;
+; give a name to groups and configure any number of groups
+;
+;namedcallgroup=engineering,sales,netgroup,protgroup
+;namedpickupgroup=sales
+
 ; Set the outgoing caller id to the value.
 ;callerid="name" <number>
 

Modified: trunk/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/sip.conf.sample?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/configs/sip.conf.sample (original)
+++ trunk/configs/sip.conf.sample Tue Aug  7 07:46:36 2012
@@ -1432,6 +1432,8 @@
 ;
 ;callgroup=1,3-4                 ; We are in caller groups 1,3,4
 ;pickupgroup=1,3-5               ; We can do call pick-p for call group 1,3,4,5
+;namedcallgroup=engineering,sales,netgroup,protgroup ; We are in named call groups engineering,sales,netgroup,protgroup
+;namedpickupgroup=sales          ; We can do call pick-p for named call group sales
 ;defaultip=192.168.0.60          ; IP address to use if peer has not registered
 ;deny=0.0.0.0/0.0.0.0            ; ACL: Control access to this account based on IP address
 ;permit=192.168.0.60/255.255.255.0

Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Tue Aug  7 07:46:36 2012
@@ -973,6 +973,17 @@
 	CHANNEL_ACL_RELOAD,
 };
 
+
+/*! \brief Structure to handle ao2-container for named groups */
+struct namedgroup_entry {
+	/*! string representation of group */
+	char *name;
+
+	/*! pre-built hash of groupname string */
+	unsigned int hash;
+};
+
+
 /*!
  * \note None of the datastore API calls lock the ast_channel they are using.
  *       So, the channel should be locked before calling the functions that
@@ -2417,8 +2428,21 @@
 
 ast_group_t ast_get_group(const char *s);
 
-/*! \brief print call- and pickup groups into buffer */
+/*! \brief Print call- and pickup groups into buffer */
 char *ast_print_group(char *buf, int buflen, ast_group_t group);
+
+/*! \brief Opaque struct holding a namedgroups set, i.e. a set of group names */
+struct ast_namedgroups;
+
+/*! \brief Create an ast_namedgroups set with group name from comma separated string s */
+struct ast_namedgroups *ast_get_namedgroups(const char *s);
+struct ast_namedgroups *ast_unref_namedgroups(struct ast_namedgroups *groups);
+struct ast_namedgroups *ast_ref_namedgroups(struct ast_namedgroups *groups);
+/*! \brief Return TRUE if group a and b contain at least one common groupname */
+int ast_namedgroups_intersect(struct ast_namedgroups *a, struct ast_namedgroups *b);
+
+/*! \brief Print named call groups and named pickup groups ---*/
+char *ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *groups);
 
 /*!
  * \brief Convert enum channelreloadreason to text string for manager event
@@ -3768,6 +3792,8 @@
 void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value);
 void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value);
 void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value);
+struct timeval ast_channel_creationtime(struct ast_channel *chan);
+void ast_channel_creationtime_set(struct ast_channel *chan, struct timeval *value);
 
 /* List getters */
 struct ast_hangup_handler_list *ast_channel_hangup_handlers(struct ast_channel *chan);
@@ -3780,6 +3806,10 @@
 void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value);
 ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan);
 void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value);
+struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan);
+void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value);
+struct ast_namedgroups *ast_channel_named_pickupgroups(const struct ast_channel *chan);
+void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value);
 
 /* Alertpipe accessors--the "internal" functions for channel.c use only */
 typedef enum {

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Tue Aug  7 07:46:36 2012
@@ -953,6 +953,7 @@
 	struct ast_format_cap *nativeformats;
 	struct ast_sched_context *schedctx;
 	struct ast_timer *timer;
+	struct timeval now;
 
 	/* If shutting down, don't allocate any new channels */
 	if (ast_shutting_down()) {
@@ -1041,6 +1042,9 @@
 
 	ast_channel_fin_set(tmp, global_fin);
 	ast_channel_fout_set(tmp, global_fout);
+
+	now = ast_tvnow();
+	ast_channel_creationtime_set(tmp, &now);
 
 	if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
 		ast_channel_uniqueid_build(tmp, "%li.%d", (long) time(NULL),
@@ -2339,6 +2343,10 @@
 	if (callid) {
 		ast_callid_unref(callid);
 	}
+
+	ast_channel_named_callgroups_set(chan, NULL);
+	ast_channel_named_pickupgroups_set(chan, NULL);
+
 	ast_atomic_fetchadd_int(&chancount, -1);
 }
 
@@ -8074,6 +8082,113 @@
 	return group;
 }
 
+/*! \brief Comparison function used for named group container */
+static int namedgroup_cmp_cb(void *obj, void *arg, int flags)
+{
+	const struct namedgroup_entry *an = obj;
+	const struct namedgroup_entry *bn = arg;
+	return strcmp(an->name, bn->name) ? 0 : CMP_MATCH | CMP_STOP;
+}
+
+/*! \brief Hashing function used for named group container */
+static int namedgroup_hash_cb(const void *obj, const int flags)
+{
+	const struct namedgroup_entry *entry = obj;
+	return entry->hash;
+}
+
+static void namedgroup_dtor(void *obj)
+{
+	ast_free(((struct namedgroup_entry*)obj)->name);
+}
+
+/*! \internal \brief Actually a refcounted ao2_object. An indirect ao2_container to hide the implementation of namedgroups. */
+struct ast_namedgroups {
+	struct ao2_container *container;
+};
+
+static void ast_namedgroups_dtor(void *obj)
+{
+	ao2_cleanup(((struct ast_namedgroups *)obj)->container);
+}
+
+struct ast_namedgroups *ast_get_namedgroups(const char *s)
+{
+	struct ast_namedgroups *namedgroups;
+	char *piece;
+	char *c;
+
+	if (ast_strlen_zero(s)) {
+		return NULL;
+	}
+	c = ast_strdupa(s);
+	if (!c) {
+		return NULL;
+	}
+
+	namedgroups = ao2_alloc_options(sizeof(*namedgroups), ast_namedgroups_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+	if (!namedgroups) {
+		return NULL;
+	}
+	namedgroups->container = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 19, namedgroup_hash_cb, namedgroup_cmp_cb);
+	if (!namedgroups->container) {
+		ao2_ref(namedgroups, -1);
+		return NULL;
+	}
+
+	/*! \brief Remove leading and trailing whitespace */
+	c = ast_strip(c);
+
+	while ((piece = strsep(&c, ","))) {
+		struct namedgroup_entry *entry;
+
+		/* remove leading/trailing whitespace */
+		piece = ast_strip(piece);
+		if (strlen(piece) == 0) {
+			ast_log(LOG_ERROR, "Syntax error parsing named group configuration '%s' at '%s'. Ignoring.\n", s, piece);
+			continue;
+		}
+
+		entry = ao2_alloc_options(sizeof(*entry), namedgroup_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+		if (!entry) {
+			ao2_ref(namedgroups, -1);
+			return NULL;
+		}
+		entry->name = ast_strdup(piece);
+		if (!entry->name) {
+			ao2_ref(entry, -1);
+			ao2_ref(namedgroups, -1);
+			return NULL;
+		}
+		entry->hash = ast_str_hash(entry->name);
+		/* every group name may exist only once, delete duplicates */
+		ao2_find(namedgroups->container, entry, OBJ_POINTER | OBJ_UNLINK | OBJ_NODATA);
+		ao2_link(namedgroups->container, entry);
+		ao2_ref(entry, -1);
+	}
+
+	if (ao2_container_count(namedgroups->container) == 0) {
+		ao2_ref(namedgroups, -1);
+		namedgroups = NULL;
+	}
+
+	return namedgroups;
+}
+
+struct ast_namedgroups *ast_unref_namedgroups(struct ast_namedgroups *groups)
+{
+	ao2_cleanup(groups);
+	return NULL;
+}
+
+struct ast_namedgroups *ast_ref_namedgroups(struct ast_namedgroups *groups)
+{
+	if (groups) {
+		ao2_ref(groups, 1);
+	}
+	return groups;
+}
+
 static int (*ast_moh_start_ptr)(struct ast_channel *, const char *, const char *) = NULL;
 static void (*ast_moh_stop_ptr)(struct ast_channel *) = NULL;
 static void (*ast_moh_cleanup_ptr)(struct ast_channel *) = NULL;
@@ -8302,6 +8417,59 @@
 		}
 	}
 	return buf;
+}
+
+/*! \brief Print named call group and named pickup group ---*/
+char *ast_print_namedgroups(struct ast_str **buf, struct ast_namedgroups *group)
+{
+	struct namedgroup_entry *ng;
+	int first = 1;
+	struct ao2_iterator it;
+
+	if (group == NULL) {
+		return ast_str_buffer(*buf);
+	}
+
+	it = ao2_iterator_init(group->container, 0);
+	while ((ng = ao2_iterator_next(&it))) {
+		if (!first) {
+			ast_str_append(buf, 0, ", ");
+		} else {
+			first = 0;
+		}
+		ast_str_append(buf, 0, "%s", ng->name);
+		ao2_ref(ng, -1);
+	}
+	ao2_iterator_destroy(&it);
+
+	return ast_str_buffer(*buf);
+}
+
+static int namedgroup_match(void *obj, void *arg, int flags)
+{
+	void *match;
+
+	match = ao2_find(arg, obj, OBJ_POINTER);
+	ao2_cleanup(match);
+
+	return match ? CMP_MATCH | CMP_STOP : 0;
+}
+
+int ast_namedgroups_intersect(struct ast_namedgroups *a, struct ast_namedgroups *b)
+{
+	/*
+	 * Do a and b intersect? Since b is hash table average time complexity is O(|a|)
+	 */
+	void *match;
+
+	if (!a || !b) {
+		return 0;
+	}
+
+	match = ao2_callback(a->container, 0, namedgroup_match, b->container);
+	ao2_cleanup(match);
+
+	return match != NULL;
 }
 
 void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)

Modified: trunk/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel_internal_api.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/main/channel_internal_api.c (original)
+++ trunk/main/channel_internal_api.c Tue Aug  7 07:46:36 2012
@@ -136,6 +136,9 @@
 	struct varshead varshead;			/*!< A linked list for channel variables. See \ref AstChanVar */
 	ast_group_t callgroup;				/*!< Call group for call pickups */
 	ast_group_t pickupgroup;			/*!< Pickup group - which calls groups can be picked up? */
+	struct ast_namedgroups *named_callgroups;	/*!< Named call group for call pickups */
+	struct ast_namedgroups *named_pickupgroups;	/*!< Named pickup group - which call groups can be picked up? */
+	struct timeval creationtime;			/*!< The time of channel creation */
 	struct ast_readq_list readq;
 	struct ast_jb jb;				/*!< The jitterbuffer state */
 	struct timeval dtmf_tv;				/*!< The time that an in process digit began, or the last digit ended */
@@ -983,6 +986,14 @@
 {
 	chan->varshead = *value;
 }
+struct timeval ast_channel_creationtime(struct ast_channel *chan)
+{
+	return chan->creationtime;
+}
+void ast_channel_creationtime_set(struct ast_channel *chan, struct timeval *value)
+{
+	chan->creationtime = *value;
+}
 
 /* Evil softhangup accessors */
 int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
@@ -1025,6 +1036,24 @@
 void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
 {
 	chan->pickupgroup = value;
+}
+struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan)
+{
+	return chan->named_callgroups;
+}
+void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
+{
+	ast_unref_namedgroups(chan->named_callgroups);
+	chan->named_callgroups = ast_ref_namedgroups(value);
+}
+struct ast_namedgroups *ast_channel_named_pickupgroups(const struct ast_channel *chan)
+{
+	return chan->named_pickupgroups;
+}
+void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
+{
+	ast_unref_namedgroups(chan->named_pickupgroups);
+	chan->named_pickupgroups = ast_ref_namedgroups(value);
 }
 
 /* Alertpipe functions */

Modified: trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/features.c?view=diff&rev=370831&r1=370830&r2=370831
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Tue Aug  7 07:46:36 2012
@@ -7679,10 +7679,19 @@
 	struct ast_channel *chan = data;/*!< Channel wanting to pickup call */
 
 	ast_channel_lock(target);
-	if (chan != target && (ast_channel_pickupgroup(chan) & ast_channel_callgroup(target))
-		&& ast_can_pickup(target)) {
-		/* Return with the channel still locked on purpose */
-		return CMP_MATCH | CMP_STOP;
+
+	/*
+	 * Both, callgroup and namedcallgroup pickup variants are matched independently.
+	 * Checking for named group match is done last since it's a rather expensive operation.
+	 */
+	if (chan != target && ast_can_pickup(target)
+		&& ((ast_channel_pickupgroup(chan) & ast_channel_callgroup(target))
+			|| (ast_namedgroups_intersect(ast_channel_named_pickupgroups(chan), ast_channel_named_callgroups(target))))) {
+		/*
+		 * Return with the channel unlocked on purpose, else we would lock many channels with the chance for deadlock
+		 */
+		ast_channel_unlock(target);
+		return CMP_MATCH;
 	}
 	ast_channel_unlock(target);
 
@@ -7700,11 +7709,36 @@
 int ast_pickup_call(struct ast_channel *chan)
 {
 	struct ast_channel *target;/*!< Potential pickup target */
+	struct ao2_iterator *targets_it;/*!< Potential pickup targets, must find the oldest of them */
+	struct ast_channel *candidate;/*!< Potential new older target */
 	int res = -1;
 	ast_debug(1, "pickup attempt by %s\n", ast_channel_name(chan));
 
-	/* The found channel is already locked. */
-	target = ast_channel_callback(find_channel_by_group, NULL, chan, 0);
+	/*
+	 * Transfer all pickup-able channels to another container-iterator.
+	 * Iterate it to find the oldest channel.
+	 */
+	targets_it = (struct ao2_iterator *)ast_channel_callback(find_channel_by_group, NULL, chan, OBJ_MULTIPLE);
+
+	target = NULL;
+	while ((candidate = ao2_iterator_next(targets_it))) {
+		if (!target || ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) {
+			target = candidate;
+		}
+		ast_channel_unref(candidate);
+	}
+	if (target) {
+		/* The found channel must be locked and ref'd. */
+		ast_channel_lock(ast_channel_ref(target));
+		/* Recheck pickup ability */
+		if (!ast_can_pickup(target)) {
+			ast_channel_unlock(target);
+			target = ast_channel_unref(target);/* Bad luck */
+		}
+	}
+
+	ao2_iterator_destroy(targets_it);
+
 	if (target) {
 		ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
 




More information about the svn-commits mailing list