diff -Nru a/channels/chan_iax2.c b/channels/chan_iax2.c --- a/channels/chan_iax2.c 2005-02-23 00:48:13 -07:00 +++ b/channels/chan_iax2.c 2005-02-23 00:48:13 -07:00 @@ -274,6 +274,8 @@ int pokeexpire; /* When to expire poke */ int lastms; /* How long last response took (in ms), or -1 for no response */ int maxms; /* Max ms we will accept for the host to be up, 0 to not monitor */ + char qualifycontext[80]; /* context to active/deactivate based on qualify status */ + const void *qualifyhandle; /* handle returned from deactivate_context */ struct ast_ha *ha; struct iax2_peer *next; @@ -6414,6 +6416,10 @@ } } peer->lastms = iaxs[fr.callno]->pingtime; + if (!ast_strlen_zero(peer->qualifycontext)) { + ast_activate_context(peer->qualifycontext, peer->qualifyhandle); + peer->qualifyhandle = NULL; + } if (peer->pokeexpire > -1) ast_sched_del(sched, peer->pokeexpire); send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno); @@ -7050,6 +7056,8 @@ ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); } + if (!ast_strlen_zero(peer->qualifycontext) && !peer->qualifyhandle) + peer->qualifyhandle = ast_deactivate_context(peer->qualifycontext); if (peer->callno > 0) iax2_destroy(peer->callno); peer->callno = 0; @@ -7394,6 +7402,8 @@ } else if (!strcasecmp(v->name, "context")) { if (ast_strlen_zero(peer->context)) strncpy(peer->context, v->value, sizeof(peer->context) - 1); + } else if (!strcasecmp(v->name, "qualifycontext")) { + strncpy(peer->qualifycontext, v->value, sizeof(peer->qualifycontext) - 1); } else if (!strcasecmp(v->name, "regexten")) { strncpy(peer->regexten, v->value, sizeof(peer->regexten) - 1); } else if (!strcasecmp(v->name, "peercontext")) { @@ -7442,6 +7452,8 @@ peer->addr.sin_family = AF_INET; if (!found && ast_test_flag(peer, IAX_DYNAMIC) && !temponly) reg_source_db(peer); + if (!ast_strlen_zero(peer->qualifycontext) && !peer->qualifyhandle && peer->lastms < 1) + peer->qualifyhandle = ast_deactivate_context(peer->qualifycontext); } if (oldha) ast_free_ha(oldha); diff -Nru a/channels/chan_sip.c b/channels/chan_sip.c --- a/channels/chan_sip.c 2005-02-23 00:48:13 -07:00 +++ b/channels/chan_sip.c 2005-02-23 00:48:13 -07:00 @@ -504,6 +504,8 @@ int lastms; /* How long last response took (in ms), or -1 for no response */ int maxms; /* Max ms we will accept for the host to be up, 0 to not monitor */ struct timeval ps; /* Ping send time */ + char qualifycontext[80]; /* context to active/deactivate based on qualify status */ + const void *qualifyhandle; /* handle returned when context deactivated */ struct sockaddr_in defaddr; /* Default IP address, used until registration */ struct ast_ha *ha; /* Access control list */ @@ -7362,6 +7364,11 @@ } } + if (!ast_strlen_zero(peer->qualifycontext)) { + ast_activate_context(peer->qualifycontext, peer->qualifyhandle); + peer->qualifyhandle = NULL; + } + if (peer->pokeexpire > -1) ast_sched_del(sched, peer->pokeexpire); if (!strcasecmp(msg, "INVITE")) @@ -8717,6 +8724,8 @@ peer->call = NULL; peer->lastms = -1; ast_device_state_changed("SIP/%s", peer->name); + if (!ast_strlen_zero(peer->qualifycontext) && !peer->qualifyhandle) + peer->qualifyhandle = ast_deactivate_context(peer->qualifycontext); /* Try again quickly */ peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer); return 0; @@ -9220,10 +9229,12 @@ strncpy(peer->secret, v->value, sizeof(peer->secret)-1); else if (!strcasecmp(v->name, "md5secret")) strncpy(peer->md5secret, v->value, sizeof(peer->md5secret)-1); - else if (!strcasecmp(v->name, "callerid")) { + else if (!strcasecmp(v->name, "callerid")) ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num)); - } else if (!strcasecmp(v->name, "context")) + else if (!strcasecmp(v->name, "context")) strncpy(peer->context, v->value, sizeof(peer->context)-1); + else if (!strcasecmp(v->name, "qualifycontext")) + strncpy(peer->qualifycontext, v->value, sizeof(peer->qualifycontext)-1); else if (!strcasecmp(v->name, "fromdomain")) strncpy(peer->fromdomain, v->value, sizeof(peer->fromdomain)-1); else if (!strcasecmp(v->name, "usereqphone")) @@ -9374,6 +9385,8 @@ ast_copy_flags(peer, &peerflags, mask.flags); if (!found && ast_test_flag(peer, SIP_DYNAMIC)) reg_source_db(peer); + if (!ast_strlen_zero(peer->qualifycontext) && !peer->qualifyhandle && peer->lastms < 1) + peer->qualifyhandle = ast_deactivate_context(peer->qualifycontext); ASTOBJ_UNMARK(peer); } ast_free_ha(oldha); diff -Nru a/channels/chan_zap.c b/channels/chan_zap.c --- a/channels/chan_zap.c 2005-02-23 00:48:13 -07:00 +++ b/channels/chan_zap.c 2005-02-23 00:48:13 -07:00 @@ -254,6 +254,7 @@ static char unknownprefix[20] = ""; static long resetinterval = 3600; /* How often (in seconds) to reset unused channels. Default 1 hour. */ static struct ast_channel inuse = { "GR-303InUse" }; +static char activecontext[80]; #ifdef PRI_GETSET_TIMERS static int pritimers[PRI_MAX_TIMERS]; #endif @@ -364,6 +365,8 @@ char localprefix[20]; /* area access code + area code ('0'+area code for european dialplans) */ char privateprefix[20]; /* for private dialplans */ char unknownprefix[20]; /* for unknown dialplans */ + char activecontext[80]; /* context to activate/deactivate as span goes up/down */ + const void *activehandle; /* handle returned from deactivate_context */ int dchannels[NUM_DCHANS]; /* What channel are the dchannels on */ int trunkgroup; /* What our trunkgroup is */ int mastertrunkgroup; /* What trunk group is our master */ @@ -6502,6 +6505,11 @@ destroy_zt_pvt(&tmp); return NULL; } + if (!ast_strlen_zero(pris[span].activecontext) && strcmp(pris[span].activecontext, activecontext)) { + ast_log(LOG_ERROR, "Span %d already has activecontext '%s'.\n", span + 1, activecontext); + destroy_zt_pvt(&tmp); + return NULL; + } if (pris[span].numchans >= MAX_CHANNELS) { ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, pris[span].trunkgroup); @@ -6524,6 +6532,7 @@ strncpy(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix)-1); strncpy(pris[span].privateprefix, privateprefix, sizeof(pris[span].privateprefix)-1); strncpy(pris[span].unknownprefix, unknownprefix, sizeof(pris[span].unknownprefix)-1); + strncpy(pris[span].activecontext, activecontext, sizeof(pris[span].activecontext) - 1); pris[span].resetinterval = resetinterval; tmp->pri = &pris[span]; @@ -7627,6 +7636,10 @@ if (pri->pvts[i]) { pri->pvts[i]->inalarm = 0; } + if (!ast_strlen_zero(pri->activecontext)) { + ast_activate_context(pri->activecontext, pri->activehandle); + pri->activehandle = NULL; + } break; case PRI_EVENT_DCHAN_DOWN: if (option_verbose > 1) @@ -7654,6 +7667,8 @@ p->inalarm = 1; } } + if (!ast_strlen_zero(pri->activecontext) && !pri->activehandle) + pri->activehandle = ast_deactivate_context(pri->activecontext); } break; case PRI_EVENT_RESTART: @@ -9882,6 +9897,8 @@ strncpy(idledial, v->value, sizeof(idledial) - 1); } else if (!strcasecmp(v->name, "overlapdial")) { overlapdial = ast_true(v->value); + } else if (!strcasecmp(v->name, "activecontext")) { + strncpy(activecontext, v->value, sizeof(activecontext) - 1); } else if (!strcasecmp(v->name, "pritimer")) { #ifdef PRI_GETSET_TIMERS char *timerc; @@ -10038,6 +10055,8 @@ if (!reload) { for (x=0;xname, context)) { + if ((bypass || !strcmp(tmp->name, context)) && !tmp->inactive) { if (*status < STATUS_NO_EXTENSION) *status = STATUS_NO_EXTENSION; eroot = tmp->root; @@ -3190,12 +3199,34 @@ return tmp; } +static void preserve_context_inactive(struct ast_context *old_contexts, struct ast_context *new_contexts) +{ + struct ast_context *old; + struct ast_context *new; + + for (old = old_contexts; old; old = old->next) { + if (!old->inactive) + continue; + + for (new = new_contexts; new; new = new->next) { + if (!strcasecmp(old->name, new->name)) { + new->inactive = old->inactive; + break; + } + } + } +} + void __ast_context_destroy(struct ast_context *con, const char *registrar); void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar) { struct ast_context *tmp, *lasttmp = NULL; + tmp = *extcontexts; ast_mutex_lock(&conlock); + + preserve_context_inactive(contexts, *extcontexts); + if (registrar) { __ast_context_destroy(NULL,registrar); while (tmp) { @@ -5403,6 +5434,72 @@ int ast_unlock_context(struct ast_context *con) { return ast_mutex_unlock(&con->lock); +} + +/* + * Activate/deactivate context + */ +const void *ast_deactivate_context(const char *context) +{ + struct ast_context *con = NULL; + struct inactive_handle *h = NULL; + + if (!context) + return NULL; + + ast_lock_contexts(); + + while ((con = ast_walk_contexts(con))) { + if (!strcasecmp(con->name, context)) + break; + } + + if (con) + h = malloc(sizeof(*h)); + + if (h) { + h->next = con->inactive; + con->inactive = h; + ast_log(LOG_DEBUG, "Deactivated context '%s' for %p\n", context, h); + } + + ast_unlock_contexts(); + + return h; +} + +void ast_activate_context(const char *context, const void *handle) +{ + struct ast_context *con = NULL; + struct inactive_handle *h, *last = NULL; + + if (!context || !handle) + return; + + ast_lock_contexts(); + + while ((con = ast_walk_contexts(con))) { + if (!strcasecmp(con->name, context)) + break; + } + + if (con) { + for (h = con->inactive; h; h = h->next) { + if (h == handle) + break; + last = h; + } + if (h) { + if (last) + last->next = h->next; + else + con->inactive = h->next; + free(h); + ast_log(LOG_DEBUG, "Activated context '%s' for %p\n", context, h); + } + } + + ast_unlock_contexts(); } /*