dial by name in chan_dahdi
* chan_dahdi supports dialing configuring and dialing by device file name. DAHDI/span-name!local!1 will use /dev/dahdi/span-name/local/1 . Likewise it may appear in chan_dahdi.conf as 'channel => span-name!local!1'. * A new options for chan_dahdi.conf: 'ignore_failed_channels'. Boolean. False by default. If set, chan_dahdi will ignore failed 'channel' entries. Handy for the above name-based syntax as it does not depend on initialization order. * have my_pri_make_cc_dialstring() only manupulate dial-strings of group (gGrR) dialing, which make it lsightly more complicated. https://reviewboard.asterisk.org/r/535/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@269238 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
3b16eaaac5
commit
0107ea5d6b
7
CHANGES
7
CHANGES
|
@ -485,6 +485,13 @@ Miscellaneous
|
|||
of dynamic parkinglots.
|
||||
* chan_dahdi now supports reporting alarms over AMI either by channel or span via
|
||||
the reportalarms config option.
|
||||
* chan_dahdi supports dialing configuring and dialing by device file name.
|
||||
DAHDI/span-name!local!1 will use /dev/dahdi/span-name/local/1 . Likewise
|
||||
it may appear in chan_dahdi.conf as 'channel => span-name!local!1'.
|
||||
* A new options for chan_dahdi.conf: 'ignore_failed_channels'. Boolean.
|
||||
False by default. If set, chan_dahdi will ignore failed 'channel' entries.
|
||||
Handy for the above name-based syntax as it does not depend on
|
||||
initialization order.
|
||||
* The Realtime dialplan switch now caches entries for 1 second. This provides a
|
||||
significant increase in performance (about 3X) for installations using this switchtype.
|
||||
|
||||
|
|
|
@ -1240,6 +1240,8 @@ struct dahdi_chan_conf {
|
|||
#endif
|
||||
struct dahdi_params timing;
|
||||
int is_sig_auto; /*!< Use channel signalling from DAHDI? */
|
||||
/*! Continue configuration even if a channel is not there. */
|
||||
int ignore_failed_channels;
|
||||
|
||||
/*!
|
||||
* \brief The serial port to listen for SMDI data on
|
||||
|
@ -2900,14 +2902,12 @@ static void my_set_rdnis(void *pvt, const char *rdnis)
|
|||
*
|
||||
* \details
|
||||
* original dialstring:
|
||||
* DAHDI/[i<span>-]<channel#>[c|r<cadance#>|d][/extension[/options]]
|
||||
* DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
|
||||
*
|
||||
* The modified dialstring will have prefixed the channel-group section
|
||||
* with the ISDN channel restriction.
|
||||
*
|
||||
* buf:
|
||||
* DAHDI/i<span>-<channel#>[c|r<cadance#>|d][/extension[/options]]
|
||||
* DAHDI/i<span>-(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]]
|
||||
*
|
||||
* The routine will check to see if the ISDN channel restriction is already
|
||||
|
@ -2939,8 +2939,9 @@ static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
|
|||
snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
|
||||
return;
|
||||
}
|
||||
if (args.group[0] == 'i') {
|
||||
/* The ISDN span channel restriction is already in the dialstring. */
|
||||
if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
|
||||
/* The ISDN span channel restriction is not needed or already
|
||||
* in the dialstring. */
|
||||
ast_copy_string(buf, pvt->dialstring, buf_size);
|
||||
return;
|
||||
}
|
||||
|
@ -11506,6 +11507,38 @@ static int sigtype_to_signalling(int sigtype)
|
|||
return sigtype;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Get file name and channel number from (subdir,number)
|
||||
*
|
||||
* \param subdir name of the subdirectory under /dev/dahdi/
|
||||
* \param channel name of device file under /dev/dahdi/<subdir>/
|
||||
* \param path buffer to put file name in
|
||||
* \param pathlen maximal length of path
|
||||
*
|
||||
* \retval minor number of dahdi channel.
|
||||
* \retval -errno on error.
|
||||
*/
|
||||
static int device2chan(const char *subdir, int channel, char *path, int pathlen)
|
||||
{
|
||||
struct stat stbuf;
|
||||
int num;
|
||||
|
||||
snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
|
||||
if (stat(path, &stbuf) < 0) {
|
||||
ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
if (!S_ISCHR(stbuf.st_mode)) {
|
||||
ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
|
||||
return -EINVAL;
|
||||
}
|
||||
num = minor(stbuf.st_rdev);
|
||||
ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
|
||||
return num;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Initialize/create a channel interface.
|
||||
|
@ -12686,6 +12719,7 @@ static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi
|
|||
int x;
|
||||
int res = 0;
|
||||
struct dahdi_pvt *p;
|
||||
char *subdir = NULL;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(group); /* channel/group token */
|
||||
//AST_APP_ARG(ext); /* extension token */
|
||||
|
@ -12696,8 +12730,9 @@ static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi
|
|||
/*
|
||||
* data is ---v
|
||||
* Dial(DAHDI/pseudo[/extension[/options]])
|
||||
* Dial(DAHDI/[i<span>-]<channel#>[c|r<cadance#>|d][/extension[/options]])
|
||||
* Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension[/options]])
|
||||
* Dial(DAHDI/[i<span>-](g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension[/options]])
|
||||
* Dial(DAHDI/<subdir>!<channel#>[c|r<cadance#>|d][/extension[/options]])
|
||||
*
|
||||
* i - ISDN span channel restriction.
|
||||
* Used by CC to ensure that the CC recall goes out the same span.
|
||||
|
@ -12728,7 +12763,16 @@ static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi
|
|||
memset(param, 0, sizeof(*param));
|
||||
param->channelmatch = -1;
|
||||
|
||||
if (args.group[0] == 'i') {
|
||||
if (strchr(args.group, '!') != NULL) {
|
||||
char *prev = args.group;
|
||||
while ((s = strchr(prev, '!')) != NULL) {
|
||||
*s++ = '/';
|
||||
prev = s;
|
||||
}
|
||||
*(prev - 1) = '\0';
|
||||
subdir = args.group;
|
||||
args.group = prev;
|
||||
} else if (args.group[0] == 'i') {
|
||||
/* Extract the ISDN span channel restriction specifier. */
|
||||
res = sscanf(args.group + 1, "%30d", &x);
|
||||
if (res < 1) {
|
||||
|
@ -12796,6 +12840,24 @@ static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi
|
|||
param->channelmatch = x;
|
||||
}
|
||||
}
|
||||
if (subdir) {
|
||||
char path[PATH_MAX];
|
||||
struct stat stbuf;
|
||||
|
||||
snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
|
||||
subdir, param->channelmatch);
|
||||
if (stat(path, &stbuf) < 0) {
|
||||
ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
|
||||
path, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (!S_ISCHR(stbuf.st_mode)) {
|
||||
ast_log(LOG_ERROR, "%s: Not a character device file\n",
|
||||
path);
|
||||
return NULL;
|
||||
}
|
||||
param->channelmatch = minor(stbuf.st_rdev);
|
||||
}
|
||||
|
||||
p = iflist;
|
||||
}
|
||||
|
@ -15807,9 +15869,33 @@ static int unload_module(void)
|
|||
return __unload_module();
|
||||
}
|
||||
|
||||
static void string_replace(char *str, int char1, int char2)
|
||||
{
|
||||
for (; *str; str++) {
|
||||
if (*str == char1) {
|
||||
*str = char2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *parse_spanchan(char *chanstr, char **subdir)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(chanstr, '!')) == NULL) {
|
||||
*subdir = NULL;
|
||||
return chanstr;
|
||||
}
|
||||
*p++ = '\0';
|
||||
string_replace(chanstr, '!', '/');
|
||||
*subdir = chanstr;
|
||||
return p;
|
||||
}
|
||||
|
||||
static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
|
||||
{
|
||||
char *c, *chan;
|
||||
char *subdir;
|
||||
int x, start, finish;
|
||||
struct dahdi_pvt *tmp;
|
||||
|
||||
|
@ -15819,6 +15905,7 @@ static int build_channels(struct dahdi_chan_conf *conf, const char *value, int r
|
|||
}
|
||||
|
||||
c = ast_strdupa(value);
|
||||
c = parse_spanchan(c, &subdir);
|
||||
|
||||
while ((chan = strsep(&c, ","))) {
|
||||
if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
|
||||
|
@ -15842,13 +15929,30 @@ static int build_channels(struct dahdi_chan_conf *conf, const char *value, int r
|
|||
}
|
||||
|
||||
for (x = start; x <= finish; x++) {
|
||||
tmp = mkintf(x, conf, reload);
|
||||
char fn[PATH_MAX];
|
||||
int real_channel = x;
|
||||
|
||||
if (!ast_strlen_zero(subdir)) {
|
||||
real_channel = device2chan(subdir, x, fn, sizeof(fn));
|
||||
if (real_channel < 0) {
|
||||
if (conf->ignore_failed_channels) {
|
||||
ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
|
||||
subdir, x, real_channel);
|
||||
continue;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
|
||||
subdir, x, real_channel);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp = mkintf(real_channel, conf, reload);
|
||||
|
||||
if (tmp) {
|
||||
ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
|
||||
ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
|
||||
(reload == 1) ? "reconfigure" : "register", value);
|
||||
(reload == 1) ? "reconfigure" : "register", value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -15939,9 +16043,17 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
|
|||
ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
|
||||
continue;
|
||||
}
|
||||
if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo))
|
||||
if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
|
||||
if (confp->ignore_failed_channels) {
|
||||
ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
|
||||
} else if (!strcasecmp(v->name, "ignore_failed_channels")) {
|
||||
confp->ignore_failed_channels = ast_true(v->value);
|
||||
} else if (!strcasecmp(v->name, "buffers")) {
|
||||
if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
|
||||
ast_log(LOG_WARNING, "Using default buffer policy.\n");
|
||||
|
|
|
@ -915,6 +915,15 @@ pickupgroup=1
|
|||
;minunused=2
|
||||
;minidle=1
|
||||
;
|
||||
;
|
||||
; ignore_failed_channels: Continue even if some channels failed to configure.
|
||||
; False by default, as if even a single channel failed to configure, it might
|
||||
; mean other channels are misplaced and having them work may not be a good
|
||||
; idea. If enabled (set to true), chan_dahdi will nevertheless attempt to
|
||||
; configure other channels rather than giving up. This normally makes sense
|
||||
; only if you use names (<subdir>!<number>) for DAHDI channels.
|
||||
;ignore_failed_channels = true
|
||||
;
|
||||
; Configure jitter buffers in DAHDI (each one is 20ms, default is 4)
|
||||
; This is set globally, rather than per-channel.
|
||||
;
|
||||
|
@ -1027,8 +1036,24 @@ pickupgroup=1
|
|||
; signalling = pri_cpe
|
||||
; group = 2
|
||||
; channel => 1-23
|
||||
|
||||
;
|
||||
; Alternatively, the number of the channel may be replaced with a relative
|
||||
; path to a device file under /dev/dahdi . The final element of that file
|
||||
; must be a number, though. The directory separator is '!', as we can't
|
||||
; use '/' in a dial string. So if we have
|
||||
;
|
||||
; /dev/dahdi/span-name/pstn/00/1
|
||||
; /dev/dahdi/span-name/pstn/00/2
|
||||
; /dev/dahdi/span-name/pstn/00/3
|
||||
; /dev/dahdi/span-name/pstn/00/4
|
||||
;
|
||||
; we could use:
|
||||
;channel => span-name!pstn!00!1-4
|
||||
;
|
||||
; or:
|
||||
;channel => span-name!pstn!00!1,2,3,4
|
||||
;
|
||||
; See also ignore_failed_channels above.
|
||||
|
||||
; Used for distinctive ring support for x100p.
|
||||
; You can see the dringX patterns is to set any one of the dringXcontext fields
|
||||
|
|
Reference in New Issue