Index: channels/misdn_config.c =================================================================== --- channels/misdn_config.c (revision 241015) +++ channels/misdn_config.c (working copy) @@ -811,10 +811,10 @@ case MISDN_CTYPE_ASTGROUP: if (port_cfg[port][place].grp) snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, - ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp)); + ast_print_group(tempbuf, sizeof(tempbuf), port_cfg[port][place].grp)); else if (port_cfg[0][place].grp) snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, - ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp)); + ast_print_group(tempbuf, sizeof(tempbuf), port_cfg[0][place].grp)); else snprintf(buf, bufsize, " -> %s:", port_spec[place].name); break; @@ -969,7 +969,7 @@ if (!dest->grp) { dest->grp = ast_malloc(sizeof(ast_group_t)); } - *(dest->grp) = ast_get_group(value); + ast_get_group(dest->grp, value); break; } Index: channels/chan_jingle.c =================================================================== --- channels/chan_jingle.c (revision 241015) +++ channels/chan_jingle.c (working copy) @@ -842,8 +842,8 @@ tmp->rawreadformat = fmt; tmp->tech_pvt = i; - tmp->callgroup = client->callgroup; - tmp->pickupgroup = client->pickupgroup; + memcpy(&tmp->callgroup, client->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, client->pickupgroup, sizeof(tmp->pickupgroup)); tmp->cid.cid_pres = client->callingpres; if (!ast_strlen_zero(client->accountcode)) ast_string_field_set(tmp, accountcode, client->accountcode); Index: channels/chan_dahdi.c =================================================================== --- channels/chan_dahdi.c (revision 241015) +++ channels/chan_dahdi.c (working copy) @@ -8670,8 +8670,8 @@ tmp->tech_pvt = i; if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { /* Only FXO signalled stuff can be picked up */ - tmp->callgroup = i->callgroup; - tmp->pickupgroup = i->pickupgroup; + memcpy(&tmp->callgroup, i->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, i->pickupgroup, sizeof(tmp->pickupgroup)); } if (!ast_strlen_zero(i->parkinglot)) ast_string_field_set(tmp, parkinglot, i->parkinglot); @@ -11619,9 +11619,9 @@ tmp->mwisend_rpas = conf->chan.mwisend_rpas; #endif - tmp->group = conf->chan.group; - tmp->callgroup = conf->chan.callgroup; - tmp->pickupgroup= conf->chan.pickupgroup; + memcpy(&tmp->group, conf->chan.group, sizeof(tmp->group)); + memcpy(&tmp->callgroup, conf->chan.callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, conf->chan.pickupgroup, sizeof(tmp->pickupgroup)); if (conf->chan.vars) { tmp->vars = ast_variable_new(conf->chan.vars->name, conf->chan.vars->value, ""); } @@ -11798,12 +11798,13 @@ return tmp; } -static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched) +static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t *groupmatch, int *reason, int *channelmatched, int *groupmatched) { /* First, check group matching */ if (groupmatch) { - if ((p->group & groupmatch) != groupmatch) + if (!ast_have_common_group(&p->group, groupmatch)) { return 0; + } *groupmatched = 1; } /* Check to see if we have a channel match */ @@ -12008,7 +12009,7 @@ static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) { - ast_group_t groupmatch = 0; + ast_group_t groupmatch; int channelmatch = -1; int roundrobin = 0; int callwait = 0; @@ -12031,6 +12032,7 @@ //AST_APP_ARG(opts); /* options token */ AST_APP_ARG(other); /* Any remining unused arguments */ ); + memset(&groupmatch, 0, sizeof(groupmatch)); /* * data is ---v @@ -12061,13 +12063,15 @@ } if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') { + char buf[12]; /* Retrieve the group number */ s = args.group + 1; if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); return NULL; } - groupmatch = ((ast_group_t) 1 << x); + sprintf(buf, "%d", x); + ast_get_group(&groupmatch, buf); /* Lock the interface list */ ast_mutex_lock(&iflock); @@ -12115,10 +12119,14 @@ if (roundrobin) round_robin[x] = p; #if 0 - ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "", p->channel, channelmatch, groupmatch); + { + char buf[64]; + ast_verbose("name = %s, %d, %d, %s\n",p->owner ? p->owner->name : "", + p->channel, channelmatch, ast_print_group(buf, sizeof(buf), &groupmatch)); + } #endif - if (p && available(p, channelmatch, groupmatch, &unavailreason, &channelmatched, &groupmatched)) { + if (p && available(p, channelmatch, &groupmatch, &unavailreason, &channelmatched, &groupmatched)) { ast_debug(1, "Using channel %d\n", p->channel); callwait = (p->owner != NULL); @@ -14290,9 +14298,14 @@ ast_mutex_lock(&iflock); for (tmp = iflist; tmp; tmp = tmp->next) { if (filtertype) { + char buf[12]; + ast_group_t targetgrp; + switch(filtertype) { case 1: /* dahdi show channels group */ - if (!(tmp->group & targetnum)) { + sprintf(buf, "%d", targetnum); + ast_get_group(&targetgrp, buf); + if (!ast_have_common_group(&tmp->group, &targetgrp)) { continue; } break; @@ -15926,17 +15939,17 @@ } else if (!strcasecmp(v->name, "jitterbuffers")) { numbufs = atoi(v->value); } else if (!strcasecmp(v->name, "group")) { - confp->chan.group = ast_get_group(v->value); + ast_get_group(&confp->chan.group, v->value); } else if (!strcasecmp(v->name, "callgroup")) { if (!strcasecmp(v->value, "none")) - confp->chan.callgroup = 0; + memset(&confp->chan.callgroup, 0, sizeof(confp->chan.callgroup)); else - confp->chan.callgroup = ast_get_group(v->value); + ast_get_group(&confp->chan.callgroup, v->value); } else if (!strcasecmp(v->name, "pickupgroup")) { if (!strcasecmp(v->value, "none")) - confp->chan.pickupgroup = 0; + memset(&confp->chan.pickupgroup, 0, sizeof(confp->chan.pickupgroup)); else - confp->chan.pickupgroup = ast_get_group(v->value); + ast_get_group(&confp->chan.pickupgroup, v->value); } else if (!strcasecmp(v->name, "setvar")) { char *varname = ast_strdupa(v->value), *varval = NULL; struct ast_variable *tmpvar; Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 241015) +++ channels/chan_sip.c (working copy) @@ -2568,7 +2568,7 @@ static char * _sip_show_peers(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[]); 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_group(int fd, ast_group_t *group, 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; @@ -5472,8 +5472,8 @@ ast_string_field_set(dialog, parkinglot, peer->parkinglot); ast_string_field_set(dialog, engine, peer->engine); ref_proxy(dialog, obproxy_get(dialog, peer)); - dialog->callgroup = peer->callgroup; - dialog->pickupgroup = peer->pickupgroup; + memcpy(&dialog->callgroup, peer->callgroup, sizeof(dialog->callgroup)); + memcpy(&dialog->pickupgroup, peer->pickupgroup, sizeof(dialog->pickupgroup)); dialog->allowtransfer = peer->allowtransfer; dialog->jointnoncodeccapability = dialog->noncodeccapability; dialog->rtptimeout = peer->rtptimeout; @@ -7033,8 +7033,8 @@ tmp->rawreadformat = fmt; tmp->tech_pvt = dialog_ref(i, "sip_new: set chan->tech_pvt to i"); - tmp->callgroup = i->callgroup; - tmp->pickupgroup = i->pickupgroup; + memcpy(&tmp->callgroup, i->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, i->pickupgroup, sizeof(tmp->pickupgroup)); tmp->cid.cid_pres = i->callingpres; if (!ast_strlen_zero(i->parkinglot)) ast_string_field_set(tmp, parkinglot, i->parkinglot); @@ -14753,8 +14753,8 @@ ast_string_field_set(p, language, peer->language); ast_string_field_set(p, accountcode, peer->accountcode); p->amaflags = peer->amaflags; - p->callgroup = peer->callgroup; - p->pickupgroup = peer->pickupgroup; + memcpy(&p->callgroup, peer->callgroup, sizeof(p->callgroup)); + memcpy(&p->pickupgroup, peer->pickupgroup, sizeof(p->pickupgroup)); p->capability = peer->capability; p->prefs = peer->prefs; p->jointcapability = peer->capability; @@ -15536,7 +15536,7 @@ return CLI_SUCCESS; } /*! \brief Print call group and pickup group */ -static void print_group(int fd, ast_group_t group, int crlf) +static void print_group(int fd, ast_group_t *group, int crlf) { char buf[256]; ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) ); @@ -16066,9 +16066,9 @@ if (!ast_strlen_zero(peer->fromdomain)) ast_cli(fd, " FromDomain : %s\n", peer->fromdomain); ast_cli(fd, " Callgroup : "); - print_group(fd, peer->callgroup, 0); + print_group(fd, &peer->callgroup, 0); ast_cli(fd, " Pickupgroup : "); - print_group(fd, peer->pickupgroup, 0); + print_group(fd, &peer->pickupgroup, 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); @@ -16177,9 +16177,9 @@ if (!ast_strlen_zero(peer->fromdomain)) astman_append(s, "SIP-FromDomain: %s\r\n", peer->fromdomain); astman_append(s, "Callgroup: "); - astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); + 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, "%s\r\n", ast_print_group(buffer, sizeof(buffer), &peer->pickupgroup)); 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); @@ -16334,9 +16334,9 @@ ast_cli(a->fd, " CallingPres : %s\n", ast_describe_caller_presentation(user->callingpres)); ast_cli(a->fd, " Call limit : %d\n", user->call_limit); ast_cli(a->fd, " Callgroup : "); - print_group(a->fd, user->callgroup, 0); + print_group(a->fd, &user->callgroup, 0); ast_cli(a->fd, " Pickupgroup : "); - print_group(a->fd, user->pickupgroup, 0); + print_group(a->fd, &user->pickupgroup, 0); ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), user->cid_name, user->cid_num, "")); ast_cli(a->fd, " ACL : %s\n", cli_yesno(user->ha != NULL)); ast_cli(a->fd, " Sess-Timers : %s\n", stmode2str(user->stimer.st_mode_oper)); @@ -17982,9 +17982,9 @@ } else if (!strcasecmp(colname, "accountcode")) { ast_copy_string(buf, peer->accountcode, len); } else if (!strcasecmp(colname, "callgroup")) { - ast_print_group(buf, len, peer->callgroup); + ast_print_group(buf, len, &peer->callgroup); } else if (!strcasecmp(colname, "pickupgroup")) { - ast_print_group(buf, len, peer->pickupgroup); + ast_print_group(buf, len, &peer->pickupgroup); } else if (!strcasecmp(colname, "useragent")) { ast_copy_string(buf, peer->useragent, len); } else if (!strcasecmp(colname, "mailbox")) { @@ -24704,8 +24704,8 @@ ast_string_field_set(peer, fromdomain, ""); ast_string_field_set(peer, fromuser, ""); ast_string_field_set(peer, regexten, ""); - peer->callgroup = 0; - peer->pickupgroup = 0; + memset(&peer->callgroup, 0, sizeof(peer->callgroup)); + memset(&peer->pickupgroup, 0, sizeof(peer->pickupgroup)); peer->maxms = default_qualify; peer->prefs = default_prefs; peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */ @@ -25033,11 +25033,11 @@ } else if (!strcasecmp(v->name, "vmexten")) { ast_string_field_set(peer, vmexten, v->value); } else if (!strcasecmp(v->name, "callgroup")) { - peer->callgroup = ast_get_group(v->value); + ast_get_group(&peer->callgroup, v->value); } else if (!strcasecmp(v->name, "allowtransfer")) { peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; } else if (!strcasecmp(v->name, "pickupgroup")) { - peer->pickupgroup = ast_get_group(v->value); + ast_get_group(&peer->pickupgroup, v->value); } else if (!strcasecmp(v->name, "allow")) { int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE); if (error) { Index: channels/chan_agent.c =================================================================== --- channels/chan_agent.c (revision 241015) +++ channels/chan_agent.c (working copy) @@ -416,7 +416,7 @@ ast_cond_init(&p->app_complete_cond, NULL); p->app_lock_flag = 0; p->app_sleep_cond = 1; - p->group = group; + memcpy(&p->group, group, sizeof(p->group)); p->pending = pending; AST_LIST_INSERT_TAIL(&agents, p, list); } @@ -1080,7 +1080,7 @@ int genhasagent; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - group = 0; + memset(group, 0, sizeof(group)); autologoff = 0; wrapuptime = 0; ackcall = 0; @@ -1126,7 +1126,7 @@ if (!strcasecmp(v->name, "agent")) { add_agent(v->value, 0); } else if (!strcasecmp(v->name, "group")) { - group = ast_get_group(v->value); + ast_get_group(&group, v->value); } else if (!strcasecmp(v->name, "autologoff")) { autologoff = atoi(v->value); if (autologoff < 0) @@ -1247,7 +1247,7 @@ continue; } ast_mutex_lock(&p->lock); - if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { + if (!p->abouttograb && p->pending && ((p->group && ast_have_common_group(&newlyavailable->group, &p->group)) || !strcmp(p->agent, newlyavailable->agent))) { ast_debug(1, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent); /* We found a pending call, time to merge */ chan = agent_new(newlyavailable, AST_STATE_DOWN, p->owner ? p->owner->linkedid : NULL); @@ -1311,7 +1311,7 @@ continue; } ast_mutex_lock(&p->lock); - if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { + if (!p->abouttograb && p->pending && ((p->group && ast_have_common_group(&newlyavailable->group, &p->group)) || !strcmp(p->agent, newlyavailable->agent))) { ast_debug(1, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent); ast_mutex_unlock(&p->lock); break; @@ -1348,18 +1348,23 @@ s = data; if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { - groupmatch = (1 << groupoff); + char tmp[12]; + sprintf(tmp, "%d", groupoff); + ast_get_group(&groupmatch, tmp); } else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { - groupmatch = (1 << groupoff); + char tmp[12]; + sprintf(tmp, "%d", groupoff); + ast_get_group(&groupmatch, tmp); waitforagent = 1; - } else - groupmatch = 0; + } else { + memset(groupmatch, 0, sizeof(groupmatch)); + } /* Check actual logged in agents first */ AST_LIST_LOCK(&agents); AST_LIST_TRAVERSE(&agents, p, list) { ast_mutex_lock(&p->lock); - if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { + if (!p->pending && ((groupmatch && ast_have_common_group(&p->group, &groupmatch)) || !strcmp(data, p->agent))) { if (p->chan) hasagent++; now = ast_tvnow(); @@ -1381,7 +1386,7 @@ if (!p) { AST_LIST_TRAVERSE(&agents, p, list) { ast_mutex_lock(&p->lock); - if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { + if (!p->pending && ((groupmatch && ast_have_common_group(&p->group, &groupmatch)) || !strcmp(data, p->agent))) { if (p->chan) { hasagent++; } @@ -1409,7 +1414,7 @@ if (hasagent) { ast_debug(1, "Creating place holder for '%s'\n", s); p = add_agent(data, 1); - p->group = groupmatch; + memcpy(&p->group, &groupmatch, sizeof(p->group)); chan = agent_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL); if (!chan) ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n"); @@ -1422,16 +1427,6 @@ return chan; } -static force_inline int powerof(unsigned int d) -{ - int x = ffs(d); - - if (x) - return x - 1; - - return 0; -} - /*! * Lists agents and their status to the Manager API. * It is registered on load_module() and it gets called by the manager backend. @@ -1667,8 +1662,9 @@ AST_LIST_TRAVERSE(&agents, p, list) { ast_mutex_lock(&p->lock); if (p->pending) { + char tmp[256]; if (p->group) - ast_cli(a->fd, "-- Pending call to group %d\n", powerof(p->group)); + ast_cli(a->fd, "-- Pending call to group %s\n", ast_print_group(tmp, sizeof(tmp), &p->group)); else ast_cli(a->fd, "-- Pending call to agent %s\n", p->agent); } else { @@ -2175,18 +2171,23 @@ int res = AST_DEVICE_INVALID; s = data; - if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) - groupmatch = (1 << groupoff); - else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { - groupmatch = (1 << groupoff); - } else - groupmatch = 0; + if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { + char tmp[12]; + sprintf(tmp, "%d", groupoff); + ast_get_group(&groupmatch, tmp); + } else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { + char tmp[12]; + sprintf(tmp, "%d", groupoff); + ast_get_group(&groupmatch, tmp); + } else { + memset(&groupmatch, 0, sizeof(groupmatch)); + } /* Check actual logged in agents first */ AST_LIST_LOCK(&agents); AST_LIST_TRAVERSE(&agents, p, list) { ast_mutex_lock(&p->lock); - if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { + if (!p->pending && ((groupmatch && ast_have_common_group(&p->group, &groupmatch)) || !strcmp(data, p->agent))) { if (p->owner) { if (res != AST_DEVICE_INUSE) res = AST_DEVICE_BUSY; Index: channels/chan_misdn.c =================================================================== --- channels/chan_misdn.c (revision 241015) +++ channels/chan_misdn.c (working copy) @@ -5868,10 +5868,11 @@ misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg)); misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg)); - 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->pickupgroup = pg; - ast->callgroup = cg; + chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), &cg), ast_print_group(buf2, sizeof(buf2), &pg)); + memcpy(&ast->pickupgroup, &pg, sizeof(ast->pickupgroup)); + memcpy(&ast->callgroup, &pg, sizeof(ast->callgroup)); + if (ch->originator == ORG_AST) { char callerid[BUFFERSIZE + 1]; Index: channels/chan_skinny.c =================================================================== --- channels/chan_skinny.c (revision 241015) +++ channels/chan_skinny.c (working copy) @@ -3448,8 +3448,8 @@ ast_cli(fd, "Line Label: %s\n", l->label); ast_cli(fd, "Extension: %s\n", S_OR(l->exten, "")); ast_cli(fd, "Context: %s\n", l->context); - ast_cli(fd, "CallGroup: %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup)); - ast_cli(fd, "PickupGroup: %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup)); + ast_cli(fd, "CallGroup: %s\n", ast_print_group(group_buf, sizeof(group_buf), &l->callgroup)); + ast_cli(fd, "PickupGroup: %s\n", ast_print_group(group_buf, sizeof(group_buf), &l->pickupgroup)); ast_cli(fd, "Language: %s\n", S_OR(l->language, "")); ast_cli(fd, "Accountcode: %s\n", S_OR(l->accountcode, "")); ast_cli(fd, "AmaFlag: %s\n", ast_cdr_flags2str(l->amaflags)); @@ -3495,8 +3495,8 @@ astman_append(s, "LineLabel: %s\r\n", l->label); astman_append(s, "Extension: %s\r\n", S_OR(l->exten, "")); astman_append(s, "Context: %s\r\n", l->context); - astman_append(s, "CallGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup)); - astman_append(s, "PickupGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup)); + astman_append(s, "CallGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), &l->callgroup)); + astman_append(s, "PickupGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), &l->pickupgroup)); astman_append(s, "Language: %s\r\n", S_OR(l->language, "")); astman_append(s, "Accountcode: %s\r\n", S_OR(l->accountcode, "")); astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(l->amaflags)); @@ -4430,8 +4430,8 @@ tmp->amaflags = l->amaflags; ast_module_ref(ast_module_info->self); - tmp->callgroup = l->callgroup; - tmp->pickupgroup = l->pickupgroup; + memcpy(&tmp->callgroup, l->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, l->pickupgroup, sizeof(tmp->pickupgroup)); /* XXX Need to figure out how to handle CFwdNoAnswer */ if (l->cfwdtype & SKINNY_CFWD_ALL) { @@ -6820,12 +6820,12 @@ } } else if (!strcasecmp(v->name, "callgroup")) { if (type & (TYPE_DEF_LINE | TYPE_LINE)) { - CLINE_OPTS->callgroup = ast_get_group(v->value); + ast_get_group(&CLINE_OPTS->callgroup, v->value); continue; } } else if (!strcasecmp(v->name, "pickupgroup")) { if (type & (TYPE_DEF_LINE | TYPE_LINE)) { - CLINE_OPTS->pickupgroup = ast_get_group(v->value); + ast_get_group(&CLINE_OPTS->pickupgroup, v->value); continue; } } else if (!strcasecmp(v->name, "immediate")) { Index: channels/chan_mgcp.c =================================================================== --- channels/chan_mgcp.c (revision 241015) +++ channels/chan_mgcp.c (working copy) @@ -160,8 +160,8 @@ static int pktcgatealloc = 0; static int hangupongateremove = 0; -static ast_group_t cur_callergroup = 0; -static ast_group_t cur_pickupgroup = 0; +static ast_group_t cur_callergroup; +static ast_group_t cur_pickupgroup; static struct { unsigned int tos; @@ -1512,8 +1512,8 @@ tmp->amaflags = i->amaflags; sub->owner = tmp; ast_module_ref(ast_module_info->self); - tmp->callgroup = i->callgroup; - tmp->pickupgroup = i->pickupgroup; + memcpy(&tmp->callgroup, i->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, i->pickupgroup, sizeof(tmp->pickupgroup)); ast_string_field_set(tmp, call_forward, i->call_forward); ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); @@ -4028,9 +4028,9 @@ } else if (!strcasecmp(v->name, "parkinglot")) { ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); } else if (!strcasecmp(v->name, "callgroup")) { - cur_callergroup = ast_get_group(v->value); + ast_get_group(&cur_callergroup, v->value); } else if (!strcasecmp(v->name, "pickupgroup")) { - cur_pickupgroup = ast_get_group(v->value); + ast_get_group(&cur_pickupgroup, v->value); } else if (!strcasecmp(v->name, "immediate")) { immediate = ast_true(v->value); } else if (!strcasecmp(v->name, "cancallforward")) { @@ -4119,8 +4119,8 @@ e->adsi = adsi; e->type = TYPE_LINE; e->immediate = immediate; - e->callgroup=cur_callergroup; - e->pickupgroup=cur_pickupgroup; + memcpy(&e->callgroup, &cur_callergroup, sizeof(e->callgroup)); + memcpy(&e->pickupgroup, &cur_pickupgroup, sizeof(e->pickupgroup)); e->callreturn = callreturn; e->cancallforward = cancallforward; e->singlepath = singlepath; @@ -4220,8 +4220,8 @@ e->adsi = adsi; e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE; e->immediate = immediate; - e->callgroup=cur_callergroup; - e->pickupgroup=cur_pickupgroup; + memcpy(&e->callgroup, &cur_callergroup, sizeof(e->callgroup)); + memcpy(&e->pickupgroup, &cur_pickupgroup, sizeof(e->pickupgroup)); e->callreturn = callreturn; e->cancallforward = cancallforward; e->directmedia = directmedia; Index: channels/chan_unistim.c =================================================================== --- channels/chan_unistim.c (revision 241015) +++ channels/chan_unistim.c (working copy) @@ -399,9 +399,9 @@ /*! MusicOnHold class */ char musicclass[MAX_MUSICCLASS]; /*! Call group */ - unsigned int callgroup; + ast_group_t callgroup; /*! Pickup group */ - unsigned int pickupgroup; + ast_group_t pickupgroup; /*! Account code (for billing) */ char accountcode[80]; /*! AMA flags (for billing) */ @@ -4485,8 +4485,8 @@ usecnt++; ast_mutex_unlock(&usecnt_lock); ast_update_use_count(); - tmp->callgroup = l->callgroup; - tmp->pickupgroup = l->pickupgroup; + memcpy(&tmp->callgroup, l->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, l->pickupgroup, sizeof(tmp->pickupgroup)); ast_string_field_set(tmp, call_forward, l->parent->call_forward); if (!ast_strlen_zero(l->cid_num)) { char *name, *loc, *instr; @@ -5120,9 +5120,9 @@ } else if (!strcasecmp(v->name, "musiconhold")) ast_copy_string(l->musicclass, v->value, sizeof(l->musicclass)); else if (!strcasecmp(v->name, "callgroup")) - l->callgroup = ast_get_group(v->value); + ast_get_group(&l->callgroup, v->value); else if (!strcasecmp(v->name, "pickupgroup")) - l->pickupgroup = ast_get_group(v->value); + ast_get_group(&l->pickupgroup, v->value); else if (!strcasecmp(v->name, "mailbox")) ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox)); else if (!strcasecmp(v->name, "parkinglot")) Index: channels/chan_gtalk.c =================================================================== --- channels/chan_gtalk.c (revision 241015) +++ channels/chan_gtalk.c (working copy) @@ -1041,8 +1041,8 @@ tmp->rawreadformat = fmt; tmp->tech_pvt = i; - tmp->callgroup = client->callgroup; - tmp->pickupgroup = client->pickupgroup; + memcpy(&tmp->callgroup, client->callgroup, sizeof(tmp->callgroup)); + memcpy(&tmp->pickupgroup, client->pickupgroup, sizeof(tmp->pickupgroup)); tmp->cid.cid_pres = client->callingpres; if (!ast_strlen_zero(client->accountcode)) ast_string_field_set(tmp, accountcode, client->accountcode); Index: apps/app_dumpchan.c =================================================================== --- apps/app_dumpchan.c (revision 241015) +++ apps/app_dumpchan.c (working copy) @@ -138,8 +138,8 @@ c->context, c->exten, c->priority, - ast_print_group(cgrp, sizeof(cgrp), c->callgroup), - ast_print_group(pgrp, sizeof(pgrp), c->pickupgroup), + ast_print_group(cgrp, sizeof(cgrp), &c->callgroup), + ast_print_group(pgrp, sizeof(pgrp), &c->pickupgroup), ( c->appl ? c->appl : "(N/A)" ), ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"), (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)")); Index: doc/asterisk-mib.txt =================================================================== --- doc/asterisk-mib.txt (revision 241015) +++ doc/asterisk-mib.txt (working copy) @@ -269,8 +269,8 @@ astChanAccountCode DisplayString, astChanForwardTo DisplayString, astChanUniqueId DisplayString, - astChanCallGroup Unsigned32, - astChanPickupGroup Unsigned32, + astChanCallGroup DisplayString, + astChanPickupGroup DisplayString, astChanState INTEGER, astChanMuted TruthValue, astChanRings Integer32, Index: funcs/func_channel.c =================================================================== --- funcs/func_channel.c (revision 241015) +++ funcs/func_channel.c (working copy) @@ -341,7 +341,7 @@ locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len); else if (!strcasecmp(data, "callgroup")) { char groupbuf[256]; - locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len); + locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), &chan->callgroup), len); } else if (!strcasecmp(data, "amaflags")) { char amabuf[256]; snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags); @@ -416,7 +416,7 @@ new_zone = ast_tone_zone_unref(new_zone); } } else if (!strcasecmp(data, "callgroup")) - chan->callgroup = ast_get_group(value); + ast_get_group(&chan->callgroup, value); else if (!strcasecmp(data, "txgain")) { sscanf(value, "%4hhd", &gainset); ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0); Index: include/asterisk/channel.h =================================================================== --- include/asterisk/channel.h (revision 241015) +++ include/asterisk/channel.h (working copy) @@ -168,7 +168,13 @@ AST_BRIDGE_RETRY = -3, }; -typedef unsigned long long ast_group_t; +/* + * By default allow 32*32=1024 call/pickup groups. + */ +#ifndef AST_GROUP_MAX +#define AST_GROUP_MAX (32 * sizeof(int)) +#endif +typedef unsigned ast_group_t[AST_GROUP_MAX/sizeof(int)]; /*! \todo Add an explanation of an Asterisk generator */ @@ -2164,11 +2170,14 @@ ast_set_flag(c, AST_FLAG_BLOCKING); \ } } while (0) -ast_group_t ast_get_group(const char *s); +void ast_get_group(ast_group_t *group, const char *s); /*! \brief print call- and pickup groups into buffer */ -char *ast_print_group(char *buf, int buflen, ast_group_t group); +char *ast_print_group(char *buf, int buflen, ast_group_t *group); +/*! \brief return true if two ast_group_t vars have bits in common */ +extern int ast_have_common_group(ast_group_t *group, ast_group_t *other); + /*! * \brief Convert enum channelreloadreason to text string for manager event * \param reason The reason for reload (manager, cli, start etc) Index: main/channel.c =================================================================== --- main/channel.c (revision 241015) +++ main/channel.c (working copy) @@ -6311,37 +6311,58 @@ return 0; } -ast_group_t ast_get_group(const char *s) +/*! \brief return TRUE if two ast_group_t vars have bits in common */ +int ast_have_common_group(ast_group_t *group, ast_group_t *other) { + unsigned int i; + if (!group || !other) + return 0; + + for (i=0; i 63) || (x < 0)) { - ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 63)\n", x); - } else - group |= ((ast_group_t) 1 << x); + if ((x >= AST_GROUP_MAX * BITS_IN_BYTE) || (x < 0)) { + ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is %d)\n", x, AST_GROUP_MAX * BITS_IN_BYTE); + } else { + int idx = x/(sizeof(int) * BITS_IN_BYTE); + int bitidx = x % (sizeof(int) * BITS_IN_BYTE); + ((int *)group)[idx] |= (1 << bitidx); + } } } - return group; + return; } +#undef BITS_IN_BYTE static int (*ast_moh_start_ptr)(struct ast_channel *, const char *, const char *) = NULL; static void (*ast_moh_stop_ptr)(struct ast_channel *) = NULL; @@ -6409,30 +6430,34 @@ } /*! \brief Print call group and pickup group ---*/ -char *ast_print_group(char *buf, int buflen, ast_group_t group) +char *ast_print_group(char *buf, int buflen, ast_group_t *group) { +#define BITS_IN_BYTE 8 unsigned int i; - int first = 1; - char num[3]; + int first=1; + char num[12]; buf[0] = '\0'; - - if (!group) /* Return empty string if no group */ - return buf; - for (i = 0; i <= 63; i++) { /* Max group is 63 */ - if (group & ((ast_group_t) 1 << i)) { - if (!first) { - strncat(buf, ", ", buflen - strlen(buf) - 1); + if (!group) /* Return empty string if no group */ + return(buf); + + for (i=0; ipickupgroup & c->callgroup) && + ast_have_common_group(&chan->pickupgroup, &c->callgroup) && ((chan->_state == AST_STATE_RINGING) || (chan->_state == AST_STATE_RING)); return i ? CMP_MATCH | CMP_STOP : 0; Index: main/cli.c =================================================================== --- main/cli.c (revision 241015) +++ main/cli.c (working copy) @@ -1322,6 +1322,7 @@ struct ast_str *out = ast_str_thread_get(&ast_str_thread_global_buf, 16); char cdrtime[256]; char nf[256], wf[256], rf[256]; + char cg[256], pg[256]; long elapsed_seconds=0; int hour=0, min=0, sec=0; #ifdef CHANNEL_TRACE @@ -1390,8 +1391,8 @@ " Context: %s\n" " Extension: %s\n" " Priority: %d\n" - " Call Group: %llu\n" - " Pickup Group: %llu\n" + " Call Group: %s\n" + " Pickup Group: %s\n" " Application: %s\n" " Data: %s\n" " Blocking in: %s\n", @@ -1411,8 +1412,8 @@ c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)c->whentohangup.tv_sec, cdrtime, c->_bridge ? c->_bridge->name : "", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "", - c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ), - ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"), + c->context, c->exten, c->priority, ast_print_group(cg, sizeof(cg), &c->callgroup), ast_print_group(pg, sizeof(pg), &c->pickupgroup), + ( c->appl ? c->appl : "(N/A)" ), ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"), (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)")); if (pbx_builtin_serialize_variables(c, &out)) { Index: res/snmp/agent.c =================================================================== --- res/snmp/agent.c (revision 241015) +++ res/snmp/agent.c (working copy) @@ -399,12 +399,14 @@ ret = (u_char *)string_ret; break; case ASTCHANCALLGROUP: - long_ret = chan->callgroup; - ret = (u_char *)&long_ret; + ast_print_group(string_ret, sizeof(string_ret), &chan->callgroup); + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; break; case ASTCHANPICKUPGROUP: - long_ret = chan->pickupgroup; - ret = (u_char *)&long_ret; + ast_print_group(string_ret, sizeof(string_ret), &chan->pickupgroup); + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; break; case ASTCHANSTATE: long_ret = chan->_state & 0xffff; @@ -863,8 +865,8 @@ {ASTCHANACCOUNTCODE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}}, {ASTCHANFORWARDTO, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}}, {ASTCHANUNIQUEID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}}, - {ASTCHANCALLGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}}, - {ASTCHANPICKUPGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}}, + {ASTCHANCALLGROUP, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}}, + {ASTCHANPICKUPGROUP, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}}, {ASTCHANSTATE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}}, {ASTCHANMUTED, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}}, {ASTCHANRINGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},