diff --git a/CHANGES b/CHANGES index 1c7e5c982f728022c79a5aca8f7aca6a170195db..71e325bd71817c5d48f4cfe34cd24113c439e898 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,8 @@ --- Functionality changes from Asterisk 1.6.2 to Asterisk 1.6.3 ------------- ------------------------------------------------------------------------------ + + SIP Changes ----------- * Added preferred_codec_only option in sip.conf. This feature limits the joint @@ -142,6 +144,7 @@ DAHDI Changes and a 'full' buffer policy for a fax transmission, add: faxbuffers=>6,full The faxbuffers configuration will be in affect until the call is torn down. + * Added service message support for 4ess/5ess switches. Dialplan Functions ------------------ diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index f6d3fb9ad8b06fc3ab3fa7f6348d871713fd8d36..adc7e510a03478ae197e345dfc6d569df9510011 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -292,6 +292,28 @@ static const char config[] = "chan_dahdi.conf"; #define CALLPROGRESS_FAX_INCOMING 4 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) +#ifdef HAVE_PRI_SERVICE_MESSAGES +/*! \brief Persistent Service State */ +#define SRVST_DBKEY "service-state" +/*! \brief The out-of-service SERVICE state */ +#define SRVST_TYPE_OOS "O" +/*! \brief SRVST_INITIALIZED is used to indicate a channel being out-of-service + * The SRVST_INITIALIZED is mostly used maintain backwards compatibility but also may + * mean that the channel has not yet received a RESTART message. If a channel is + * out-of-service with this reason a RESTART message will result in the channel + * being put into service. */ +#define SRVST_INITIALIZED 0 +/*! \brief SRVST_NEAREND is used to indicate that the near end was put out-of-service */ +#define SRVST_NEAREND (1 << 0) +/*! \brief SRVST_FAREND is used to indicate that the far end was taken out-of-service */ +#define SRVST_FAREND (1 << 1) +/*! \brief SRVST_BOTH is used to indicate that both sides of the channel are out-of-service */ +#define SRVST_BOTH (SRVST_NEAREND | SRVST_FAREND) + +/*! \brief The AstDB family */ +static const char dahdi_db[] = "dahdi/registry"; +#endif + static char defaultcic[64] = ""; static char defaultozz[64] = ""; @@ -543,6 +565,9 @@ struct dahdi_pri { int resetting; /*! \brief Current position during a reset (-1 if not started) */ int resetpos; +#ifdef HAVE_PRI_SERVICE_MESSAGES + unsigned int enable_service_message_support:1; /*!< enable SERVICE message support */ +#endif #ifdef HAVE_PRI_INBANDDISCONNECT unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */ #endif @@ -3934,6 +3959,21 @@ static void destroy_all_channels(void) pl = p; p = p->next; x = pl->channel; +#ifdef HAVE_PRI_SERVICE_MESSAGES + { + char db_chan_name[20], db_answer[5], state; + int why = -1; + + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pl->span, x); + if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + sscanf(db_answer, "%c:%d", &state, &why); + } + if (!why) { + /* SRVST persistence is not required */ + ast_db_del(db_chan_name, SRVST_DBKEY); + } + } +#endif /* Free associated memory */ if (pl) destroy_dahdi_pvt(&pl); @@ -10134,7 +10174,6 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, } } } - offset = p.chanpos; if (!matchesdchan) { if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); @@ -10190,6 +10229,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, pris[span].overlapdial = conf->pri.overlapdial; pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping; pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval; +#ifdef HAVE_PRI_SERVICE_MESSAGES + pris[span].enable_service_message_support = conf->pri.enable_service_message_support; +#endif #ifdef HAVE_PRI_INBANDDISCONNECT pris[span].inbanddisconnect = conf->pri.inbanddisconnect; #endif @@ -10204,7 +10246,11 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, pris[span].resetinterval = conf->pri.resetinterval; tmp->pri = &pris[span]; - tmp->prioffset = offset; + if (si.spanno != span + 1) { /* in another trunkgroup */ + tmp->prioffset = pris[span].numchans; + } else { + tmp->prioffset = p.chanpos; + } tmp->call = NULL; } else { ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); @@ -10483,10 +10529,23 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp->sendcalleridafter = conf->chan.sendcalleridafter; if (!here) { tmp->locallyblocked = tmp->remotelyblocked = 0; - if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) + if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) { tmp->inservice = 0; - else /* We default to in service on protocols that don't have a reset */ +#ifdef HAVE_PRI_SERVICE_MESSAGES + if (chan_sig == SIG_PRI) { + char db_chan_name[20], db_answer[5]; + + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel); + if (ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_INITIALIZED); + ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); + } + } +#endif + } else { + /* We default to in service on protocols that don't have a reset */ tmp->inservice = 1; + } } } if (tmp && !here) { @@ -10536,7 +10595,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, return tmp; } -static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched) +static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched) { int res; struct dahdi_params par; @@ -10554,9 +10613,9 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g *channelmatched = 1; } /* We're at least busy at this point */ - if (busy) { + if (reason) { if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) - *busy = 1; + *reason = AST_CAUSE_BUSY; } /* If do not disturb, definitely not */ if (p->dnd) @@ -10573,10 +10632,25 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g #ifdef HAVE_PRI /* Trust PRI */ if (p->pri) { - if (p->resetting || p->call) +#ifdef HAVE_PRI_SERVICE_MESSAGES + char db_chan_name[20], db_answer[5], state; + int why = 0; + + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, p->channel); + if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + sscanf(db_answer, "%c:%d", &state, &why); + } + if ((p->resetting || p->call) || (why)) { + if (why) { + *reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL; + } +#else + if (p->resetting || p->call) { +#endif return 0; - else + } else { return 1; + } } #endif #ifdef HAVE_SS7 @@ -10736,7 +10810,7 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat int channelmatch = -1; int roundrobin = 0; int callwait = 0; - int busy = 0; + int unavailreason = 0; struct dahdi_pvt *p; struct ast_channel *tmp = NULL; char *dest=NULL; @@ -10865,7 +10939,7 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); #endif - if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { + if (p && available(p, channelmatch, groupmatch, &unavailreason, &channelmatched, &groupmatched)) { ast_debug(1, "Using channel %d\n", p->channel); if (p->inalarm) goto next; @@ -10973,10 +11047,10 @@ next: *cause = AST_CAUSE_BUSY; else if (!tmp) { if (channelmatched) { - if (busy) + if (unavailreason) *cause = AST_CAUSE_BUSY; } else if (groupmatched) { - *cause = AST_CAUSE_CONGESTION; + *cause = (unavailreason) ? unavailreason : AST_CAUSE_CONGESTION; } } @@ -12181,6 +12255,7 @@ static void dahdi_pri_error(struct pri *pri, char *s) #if defined(HAVE_PRI) static int pri_check_restart(struct dahdi_pri *pri) { +tryanotherpos: do { pri->resetpos++; } while ((pri->resetpos < pri->numchans) && @@ -12188,6 +12263,24 @@ static int pri_check_restart(struct dahdi_pri *pri) pri->pvts[pri->resetpos]->call || pri->pvts[pri->resetpos]->resetting)); if (pri->resetpos < pri->numchans) { + char db_chan_name[20], db_answer[5], state; + int why; + + /* check if the channel is out of service */ + ast_mutex_lock(&pri->pvts[pri->resetpos]->lock); + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[pri->resetpos]->span, pri->pvts[pri->resetpos]->channel); + ast_mutex_unlock(&pri->pvts[pri->resetpos]->lock); + + /* if so, try next channel */ + if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + sscanf(db_answer, "%c:%d", &state, &why); + if (why) { + ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), not sending RESTART\n", pri->span, + pri->pvts[pri->resetpos]->channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end"); + goto tryanotherpos; + } + } + /* Mark the channel as resetting and restart it */ pri->pvts[pri->resetpos]->resetting = 1; pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); @@ -12566,13 +12659,36 @@ static void *pri_dchannel(void *vpri) ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); else { - ast_verb(3, "B-channel %d/%d restarted on span %d\n", - PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); +#ifdef HAVE_PRI_SERVICE_MESSAGES + char db_chan_name[20], db_answer[5], state; + int why, skipit = 0; + ast_mutex_lock(&pri->pvts[chanpos]->lock); - if (pri->pvts[chanpos]->call) { - pri_destroycall(pri->pri, pri->pvts[chanpos]->call); - pri->pvts[chanpos]->call = NULL; + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[chanpos]->span, pri->pvts[chanpos]->channel); + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + + if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + sscanf(db_answer, "%c:%d", &state, &why); + if (why) { + ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), ignoring RESTART\n", pri->span, + e->restart.channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end"); + skipit = 1; + } else { + ast_db_del(db_chan_name, SRVST_DBKEY); + } + } + if (!skipit) { +#endif + ast_verb(3, "B-channel %d/%d restarted on span %d\n", + PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (pri->pvts[chanpos]->call) { + pri_destroycall(pri->pri, pri->pvts[chanpos]->call); + pri->pvts[chanpos]->call = NULL; + } +#ifdef HAVE_PRI_SERVICE_MESSAGES } +#endif /* Force soft hangup if appropriate */ if (pri->pvts[chanpos]->realcall) pri_hangup_all(pri->pvts[chanpos]->realcall, pri); @@ -12652,6 +12768,62 @@ static void *pri_dchannel(void *vpri) } } break; +#ifdef HAVE_PRI_SERVICE_MESSAGES + case PRI_EVENT_SERVICE: + chanpos = pri_find_principle(pri, e->service.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n", + e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span); + } else { + char db_chan_name[20], db_answer[5], state; + int ch, why = -1; + + ast_mutex_lock(&pri->pvts[chanpos]->lock); + ch = pri->pvts[chanpos]->channel; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[chanpos]->span, ch); + if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + sscanf(db_answer, "%c:%d", &state, &why); + ast_db_del(db_chan_name, SRVST_DBKEY); + } + switch (e->service.changestatus) { + case 0: /* in-service */ + if (why > -1) { + if (why & SRVST_NEAREND) { + snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NEAREND); + ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); + ast_debug(2, "channel '%d' service state { near: out-of-service, far: in-service }\n", ch); + } + } + break; + case 2: /* out-of-service */ + if (why == -1) { + why = SRVST_FAREND; + } else { + why |= SRVST_FAREND; + } + snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why); + ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); + break; + default: + ast_log(LOG_ERROR, "Huh? changestatus is: %d\n", e->service.changestatus); + } + ast_log(LOG_NOTICE, "Channel %d/%d span %d (logical: %d) received a change of service message, status '%d'\n", + PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch, e->service.changestatus); + } + break; + case PRI_EVENT_SERVICE_ACK: + chanpos = pri_find_principle(pri, e->service_ack.channel); + if (chanpos < 0) { + ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n", + e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span); + } else { + ast_debug(2, "Channel %d/%d span %d received a change os service acknowledgement message, status '%d'\n", + PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus); + } + break; +#endif case PRI_EVENT_RING: crv = NULL; if (e->ring.channel == -1) @@ -13448,6 +13620,11 @@ static int start_pri(struct dahdi_pri *pri) break; default: pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); +#ifdef HAVE_PRI_SERVICE_MESSAGES + if (pri->enable_service_message_support) { + pri_set_service_message_support(pri->dchans[i], 1); + } +#endif break; } /* Force overlap dial if we're doing GR-303! */ @@ -13622,6 +13799,149 @@ static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a } #endif /* defined(HAVE_PRI) */ +#ifdef HAVE_PRI_SERVICE_MESSAGES +static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus) +{ + int why; + int channel; + int trunkgroup; + int x, y, fd = a->fd; + int interfaceid = 0; + char *c; + char state; + char db_chan_name[20], db_answer[5]; + struct dahdi_pvt *start, *tmp = NULL; + struct dahdi_pri *pri = NULL; + ast_mutex_t *lock; + + lock = &iflock; + start = iflist; + + if (a->argc < 5 || a->argc > 6) + return CLI_SHOWUSAGE; + if ((c = strchr(a->argv[4], ':'))) { + if (sscanf(a->argv[4], "%d:%d", &trunkgroup, &channel) != 2) + return CLI_SHOWUSAGE; + if ((trunkgroup < 1) || (channel < 1)) + return CLI_SHOWUSAGE; + for (x=0;x<NUM_SPANS;x++) { + if (pris[x].trunkgroup == trunkgroup) { + pri = pris + x; + break; + } + } + if (pri) { + start = pri->crvs; + lock = &pri->lock; + } else { + ast_cli(fd, "No such trunk group %d\n", trunkgroup); + return CLI_FAILURE; + } + } else + channel = atoi(a->argv[4]); + + if (a->argc == 6) + interfaceid = atoi(a->argv[5]); + + /* either servicing a D-Channel */ + for (x = 0; x < NUM_SPANS; x++) { + for (y = 0; y < NUM_DCHANS; y++) { + if (pris[x].dchannels[y] == channel) { + pri = pris + x; + pri_maintenance_service(pri->pri, interfaceid, -1, changestatus); + return CLI_SUCCESS; + } + } + } + + /* or servicing a B-Channel */ + ast_mutex_lock(lock); + tmp = start; + while (tmp) { + if (tmp->pri && tmp->channel == channel) { + if (!tmp->pri->enable_service_message_support) { + ast_cli(fd, "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n\tNote only 4ess and 5ess switch types are supported.\n\n"); + return CLI_SUCCESS; + } + why = -1; + snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel); + if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) { + sscanf(db_answer, "%c:%d", &state, &why); + ast_db_del(db_chan_name, SRVST_DBKEY); + } + switch(changestatus) { + case 0: /* enable */ + if (why > -1) { + if (why & SRVST_FAREND) { + why = SRVST_FAREND; + snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why); + ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); + ast_debug(2, "channel '%d' service state { near: in-service, far: out-of-service }\n", channel); + } + } + break; + /* case 1: -- loop */ + case 2: /* disable */ + if (why == -1) { + why = SRVST_NEAREND; + } else { + why |= SRVST_NEAREND; + } + snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why); + ast_db_put(db_chan_name, SRVST_DBKEY, db_answer); + break; + /* case 3: -- continuity */ + /* case 4: -- shutdown */ + default: + ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus); + } + pri_maintenance_service(tmp->pri->pri, PRI_SPAN(PVT_TO_CHANNEL(tmp)), PVT_TO_CHANNEL(tmp), changestatus); + ast_mutex_unlock(lock); + return CLI_SUCCESS; + } + tmp = tmp->next; + } + ast_mutex_unlock(lock); + + ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel); + return CLI_FAILURE; +} + +static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "pri service enable channel"; + e->usage = + "Usage: pri service enable channel <channel> [<interface id>]\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to restore a channel to service, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + return handle_pri_service_generic(e, cmd, a, 0); +} + +static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "pri service disable channel"; + e->usage = + "Usage: pri service disable channel <chan num> [<interface id>]\n" + " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n" + " to remove a channel from service, with optional interface id\n" + " as agreed upon with remote switch operator\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + return handle_pri_service_generic(e, cmd, a, 2); +} +#endif + #if defined(HAVE_PRI) static void build_status(char *s, size_t len, int status, int active) { @@ -13798,6 +14118,10 @@ static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli #if defined(HAVE_PRI) static struct ast_cli_entry dahdi_pri_cli[] = { AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"), +#ifdef HAVE_PRI_SERVICE_MESSAGES + AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"), + AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"), +#endif AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"), AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"), AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"), @@ -16581,6 +16905,14 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct #endif } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { confp->pri.discardremoteholdretrieval = ast_true(v->value); +#ifdef HAVE_PRI_SERVICE_MESSAGES + } else if (!strcasecmp(v->name, "service_message_support")) { + /* assuming switchtype for this channel group has been configured already */ + if ((confp->pri.switchtype == PRI_SWITCH_ATT4ESS || confp->pri.switchtype == PRI_SWITCH_LUCENT5E) && ast_true(v->value)) + confp->pri.enable_service_message_support = 1; + else + confp->pri.enable_service_message_support = 0; +#endif #ifdef HAVE_PRI_INBANDDISCONNECT } else if (!strcasecmp(v->name, "inbanddisconnect")) { confp->pri.inbanddisconnect = ast_true(v->value); diff --git a/configs/chan_dahdi.conf.sample b/configs/chan_dahdi.conf.sample index c3219f3fcc21b5641e023142011d48a4bbdc1042..c0c9cfe5af120f328e65dfe597ae359fbb7930d7 100644 --- a/configs/chan_dahdi.conf.sample +++ b/configs/chan_dahdi.conf.sample @@ -74,6 +74,9 @@ ; ;nsf=none ; +;service_message_support=yes +; Enable service message support for channel. Must be set after switchtype. +; ; PRI Dialplan: The ISDN-level Type Of Number (TON) or numbering plan, used for ; the dialed number. For most installations, leaving this as 'unknown' (the ; default) works in the most cases. In some very unusual circumstances, you diff --git a/configure b/configure index 0725b292779e95ee03cefd1b08d94ab667d99bc8..771a1159e7461b8671592b1a2335648312cd6a1d 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 182847 . +# From configure.ac Revision: 183242 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for asterisk 1.6. # @@ -42037,6 +42037,268 @@ fi +if test "x${PBX_PRI_SERVICE_MESSAGES}" != "x1" -a "${USE_PRI_SERVICE_MESSAGES}" != "no"; then + pbxlibdir="" + # if --with-PRI_SERVICE_MESSAGES=DIR has been specified, use it. + if test "x${PRI_SERVICE_MESSAGES_DIR}" != "x"; then + if test -d ${PRI_SERVICE_MESSAGES_DIR}/lib; then + pbxlibdir="-L${PRI_SERVICE_MESSAGES_DIR}/lib" + else + pbxlibdir="-L${PRI_SERVICE_MESSAGES_DIR}" + fi + fi + pbxfuncname="pri_maintenance_service" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_PRI_SERVICE_MESSAGES_FOUND=yes + else + as_ac_Lib=`echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lpri" >&5 +echo $ECHO_N "checking for ${pbxfuncname} in -lpri... $ECHO_C" >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpri ${pbxlibdir} $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_Lib=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval echo '${'$as_ac_Lib'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Lib'}'` = yes; then + AST_PRI_SERVICE_MESSAGES_FOUND=yes +else + AST_PRI_SERVICE_MESSAGES_FOUND=no +fi + + fi + + # now check for the header. + if test "${AST_PRI_SERVICE_MESSAGES_FOUND}" = "yes"; then + PRI_SERVICE_MESSAGES_LIB="${pbxlibdir} -lpri " + # if --with-PRI_SERVICE_MESSAGES=DIR has been specified, use it. + if test "x${PRI_SERVICE_MESSAGES_DIR}" != "x"; then + PRI_SERVICE_MESSAGES_INCLUDE="-I${PRI_SERVICE_MESSAGES_DIR}/include" + fi + PRI_SERVICE_MESSAGES_INCLUDE="${PRI_SERVICE_MESSAGES_INCLUDE} " + if test "xlibpri.h" = "x" ; then # no header, assume found + PRI_SERVICE_MESSAGES_HEADER_FOUND="1" + else # check for the header + saved_cppflags="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${PRI_SERVICE_MESSAGES_INCLUDE}" + if test "${ac_cv_header_libpri_h+set}" = set; then + { echo "$as_me:$LINENO: checking for libpri.h" >&5 +echo $ECHO_N "checking for libpri.h... $ECHO_C" >&6; } +if test "${ac_cv_header_libpri_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_libpri_h" >&5 +echo "${ECHO_T}$ac_cv_header_libpri_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking libpri.h usability" >&5 +echo $ECHO_N "checking libpri.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <libpri.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking libpri.h presence" >&5 +echo $ECHO_N "checking libpri.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <libpri.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: libpri.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: libpri.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: libpri.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: libpri.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: libpri.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: libpri.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: libpri.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: libpri.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: libpri.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: libpri.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: libpri.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: libpri.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: libpri.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: libpri.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: libpri.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: libpri.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------- ## +## Report this to www.asterisk.org ## +## ------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for libpri.h" >&5 +echo $ECHO_N "checking for libpri.h... $ECHO_C" >&6; } +if test "${ac_cv_header_libpri_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_libpri_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_libpri_h" >&5 +echo "${ECHO_T}$ac_cv_header_libpri_h" >&6; } + +fi +if test $ac_cv_header_libpri_h = yes; then + PRI_SERVICE_MESSAGES_HEADER_FOUND=1 +else + PRI_SERVICE_MESSAGES_HEADER_FOUND=0 +fi + + + CPPFLAGS="${saved_cppflags}" + fi + if test "x${PRI_SERVICE_MESSAGES_HEADER_FOUND}" = "x0" ; then + PRI_SERVICE_MESSAGES_LIB="" + PRI_SERVICE_MESSAGES_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + PRI_SERVICE_MESSAGES_LIB="" + fi + PBX_PRI_SERVICE_MESSAGES=1 + # XXX don't know how to evaluate the description (third argument) in AC_DEFINE_UNQUOTED + +cat >>confdefs.h <<_ACEOF +#define HAVE_PRI_SERVICE_MESSAGES 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define HAVE_PRI_SERVICE_MESSAGES_VERSION +_ACEOF + + fi + fi +fi + + + if test "x${PBX_RESAMPLE}" != "x1" -a "${USE_RESAMPLE}" != "no"; then pbxlibdir="" # if --with-RESAMPLE=DIR has been specified, use it. diff --git a/configure.ac b/configure.ac index ac129accc816d6f5c65c5c451cc7533b070078d7..00220d238ed7106cd17d85905d20f92dd50c3d99 100644 --- a/configure.ac +++ b/configure.ac @@ -1404,6 +1404,8 @@ AST_EXT_LIB_CHECK([PRI_PROG_W_CAUSE], [pri], [pri_progress_with_cause], [libpri. AST_EXT_LIB_CHECK([PRI_INBANDDISCONNECT], [pri], [pri_set_inbanddisconnect], [libpri.h]) +AST_EXT_LIB_CHECK([PRI_SERVICE_MESSAGES], [pri], [pri_maintenance_service], [libpri.h]) + AST_EXT_LIB_CHECK([RESAMPLE], [resample], [resample_open], [libresample.h], [-lm]) AST_C_COMPILE_CHECK([SPANDSP], [ diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index dc95c83929457e6fb6fac3b898f130274c47856e..dba007d47a9343eeefc69079eb65757a7c03584d 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -671,6 +671,12 @@ /* Define to indicate the ${PRI_PROG_W_CAUSE_DESCRIP} library version */ #undef HAVE_PRI_PROG_W_CAUSE_VERSION +/* Define this to indicate the ${PRI_SERVICE_MESSAGES_DESCRIP} library */ +#undef HAVE_PRI_SERVICE_MESSAGES + +/* Define to indicate the ${PRI_SERVICE_MESSAGES_DESCRIP} library version */ +#undef HAVE_PRI_SERVICE_MESSAGES_VERSION + /* Define to indicate the ${PRI_DESCRIP} library version */ #undef HAVE_PRI_VERSION