--- res_features.c 2007-09-28 03:17:16.000000000 +0200 +++ res_features.c 2007-09-28 03:17:31.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,6 +319,7 @@ 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; @@ -319,15 +328,48 @@ if (!(pu = ast_calloc(1, sizeof(*pu)))) return -1; - /* Lock parking lot */ + /* Lock parking lot */ ast_mutex_lock(&parking_lock); + pa = parkingoffset; + + while (pa) { + if (strstr(pa->context, chan->context)) { + break; + } + pal = pa; + pa = pa->next; + } + if (pa) { + if (!strstr(pa->context, chan->context)) { + if (!(par = ast_calloc(1, sizeof(*par)))) + return -1; + ast_copy_string(par->context, chan->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, chan->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); + /* Check for channel variable PARKINGEXTEN */ parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"); 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 +378,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 +397,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 +426,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 +436,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,9 +458,9 @@ 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); /* Tell the peer channel the number of the parking space */ @@ -426,7 +468,7 @@ ast_say_digits(peer, pu->parkingnum, "", peer->language); 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 */ @@ -670,7 +712,7 @@ finishup(transferee); return res; } - if (!strcmp(xferto, ast_parking_ext())) { + if (!strcasecmp(xferto, ast_parking_ext())) { res = finishup(transferee); if (res) res = -1; @@ -1625,6 +1667,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 */ @@ -1633,8 +1676,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 */ @@ -1687,7 +1734,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); @@ -1727,7 +1774,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); @@ -1772,6 +1819,8 @@ } } } /* end while */ + pa = pa->next; + } /* end while pa */ ast_mutex_unlock(&parking_lock); rfds = nrfds; efds = nefds; @@ -1820,8 +1869,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; @@ -1835,13 +1885,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; @@ -1987,24 +2051,38 @@ static int handle_parkedcalls(int fd, int argc, char *argv[]) { + struct parking_offset *pa, *pacur; struct parkeduser *cur; int numparked = 0; - ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel" - , "Context", "Extension", "Pri", "Timeout"); - ast_mutex_lock(&parking_lock); + + pa = parkingoffset; + if (!pa) + ast_cli(fd, "%4s\n", "No parked calls"); + else { - for (cur = 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_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++; + } + pa = pa->next; + } + ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : ""); } ast_mutex_unlock(&parking_lock); - ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : ""); - return RESULT_SUCCESS; } @@ -2042,7 +2120,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"