--- res_features.c 2007-10-03 02:47:51.000000000 +0200 +++ res_features.c.new 2007-10-03 02:41:40.000000000 +0200 @@ -92,7 +92,6 @@ static char xfersound[256]; /*!< Call transfer sound */ static char xferfailsound[256]; /*!< Call transfer failure sound */ -static int parking_offset; static int parkfindnext; static int adsipark; @@ -146,7 +145,16 @@ struct parkeduser *next; }; -static struct parkeduser *parkinglot; +/* static struct parkeduser *parkinglot; */ + +struct parking_offset { + int offset; + struct parkeduser *parkinglot; + char context[AST_MAX_CONTEXT]; + struct parking_offset *next; +}; + +static struct parking_offset *parkingoffset; AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */ @@ -311,23 +319,58 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout) { struct parkeduser *pu, *cur; + struct parking_offset *pa, *par, *pal=NULL; int i, x = -1, parking_range; struct ast_context *con; const char *parkingexten; + /* Check for channel variable PARKINGEXTEN */ + parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"); + /* Allocate memory for parking data */ if (!(pu = ast_calloc(1, sizeof(*pu)))) return -1; /* Lock parking lot */ ast_mutex_lock(&parking_lock); - /* Check for channel variable PARKINGEXTEN */ - parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"); + pa = parkingoffset; + + while (pa) { + if (strstr(pa->context, peer->context)) { + break; + } + pal = pa; + pa = pa->next; + } + if (pa) { + if (!strstr(pa->context, peer->context)) { + if (!(par = ast_calloc(1, sizeof(*par)))) + return -1; + ast_copy_string(par->context, peer->context, sizeof(par->context)); + par->offset = 0; + pa->next = par; + pa = par; + } + } else { + if (!(pa = ast_calloc(1, sizeof(*pa)))) + return -1; + ast_copy_string(pa->context, peer->context, sizeof(pa->context)); + pa->offset = 0; + pa->next = NULL; + if (pal) + pal->next = pa; + else + parkingoffset = pa; + } + + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Using context %s for park call.\n", pa->context); + if (!ast_strlen_zero(parkingexten)) { - if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) { + if (ast_exists_extension(NULL, pa->context , parkingexten, 1, NULL)) { ast_mutex_unlock(&parking_lock); free(pu); - ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con); + ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, peer->context); return -1; /* We failed to park this call, plain and simple so we need to error out */ } ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten)); @@ -336,9 +379,9 @@ /* Select parking space within range */ parking_range = parking_stop - parking_start+1; for (i = 0; i < parking_range; i++) { - x = (i + parking_offset) % parking_range + parking_start; - cur = parkinglot; - while(cur) { + x = (i + pa->offset) % parking_range + parking_start; + cur = pa->parkinglot; + while (cur) { if (cur->parkingnum == x) break; cur = cur->next; @@ -355,7 +398,7 @@ } /* Set pointer for next parking */ if (parkfindnext) - parking_offset = x - parking_start + 1; + pa->offset = x - parking_start + 1; } chan->appl = "Parked Call"; @@ -384,8 +427,8 @@ ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context)); ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten)); pu->priority = chan->macropriority ? chan->macropriority : chan->priority; - pu->next = parkinglot; - parkinglot = pu; + pu->next = pa->parkinglot; + pa->parkinglot = pu; /* If parking a channel directly, don't quiet yet get parking running on it */ if (peer == chan) @@ -394,7 +437,7 @@ /* Wake up the (presumably select()ing) thread */ pthread_kill(parking_thread, SIGURG); if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000)); + ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pa->context, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000)); if (pu->parkingnum != -1) snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x); @@ -416,11 +459,11 @@ ast_adsi_unload_session(peer); } - con = ast_context_find(parking_con); + con = ast_context_find(pa->context); if (!con) - con = ast_context_create(NULL, parking_con, registrar); + con = ast_context_create(NULL, pa->context, registrar); if (!con) /* Still no context? Bad */ - ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con); + ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", pa->context); /* Tell the peer channel the number of the parking space */ if (peer && pu->parkingnum != -1) { /* Only say number if it's a number */ /* Make sure we don't start saying digits to the channel being parked */ @@ -430,7 +473,7 @@ } if (con) { if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar)) - notify_metermaids(pu->parkingexten, parking_con); + notify_metermaids(pu->parkingexten, peer->context); } if (pu->notquiteyet) { /* Wake up parking thread if we're really done */ @@ -1636,6 +1679,7 @@ FD_ZERO(&efds); for (;;) { + struct parking_offset *pa; struct parkeduser *pu, *pl, *pt = NULL; int ms = -1; /* select timeout, uninitialized */ int max = -1; /* max fd, none there yet */ @@ -1644,8 +1688,12 @@ FD_ZERO(&nefds); ast_mutex_lock(&parking_lock); + + pa = parkingoffset; + while (pa) { + pl = NULL; - pu = parkinglot; + pu = pa->parkinglot; /* navigate the list with prev-cur pointers to support removals */ while (pu) { struct ast_channel *chan = pu->chan; /* shorthand */ @@ -1698,7 +1746,7 @@ if (pl) pl->next = pu->next; else - parkinglot = pu->next; + pa->parkinglot = pu->next; pt = pu; pu = pu->next; con = ast_context_find(parking_con); @@ -1738,7 +1786,7 @@ if (pl) pl->next = pu->next; else - parkinglot = pu->next; + pa->parkinglot = pu->next; pt = pu; pu = pu->next; con = ast_context_find(parking_con); @@ -1783,6 +1831,8 @@ } } } /* end while */ + pa = pa->next; + } /* end while pa */ ast_mutex_unlock(&parking_lock); rfds = nrfds; efds = nefds; @@ -1831,8 +1881,9 @@ int res = 0; struct ast_module_user *u; struct ast_channel *peer=NULL; - struct parkeduser *pu, *pl=NULL; + struct parkeduser *pu=NULL, *pl=NULL; struct ast_context *con; + struct parking_offset *pa=NULL; int park; struct ast_bridge_config config; @@ -1846,13 +1897,27 @@ park = atoi((char *)data); ast_mutex_lock(&parking_lock); - pu = parkinglot; + + if (parkingoffset) { + pa = parkingoffset; + while (pa) { + if (strstr(pa->context, chan->context)) + break; + pa = pa->next; + } + if (pa) + pu = pa->parkinglot; + else + if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "No parked calls for context %s", chan->context); + } + while(pu) { if (pu->parkingnum == park) { if (pl) pl->next = pu->next; else - parkinglot = pu->next; + pa->parkinglot = pu->next; break; } pl = pu; @@ -1998,6 +2063,7 @@ static int handle_parkedcalls(int fd, int argc, char *argv[]) { + struct parking_offset *pa, *pacur; struct parkeduser *cur; int numparked = 0; @@ -2006,16 +2072,32 @@ ast_mutex_lock(&parking_lock); - for (cur = parkinglot; cur; cur = cur->next) { + pa = parkingoffset; + if (!pa) + ast_cli(fd, "%4s\n", "No parked calls"); + else { + + ast_cli(fd, "%-10s", "Contexts: "); + for (pacur = parkingoffset; pacur; pacur = pacur->next) { + ast_cli(fd, "%s, ", pacur->context); + } + ast_cli(fd, "\n"); + + ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel" + , "Context", "Extension", "Pri", "Timeout"); + while (pa) { + for (cur = pa->parkinglot; cur; cur = cur->next) { ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n" ,cur->parkingexten, cur->chan->name, cur->context, cur->exten ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL)); numparked++; } - ast_mutex_unlock(&parking_lock); + pa = pa->next; + } ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : ""); - + } + ast_mutex_unlock(&parking_lock); return RESULT_SUCCESS; } @@ -2053,7 +2135,7 @@ ast_mutex_lock(&parking_lock); - for (cur = parkinglot; cur; cur = cur->next) { + for (cur = parkingoffset->parkinglot; cur; cur = cur->next) { astman_append(s, "Event: ParkedCall\r\n" "Exten: %d\r\n" "Channel: %s\r\n"