merge markster's usersconf branch with some slight changes
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@43052 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
5b13041e0f
commit
5c0e56df21
|
@ -393,10 +393,10 @@ static struct ast_config *realtime_directory(char *context)
|
|||
return cfg;
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last, int readext, int fromappvm)
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int last, int readext, int fromappvm)
|
||||
{
|
||||
/* Read in the first three digits.. "digit" is the first digit, already read */
|
||||
char ext[NUMDIGITS + 1];
|
||||
char ext[NUMDIGITS + 1], *cat;
|
||||
char name[80] = "";
|
||||
struct ast_variable *v;
|
||||
int res;
|
||||
|
@ -499,6 +499,58 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
|||
}
|
||||
}
|
||||
|
||||
if (!res && ucfg) {
|
||||
/* Search users.conf for all names which start with those digits */
|
||||
for (cat = ast_category_browse(ucfg, NULL); cat && !res ; cat = ast_category_browse(ucfg, cat)) {
|
||||
if (!strcasecmp(cat, "general"))
|
||||
continue;
|
||||
if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
|
||||
continue;
|
||||
|
||||
/* Find all candidate extensions */
|
||||
if ((pos = ast_variable_retrieve(ucfg, cat, "fullname"))) {
|
||||
ast_copy_string(name, pos, sizeof(name));
|
||||
/* Grab the last name */
|
||||
if (last && strrchr(pos,' '))
|
||||
pos = strrchr(pos, ' ') + 1;
|
||||
conv = convert(pos);
|
||||
if (conv) {
|
||||
if (!strcmp(conv, ext)) {
|
||||
/* Match! */
|
||||
found++;
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
res = play_mailbox_owner(chan, context, dialcontext, cat, name, readext, fromappvm);
|
||||
switch (res) {
|
||||
case -1:
|
||||
/* user pressed '1' but extension does not exist, or
|
||||
* user hungup
|
||||
*/
|
||||
lastuserchoice = 0;
|
||||
break;
|
||||
case '1':
|
||||
/* user pressed '1' and extensions exists;
|
||||
play_mailbox_owner will already have done
|
||||
a goto() on the channel
|
||||
*/
|
||||
lastuserchoice = res;
|
||||
break;
|
||||
case '*':
|
||||
/* user pressed '*' to skip something found */
|
||||
lastuserchoice = res;
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(conv);
|
||||
break;
|
||||
}
|
||||
free(conv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastuserchoice != '1') {
|
||||
res = ast_streamfile(chan, found ? "dir-nomore" : "dir-nomatch", chan->language);
|
||||
if (!res)
|
||||
|
@ -514,7 +566,7 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
|||
{
|
||||
int res = 0;
|
||||
struct ast_module_user *u;
|
||||
struct ast_config *cfg;
|
||||
struct ast_config *cfg, *ucfg;
|
||||
int last = 1;
|
||||
int readext = 0;
|
||||
int fromappvm = 0;
|
||||
|
@ -554,6 +606,8 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
|||
ast_module_user_remove(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ucfg = ast_config_load("users.conf");
|
||||
|
||||
dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
|
||||
if (ast_strlen_zero(dirintro))
|
||||
|
@ -571,7 +625,7 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
|||
if (!res)
|
||||
res = ast_waitfordigit(chan, 5000);
|
||||
if (res > 0) {
|
||||
res = do_directory(chan, cfg, args.vmcontext, args.dialcontext, res, last, readext, fromappvm);
|
||||
res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, last, readext, fromappvm);
|
||||
if (res > 0) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
|
@ -581,6 +635,8 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (ucfg)
|
||||
ast_config_destroy(ucfg);
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
return res;
|
||||
|
|
|
@ -404,6 +404,8 @@ static char ext_pass_cmd[128];
|
|||
#define tdesc "Comedian Mail (Voicemail System)"
|
||||
#endif
|
||||
|
||||
static char userscontext[AST_MAX_EXTENSION] = "default";
|
||||
|
||||
static char *addesc = "Comedian Mail";
|
||||
|
||||
static char *synopsis_vm =
|
||||
|
@ -641,9 +643,32 @@ static void apply_options(struct ast_vm_user *vmu, const char *options)
|
|||
}
|
||||
}
|
||||
|
||||
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
|
||||
{
|
||||
struct ast_variable *tmp;
|
||||
tmp = var;
|
||||
while (tmp) {
|
||||
if (!strcasecmp(tmp->name, "password")) {
|
||||
ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
|
||||
} else if (!strcasecmp(tmp->name, "uniqueid")) {
|
||||
ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
|
||||
} else if (!strcasecmp(tmp->name, "pager")) {
|
||||
ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
|
||||
} else if (!strcasecmp(tmp->name, "email")) {
|
||||
ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
|
||||
} else if (!strcasecmp(tmp->name, "fullname")) {
|
||||
ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
|
||||
} else if (!strcasecmp(tmp->name, "context")) {
|
||||
ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
|
||||
} else
|
||||
apply_option(retval, tmp->name, tmp->value);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
|
||||
{
|
||||
struct ast_variable *var, *tmp;
|
||||
struct ast_variable *var;
|
||||
struct ast_vm_user *retval;
|
||||
|
||||
if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
|
||||
|
@ -659,25 +684,7 @@ static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const cha
|
|||
else
|
||||
var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, NULL);
|
||||
if (var) {
|
||||
tmp = var;
|
||||
while (tmp) {
|
||||
printf("%s => %s\n", tmp->name, tmp->value);
|
||||
if (!strcasecmp(tmp->name, "password")) {
|
||||
ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
|
||||
} else if (!strcasecmp(tmp->name, "uniqueid")) {
|
||||
ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
|
||||
} else if (!strcasecmp(tmp->name, "pager")) {
|
||||
ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
|
||||
} else if (!strcasecmp(tmp->name, "email")) {
|
||||
ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
|
||||
} else if (!strcasecmp(tmp->name, "fullname")) {
|
||||
ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
|
||||
} else if (!strcasecmp(tmp->name, "context")) {
|
||||
ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
|
||||
} else
|
||||
apply_option(retval, tmp->name, tmp->value);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
apply_options_full(retval, var);
|
||||
ast_variables_destroy(var);
|
||||
} else {
|
||||
if (!ivm)
|
||||
|
@ -6573,6 +6580,26 @@ static int vm_exec(struct ast_channel *chan, void *data)
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct ast_vm_user *find_or_create(char *context, char *mbox)
|
||||
{
|
||||
struct ast_vm_user *vmu;
|
||||
AST_LIST_TRAVERSE(&users, vmu, list) {
|
||||
if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mbox, vmu->mailbox))
|
||||
break;
|
||||
if (context && (!strcasecmp(context, vmu->context)) && (!strcasecmp(mbox, vmu->mailbox)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!vmu) {
|
||||
if ((vmu = ast_calloc(1, sizeof(*vmu)))) {
|
||||
ast_copy_string(vmu->context, context, sizeof(vmu->context));
|
||||
ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
|
||||
AST_LIST_INSERT_TAIL(&users, vmu, list);
|
||||
}
|
||||
}
|
||||
return vmu;
|
||||
}
|
||||
|
||||
static int append_mailbox(char *context, char *mbox, char *data)
|
||||
{
|
||||
/* Assumes lock is already held */
|
||||
|
@ -6582,10 +6609,7 @@ static int append_mailbox(char *context, char *mbox, char *data)
|
|||
struct ast_vm_user *vmu;
|
||||
|
||||
ast_copy_string(tmp, data, sizeof(tmp));
|
||||
if ((vmu = ast_calloc(1, sizeof(*vmu)))) {
|
||||
ast_copy_string(vmu->context, context, sizeof(vmu->context));
|
||||
ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
|
||||
|
||||
if ((vmu = find_or_create(context, mbox))) {
|
||||
populate_defaults(vmu);
|
||||
|
||||
stringp = tmp;
|
||||
|
@ -6599,8 +6623,6 @@ static int append_mailbox(char *context, char *mbox, char *data)
|
|||
ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
|
||||
if (stringp && (s = strsep(&stringp, ",")))
|
||||
apply_options(vmu, s);
|
||||
|
||||
AST_LIST_INSERT_TAIL(&users, vmu, list);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -6813,7 +6835,7 @@ static int load_config(void)
|
|||
{
|
||||
struct ast_vm_user *cur;
|
||||
struct vm_zone *zcur;
|
||||
struct ast_config *cfg;
|
||||
struct ast_config *cfg, *ucfg;
|
||||
char *cat;
|
||||
struct ast_variable *var;
|
||||
char *notifystr = NULL;
|
||||
|
@ -6843,6 +6865,7 @@ static int load_config(void)
|
|||
char *thresholdstr;
|
||||
char *fmt;
|
||||
char *astemail;
|
||||
char *ucontext;
|
||||
char *astmailcmd = SENDMAIL;
|
||||
char *astforcename;
|
||||
char *astforcegreet;
|
||||
|
@ -6874,6 +6897,9 @@ static int load_config(void)
|
|||
if (cfg) {
|
||||
/* General settings */
|
||||
|
||||
if (!(ucontext = ast_variable_retrieve(cfg, "general", "userscontext")))
|
||||
ucontext = "default";
|
||||
ast_copy_string(userscontext, ucontext, sizeof(userscontext));
|
||||
/* Attach voice message to mail message ? */
|
||||
if (!(astattach = ast_variable_retrieve(cfg, "general", "attach")))
|
||||
astattach = "yes";
|
||||
|
@ -7159,6 +7185,18 @@ static int load_config(void)
|
|||
if (!(astdirfwd = ast_variable_retrieve(cfg, "general", "usedirectory")))
|
||||
astdirfwd = "no";
|
||||
ast_set2_flag((&globalflags), ast_true(astdirfwd), VM_DIRECFORWARD);
|
||||
if ((ucfg = ast_config_load("users.conf"))) {
|
||||
for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
|
||||
if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
|
||||
continue;
|
||||
if ((cur = find_or_create(userscontext, cat))) {
|
||||
populate_defaults(cur);
|
||||
apply_options_full(cur, ast_variable_browse(ucfg, cat));
|
||||
ast_copy_string(cur->context, userscontext, sizeof(cur->context));
|
||||
}
|
||||
}
|
||||
ast_config_destroy(ucfg);
|
||||
}
|
||||
cat = ast_category_browse(cfg, NULL);
|
||||
while (cat) {
|
||||
if (strcasecmp(cat, "general")) {
|
||||
|
|
|
@ -798,8 +798,8 @@ static int send_command_locked(unsigned short callno, char, int, unsigned int, c
|
|||
static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int);
|
||||
static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause);
|
||||
static struct ast_frame *iax2_read(struct ast_channel *c);
|
||||
static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly);
|
||||
static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly);
|
||||
static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly);
|
||||
static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly);
|
||||
static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, time_t regtime);
|
||||
static void destroy_user(struct iax2_user *user);
|
||||
static void prune_peers(void);
|
||||
|
@ -2446,7 +2446,7 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in
|
|||
if (!var)
|
||||
return NULL;
|
||||
|
||||
peer = build_peer(peername, var, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
|
||||
peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
|
||||
|
||||
if (!peer)
|
||||
return NULL;
|
||||
|
@ -2534,7 +2534,7 @@ static struct iax2_user *realtime_user(const char *username)
|
|||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
user = build_user(username, var, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
|
||||
user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
|
||||
if (!user)
|
||||
return NULL;
|
||||
|
||||
|
@ -8216,17 +8216,20 @@ static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr)
|
|||
|
||||
|
||||
/*! \brief Create peer structure based on configuration */
|
||||
static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly)
|
||||
static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
|
||||
{
|
||||
struct iax2_peer *peer = NULL;
|
||||
struct ast_ha *oldha = NULL;
|
||||
int maskfound=0;
|
||||
int found=0;
|
||||
int firstpass=1;
|
||||
|
||||
AST_LIST_LOCK(&peers);
|
||||
if (!temponly) {
|
||||
AST_LIST_TRAVERSE(&peers, peer, entry) {
|
||||
if (!strcmp(peer->name, name)) {
|
||||
if (!ast_test_flag(peer, IAX_DELME))
|
||||
firstpass = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8234,8 +8237,10 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
|
|||
peer = NULL;
|
||||
if (peer) {
|
||||
found++;
|
||||
oldha = peer->ha;
|
||||
peer->ha = NULL;
|
||||
if (firstpass) {
|
||||
oldha = peer->ha;
|
||||
peer->ha = NULL;
|
||||
}
|
||||
AST_LIST_REMOVE(&peers, peer, entry);
|
||||
AST_LIST_UNLOCK(&peers);
|
||||
} else {
|
||||
|
@ -8251,25 +8256,29 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
|
|||
}
|
||||
}
|
||||
if (peer) {
|
||||
ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
|
||||
peer->encmethods = iax2_encryption;
|
||||
peer->adsi = adsi;
|
||||
/* NOT ANY MORE: peer->secret[0] = '\0'; */
|
||||
ast_string_field_set(peer,secret,"");
|
||||
if (!found) {
|
||||
ast_string_field_set(peer, name, name);
|
||||
peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
|
||||
peer->expiry = min_reg_expire;
|
||||
if (firstpass) {
|
||||
ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
|
||||
peer->encmethods = iax2_encryption;
|
||||
peer->adsi = adsi;
|
||||
ast_string_field_set(peer,secret,"");
|
||||
if (!found) {
|
||||
ast_string_field_set(peer, name, name);
|
||||
peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
|
||||
peer->expiry = min_reg_expire;
|
||||
}
|
||||
peer->prefs = prefs;
|
||||
peer->capability = iax2_capability;
|
||||
peer->smoothing = 0;
|
||||
peer->pokefreqok = DEFAULT_FREQ_OK;
|
||||
peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
|
||||
ast_string_field_set(peer,context,"");
|
||||
ast_string_field_set(peer,peercontext,"");
|
||||
}
|
||||
|
||||
if (!v) {
|
||||
v = alt;
|
||||
alt = NULL;
|
||||
}
|
||||
peer->prefs = prefs;
|
||||
peer->capability = iax2_capability;
|
||||
peer->smoothing = 0;
|
||||
peer->pokefreqok = DEFAULT_FREQ_OK;
|
||||
peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
|
||||
/* NO MORE: peer->context[0] = '\0';
|
||||
peer->peercontext[0] = '\0'; */
|
||||
ast_string_field_set(peer,context,"");
|
||||
ast_string_field_set(peer,peercontext,"");
|
||||
while(v) {
|
||||
if (!strcasecmp(v->name, "secret")) {
|
||||
ast_string_field_set(peer, secret, v->value);
|
||||
|
@ -8376,6 +8385,12 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
|
|||
ast_string_field_set(peer, cid_name, name2);
|
||||
ast_string_field_set(peer, cid_num, num2);
|
||||
ast_set_flag(peer, IAX_HASCALLERID);
|
||||
} else if (!strcasecmp(v->name, "fullname")) {
|
||||
ast_string_field_set(peer, cid_name, v->value);
|
||||
ast_set_flag(peer, IAX_HASCALLERID);
|
||||
} else if (!strcasecmp(v->name, "cid_number")) {
|
||||
ast_string_field_set(peer, cid_num, v->value);
|
||||
ast_set_flag(peer, IAX_HASCALLERID);
|
||||
} else if (!strcasecmp(v->name, "sendani")) {
|
||||
ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI);
|
||||
} else if (!strcasecmp(v->name, "inkeys")) {
|
||||
|
@ -8407,7 +8422,11 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
|
|||
peer->adsi = ast_true(v->value);
|
||||
}/* else if (strcasecmp(v->name,"type")) */
|
||||
/* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
|
||||
v=v->next;
|
||||
v = v->next;
|
||||
if (!v) {
|
||||
v = alt;
|
||||
alt = NULL;
|
||||
}
|
||||
}
|
||||
if (!peer->authmethods)
|
||||
peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
|
||||
|
@ -8421,13 +8440,14 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
|
|||
}
|
||||
|
||||
/*! \brief Create in-memory user structure from configuration */
|
||||
static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly)
|
||||
static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
|
||||
{
|
||||
struct iax2_user *user = NULL;
|
||||
struct iax2_context *con, *conl = NULL;
|
||||
struct ast_ha *oldha = NULL;
|
||||
struct iax2_context *oldcon = NULL;
|
||||
int format;
|
||||
int firstpass=1;
|
||||
int oldcurauthreq = 0;
|
||||
char *varname = NULL, *varval = NULL;
|
||||
struct ast_variable *tmpvar = NULL;
|
||||
|
@ -8436,18 +8456,22 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
|
|||
if (!temponly) {
|
||||
AST_LIST_TRAVERSE(&users, user, entry) {
|
||||
if (!strcmp(user->name, name)) {
|
||||
if (!ast_test_flag(user, IAX_DELME))
|
||||
firstpass = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
user = NULL;
|
||||
|
||||
|
||||
if (user) {
|
||||
oldcurauthreq = user->curauthreq;
|
||||
oldha = user->ha;
|
||||
oldcon = user->contexts;
|
||||
user->ha = NULL;
|
||||
user->contexts = NULL;
|
||||
if (firstpass) {
|
||||
oldcurauthreq = user->curauthreq;
|
||||
oldha = user->ha;
|
||||
oldcon = user->contexts;
|
||||
user->ha = NULL;
|
||||
user->contexts = NULL;
|
||||
}
|
||||
/* Already in the list, remove it and it will be added back (or FREE'd) */
|
||||
AST_LIST_REMOVE(&users, user, entry);
|
||||
AST_LIST_UNLOCK(&users);
|
||||
|
@ -8455,22 +8479,30 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
|
|||
AST_LIST_UNLOCK(&users);
|
||||
/* This is going to memset'd to 0 in the next block */
|
||||
user = ast_calloc(sizeof(*user),1);
|
||||
if (ast_string_field_init(user, 32)) {
|
||||
free(user);
|
||||
user = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (user) {
|
||||
user->maxauthreq = maxauthreq;
|
||||
user->curauthreq = oldcurauthreq;
|
||||
user->prefs = prefs;
|
||||
user->capability = iax2_capability;
|
||||
user->encmethods = iax2_encryption;
|
||||
user->adsi = adsi;
|
||||
ast_string_field_set(user, name, name);
|
||||
ast_string_field_set(user, language, language);
|
||||
ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);
|
||||
if (firstpass) {
|
||||
ast_string_field_free_all(user);
|
||||
memset(user, 0, sizeof(struct iax2_user));
|
||||
if (ast_string_field_init(user, 32)) {
|
||||
free(user);
|
||||
user = NULL;
|
||||
}
|
||||
user->maxauthreq = maxauthreq;
|
||||
user->curauthreq = oldcurauthreq;
|
||||
user->prefs = prefs;
|
||||
user->capability = iax2_capability;
|
||||
user->encmethods = iax2_encryption;
|
||||
user->adsi = adsi;
|
||||
ast_string_field_set(user, name, name);
|
||||
ast_string_field_set(user, language, language);
|
||||
ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);
|
||||
}
|
||||
if (!v) {
|
||||
v = alt;
|
||||
alt = NULL;
|
||||
}
|
||||
while(v) {
|
||||
if (!strcasecmp(v->name, "context")) {
|
||||
con = build_context(v->value);
|
||||
|
@ -8550,6 +8582,12 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
|
|||
ast_string_field_set(user, cid_name, name2);
|
||||
ast_string_field_set(user, cid_num, num2);
|
||||
ast_set_flag(user, IAX_HASCALLERID);
|
||||
} else if (!strcasecmp(v->name, "fullname")) {
|
||||
ast_string_field_set(user, cid_name, v->value);
|
||||
ast_set_flag(user, IAX_HASCALLERID);
|
||||
} else if (!strcasecmp(v->name, "cid_number")) {
|
||||
ast_string_field_set(user, cid_num, v->value);
|
||||
ast_set_flag(user, IAX_HASCALLERID);
|
||||
} else if (!strcasecmp(v->name, "accountcode")) {
|
||||
ast_string_field_set(user, accountcode, v->value);
|
||||
} else if (!strcasecmp(v->name, "mohinterpret")) {
|
||||
|
@ -8576,6 +8614,10 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
|
|||
}/* else if (strcasecmp(v->name,"type")) */
|
||||
/* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
|
||||
v = v->next;
|
||||
if (!v) {
|
||||
v = alt;
|
||||
alt = NULL;
|
||||
}
|
||||
}
|
||||
if (!user->authmethods) {
|
||||
if (!ast_strlen_zero(user->secret)) {
|
||||
|
@ -8722,7 +8764,7 @@ static void set_timing(void)
|
|||
/*! \brief Load configuration */
|
||||
static int set_config(char *config_file, int reload)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
struct ast_config *cfg, *ucfg;
|
||||
int capability=iax2_capability;
|
||||
struct ast_variable *v;
|
||||
char *cat;
|
||||
|
@ -8975,13 +9017,71 @@ static int set_config(char *config_file, int reload)
|
|||
min_reg_expire = max_reg_expire;
|
||||
}
|
||||
iax2_capability = capability;
|
||||
|
||||
ucfg = ast_config_load("users.conf");
|
||||
if (ucfg) {
|
||||
struct ast_variable *gen;
|
||||
int genhasiax;
|
||||
int genregisteriax;
|
||||
char *hasiax, *registeriax;
|
||||
|
||||
genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
|
||||
genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
|
||||
gen = ast_variable_browse(ucfg, "general");
|
||||
cat = ast_category_browse(ucfg, NULL);
|
||||
while (cat) {
|
||||
if (strcasecmp(cat, "general")) {
|
||||
hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
|
||||
registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
|
||||
if (ast_true(hasiax) || (!hasiax && genhasiax)) {
|
||||
/* Start with general parameters, then specific parameters, user and peer */
|
||||
user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
|
||||
if (user) {
|
||||
AST_LIST_LOCK(&users);
|
||||
AST_LIST_INSERT_HEAD(&users, user, entry);
|
||||
AST_LIST_UNLOCK(&users);
|
||||
}
|
||||
peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
|
||||
if (peer) {
|
||||
AST_LIST_LOCK(&peers);
|
||||
AST_LIST_INSERT_HEAD(&peers, peer, entry);
|
||||
AST_LIST_UNLOCK(&peers);
|
||||
if (ast_test_flag(peer, IAX_DYNAMIC))
|
||||
reg_source_db(peer);
|
||||
}
|
||||
}
|
||||
if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
|
||||
char tmp[256];
|
||||
char *host = ast_variable_retrieve(ucfg, cat, "host");
|
||||
char *username = ast_variable_retrieve(ucfg, cat, "username");
|
||||
char *secret = ast_variable_retrieve(ucfg, cat, "secret");
|
||||
if (!host)
|
||||
host = ast_variable_retrieve(ucfg, "general", "host");
|
||||
if (!username)
|
||||
username = ast_variable_retrieve(ucfg, "general", "username");
|
||||
if (!secret)
|
||||
secret = ast_variable_retrieve(ucfg, "general", "secret");
|
||||
if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
|
||||
if (!ast_strlen_zero(secret))
|
||||
snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
|
||||
else
|
||||
snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
|
||||
iax2_register(tmp, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
cat = ast_category_browse(ucfg, cat);
|
||||
}
|
||||
ast_config_destroy(ucfg);
|
||||
}
|
||||
|
||||
cat = ast_category_browse(cfg, NULL);
|
||||
while(cat) {
|
||||
if (strcasecmp(cat, "general")) {
|
||||
utype = ast_variable_retrieve(cfg, cat, "type");
|
||||
if (utype) {
|
||||
if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
|
||||
user = build_user(cat, ast_variable_browse(cfg, cat), 0);
|
||||
user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
|
||||
if (user) {
|
||||
AST_LIST_LOCK(&users);
|
||||
AST_LIST_INSERT_HEAD(&users, user, entry);
|
||||
|
@ -8989,7 +9089,7 @@ static int set_config(char *config_file, int reload)
|
|||
}
|
||||
}
|
||||
if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
|
||||
peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
|
||||
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
|
||||
if (peer) {
|
||||
AST_LIST_LOCK(&peers);
|
||||
AST_LIST_INSERT_HEAD(&peers, peer, entry);
|
||||
|
|
|
@ -1365,7 +1365,7 @@ static void sip_dump_history(struct sip_pvt *dialog);
|
|||
|
||||
/*--- Device object handling */
|
||||
static struct sip_peer *temp_peer(const char *name);
|
||||
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime);
|
||||
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime);
|
||||
static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
|
||||
static int update_call_counter(struct sip_pvt *fup, int event);
|
||||
static void sip_destroy_peer(struct sip_peer *peer);
|
||||
|
@ -2357,7 +2357,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
|
|||
}
|
||||
|
||||
/* Peer found in realtime, now build it in memory */
|
||||
peer = build_peer(newpeername, var, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS));
|
||||
peer = build_peer(newpeername, var, NULL, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS));
|
||||
if (!peer) {
|
||||
ast_variables_destroy(var);
|
||||
return NULL;
|
||||
|
@ -15118,6 +15118,10 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int
|
|||
ast_copy_string(user->md5secret, v->value, sizeof(user->md5secret));
|
||||
} else if (!strcasecmp(v->name, "callerid")) {
|
||||
ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num));
|
||||
} else if (!strcasecmp(v->name, "fullname")) {
|
||||
ast_copy_string(user->cid_name, v->value, sizeof(user->cid_name));
|
||||
} else if (!strcasecmp(v->name, "cid_number")) {
|
||||
ast_copy_string(user->cid_num, v->value, sizeof(user->cid_num));
|
||||
} else if (!strcasecmp(v->name, "callgroup")) {
|
||||
user->callgroup = ast_get_group(v->value);
|
||||
} else if (!strcasecmp(v->name, "pickupgroup")) {
|
||||
|
@ -15243,12 +15247,13 @@ static struct sip_peer *temp_peer(const char *name)
|
|||
}
|
||||
|
||||
/*! \brief Build peer from configuration (file or realtime static/dynamic) */
|
||||
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime)
|
||||
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
|
||||
{
|
||||
struct sip_peer *peer = NULL;
|
||||
struct ast_ha *oldha = NULL;
|
||||
int obproxyfound=0;
|
||||
int found=0;
|
||||
int firstpass=1;
|
||||
int format=0; /* Ama flags */
|
||||
time_t regseconds = 0;
|
||||
char *varname = NULL, *varval = NULL;
|
||||
|
@ -15268,6 +15273,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
|
|||
if (peer) {
|
||||
/* Already in the list, remove it and it will be added back (or FREE'd) */
|
||||
found++;
|
||||
if (!(peer->objflags & ASTOBJ_FLAG_MARKED))
|
||||
firstpass = 0;
|
||||
} else {
|
||||
if (!(peer = ast_calloc(1, sizeof(*peer))))
|
||||
return NULL;
|
||||
|
@ -15279,11 +15286,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
|
|||
ASTOBJ_INIT(peer);
|
||||
}
|
||||
/* Note that our peer HAS had its reference count incrased */
|
||||
|
||||
peer->lastmsgssent = -1;
|
||||
oldha = peer->ha;
|
||||
peer->ha = NULL;
|
||||
set_peer_defaults(peer); /* Set peer defaults */
|
||||
if (firstpass) {
|
||||
peer->lastmsgssent = -1;
|
||||
oldha = peer->ha;
|
||||
peer->ha = NULL;
|
||||
set_peer_defaults(peer); /* Set peer defaults */
|
||||
}
|
||||
if (!found && name)
|
||||
ast_copy_string(peer->name, name, sizeof(peer->name));
|
||||
|
||||
|
@ -15293,7 +15301,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
|
|||
peer->chanvars = NULL;
|
||||
/* XXX should unregister ? */
|
||||
}
|
||||
for (; v; v = v->next) {
|
||||
for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
|
||||
if (handle_common_options(&peerflags[0], &mask[0], v))
|
||||
continue;
|
||||
if (realtime && !strcasecmp(v->name, "regseconds")) {
|
||||
|
@ -15313,6 +15321,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
|
|||
peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno);
|
||||
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, "fullname")) {
|
||||
ast_copy_string(peer->cid_name, v->value, sizeof(peer->cid_name));
|
||||
} else if (!strcasecmp(v->name, "cid_number")) {
|
||||
ast_copy_string(peer->cid_num, v->value, sizeof(peer->cid_num));
|
||||
} else if (!strcasecmp(v->name, "context")) {
|
||||
ast_copy_string(peer->context, v->value, sizeof(peer->context));
|
||||
} else if (!strcasecmp(v->name, "subscribecontext")) {
|
||||
|
@ -15501,7 +15513,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
|
|||
*/
|
||||
static int reload_config(enum channelreloadreason reason)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
struct ast_config *cfg, *ucfg;
|
||||
struct ast_variable *v;
|
||||
struct sip_peer *peer;
|
||||
struct sip_user *user;
|
||||
|
@ -15863,6 +15875,58 @@ static int reload_config(enum channelreloadreason reason)
|
|||
authl = add_realm_authentication(authl, v->value, v->lineno);
|
||||
}
|
||||
|
||||
ucfg = ast_config_load("users.conf");
|
||||
if (ucfg) {
|
||||
struct ast_variable *gen;
|
||||
int genhassip, genregistersip;
|
||||
char *hassip, *registersip;
|
||||
|
||||
genhassip = ast_true(ast_variable_retrieve(ucfg, "general", "hassip"));
|
||||
genregistersip = ast_true(ast_variable_retrieve(ucfg, "general", "registersip"));
|
||||
gen = ast_variable_browse(ucfg, "general");
|
||||
cat = ast_category_browse(ucfg, NULL);
|
||||
while (cat) {
|
||||
if (strcasecmp(cat, "general")) {
|
||||
hassip = ast_variable_retrieve(ucfg, cat, "hassip");
|
||||
registersip = ast_variable_retrieve(ucfg, cat, "registersip");
|
||||
if (ast_true(hassip) || (!hassip && genhassip)) {
|
||||
peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
|
||||
if (peer) {
|
||||
ASTOBJ_CONTAINER_LINK(&peerl,peer);
|
||||
ASTOBJ_UNREF(peer, sip_destroy_peer);
|
||||
peer_count++;
|
||||
}
|
||||
}
|
||||
if (ast_true(registersip) || (!registersip && genregistersip)) {
|
||||
char tmp[256];
|
||||
char *host = ast_variable_retrieve(ucfg, cat, "host");
|
||||
char *username = ast_variable_retrieve(ucfg, cat, "username");
|
||||
char *secret = ast_variable_retrieve(ucfg, cat, "secret");
|
||||
char *contact = ast_variable_retrieve(ucfg, cat, "contact");
|
||||
if (!host)
|
||||
host = ast_variable_retrieve(ucfg, "general", "host");
|
||||
if (!username)
|
||||
username = ast_variable_retrieve(ucfg, "general", "username");
|
||||
if (!secret)
|
||||
secret = ast_variable_retrieve(ucfg, "general", "secret");
|
||||
if (!contact)
|
||||
contact = "s";
|
||||
if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
|
||||
if (!ast_strlen_zero(secret))
|
||||
snprintf(tmp, sizeof(tmp), "%s:%s@%s/%s", username, secret, host, contact);
|
||||
else
|
||||
snprintf(tmp, sizeof(tmp), "%s@%s/%s", username, host, contact);
|
||||
if (sip_register(tmp, 0) == 0)
|
||||
registry_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
cat = ast_category_browse(ucfg, cat);
|
||||
}
|
||||
ast_config_destroy(ucfg);
|
||||
}
|
||||
|
||||
|
||||
/* Load peers, users and friends */
|
||||
cat = NULL;
|
||||
while ( (cat = ast_category_browse(cfg, cat)) ) {
|
||||
|
@ -15894,7 +15958,7 @@ static int reload_config(enum channelreloadreason reason)
|
|||
}
|
||||
}
|
||||
if (is_peer) {
|
||||
peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
|
||||
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
|
||||
if (peer) {
|
||||
ASTOBJ_CONTAINER_LINK(&peerl,peer);
|
||||
ASTOBJ_UNREF(peer, sip_destroy_peer);
|
||||
|
|
|
@ -219,6 +219,7 @@ static int use_callerid = 1;
|
|||
static int cid_signalling = CID_SIG_BELL;
|
||||
static int cid_start = CID_START_RING;
|
||||
static int zaptrcallerid = 0;
|
||||
static int cur_radio = 0;
|
||||
static int cur_signalling = -1;
|
||||
static int cur_outsignalling = -1;
|
||||
|
||||
|
@ -10282,202 +10283,115 @@ static int unload_module(void)
|
|||
#endif
|
||||
return __unload_module();
|
||||
}
|
||||
|
||||
static int setup_zap(int reload)
|
||||
|
||||
static int build_channels(int iscrv, char *value, int reload, int lineno, int *found_pseudo)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *v;
|
||||
struct ast_variable *vjb;
|
||||
char *c, *chan;
|
||||
int x, y, start, finish;
|
||||
struct zt_pvt *tmp;
|
||||
char *chan;
|
||||
char *c;
|
||||
char *ringc;
|
||||
int start, finish,x;
|
||||
int y;
|
||||
int found_pseudo = 0;
|
||||
int cur_radio = 0;
|
||||
#ifdef HAVE_PRI
|
||||
int spanno;
|
||||
int i;
|
||||
int logicalspan;
|
||||
int trunkgroup;
|
||||
int dchannels[NUM_DCHANS];
|
||||
struct zt_pri *pri;
|
||||
int trunkgroup;
|
||||
#endif
|
||||
|
||||
cfg = ast_config_load(config);
|
||||
|
||||
/* Error if we have no config file */
|
||||
if (!cfg) {
|
||||
ast_log(LOG_ERROR, "Unable to load config %s\n", config);
|
||||
return 0;
|
||||
|
||||
if ((reload == 0) && (cur_signalling < 0)) {
|
||||
ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* It's a little silly to lock it, but we mind as well just to be sure */
|
||||
ast_mutex_lock(&iflock);
|
||||
c = value;
|
||||
|
||||
#ifdef HAVE_PRI
|
||||
if (!reload) {
|
||||
/* Process trunkgroups first */
|
||||
v = ast_variable_browse(cfg, "trunkgroups");
|
||||
while (v) {
|
||||
if (!strcasecmp(v->name, "trunkgroup")) {
|
||||
trunkgroup = atoi(v->value);
|
||||
if (trunkgroup > 0) {
|
||||
if ((c = strchr(v->value, ','))) {
|
||||
i = 0;
|
||||
memset(dchannels, 0, sizeof(dchannels));
|
||||
while (c && (i < NUM_DCHANS)) {
|
||||
dchannels[i] = atoi(c + 1);
|
||||
if (dchannels[i] < 0) {
|
||||
ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno);
|
||||
} else
|
||||
i++;
|
||||
c = strchr(c + 1, ',');
|
||||
}
|
||||
if (i) {
|
||||
if (pri_create_trunkgroup(trunkgroup, dchannels)) {
|
||||
ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno);
|
||||
} else if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
|
||||
} else if (!strcasecmp(v->name, "spanmap")) {
|
||||
spanno = atoi(v->value);
|
||||
if (spanno > 0) {
|
||||
if ((c = strchr(v->value, ','))) {
|
||||
trunkgroup = atoi(c + 1);
|
||||
if (trunkgroup > 0) {
|
||||
if ((c = strchr(c + 1, ',')))
|
||||
logicalspan = atoi(c + 1);
|
||||
else
|
||||
logicalspan = 0;
|
||||
if (logicalspan >= 0) {
|
||||
if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
|
||||
ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
|
||||
} else if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
|
||||
pri = NULL;
|
||||
if (iscrv) {
|
||||
if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
|
||||
ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
|
||||
return -1;
|
||||
}
|
||||
if (trunkgroup < 1) {
|
||||
ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
|
||||
return -1;
|
||||
}
|
||||
c += y;
|
||||
for (y = 0; y < NUM_SPANS; y++) {
|
||||
if (pris[y].trunkgroup == trunkgroup) {
|
||||
pri = pris + y;
|
||||
break;
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
if (!pri) {
|
||||
ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while ((chan = strsep(&c, ","))) {
|
||||
if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
|
||||
/* Range */
|
||||
} else if (sscanf(chan, "%d", &start)) {
|
||||
/* Just one */
|
||||
finish = start;
|
||||
} else if (!strcasecmp(chan, "pseudo")) {
|
||||
finish = start = CHAN_PSEUDO;
|
||||
if (found_pseudo)
|
||||
*found_pseudo = 1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
|
||||
return -1;
|
||||
}
|
||||
if (finish < start) {
|
||||
ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
|
||||
x = finish;
|
||||
finish = start;
|
||||
start = x;
|
||||
}
|
||||
|
||||
for (x = start; x <= finish; x++) {
|
||||
#ifdef HAVE_PRI
|
||||
tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, pri, reload);
|
||||
#else
|
||||
tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, NULL, reload);
|
||||
#endif
|
||||
|
||||
if (tmp) {
|
||||
if (option_verbose > 2) {
|
||||
#ifdef HAVE_PRI
|
||||
if (pri)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
|
||||
else
|
||||
#endif
|
||||
v = ast_variable_browse(cfg, "channels");
|
||||
/* Copy the default jb config over global_jbconf */
|
||||
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
|
||||
/* Traverse all variables to handle jb conf */
|
||||
for (vjb = v; vjb; vjb = vjb->next)
|
||||
ast_jb_read_conf(&global_jbconf, vjb->name, vjb->value);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
|
||||
(reload == 1) ? "reconfigure" : "register", value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_zap(struct ast_variable *v, int reload, int skipchannels)
|
||||
{
|
||||
struct zt_pvt *tmp;
|
||||
char *ringc;
|
||||
int y;
|
||||
int found_pseudo = 0;
|
||||
char *c;
|
||||
|
||||
while(v) {
|
||||
/* Create the interface list */
|
||||
if (!strcasecmp(v->name, "channel")
|
||||
#ifdef HAVE_PRI
|
||||
|| !strcasecmp(v->name, "crv")
|
||||
|| !strcasecmp(v->name, "crv")
|
||||
#endif
|
||||
) {
|
||||
if (reload == 0) {
|
||||
if (cur_signalling < 0) {
|
||||
ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
) {
|
||||
if (!skipchannels) {
|
||||
if (build_channels(!strcasecmp(v->name, "crv"), v->value, reload, v->lineno, &found_pseudo))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
c = v->value;
|
||||
|
||||
#ifdef HAVE_PRI
|
||||
pri = NULL;
|
||||
if (!strcasecmp(v->name, "crv")) {
|
||||
if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
|
||||
ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", v->lineno);
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
if (trunkgroup < 1) {
|
||||
ast_log(LOG_WARNING, "CRV trunk group must be a postive number at line %d\n", v->lineno);
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
c += y;
|
||||
for (y = 0; y < NUM_SPANS; y++) {
|
||||
if (pris[y].trunkgroup == trunkgroup) {
|
||||
pri = pris + y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pri) {
|
||||
ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, v->lineno);
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
chan = strsep(&c, ",");
|
||||
while (chan) {
|
||||
if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
|
||||
/* Range */
|
||||
} else if (sscanf(chan, "%d", &start)) {
|
||||
/* Just one */
|
||||
finish = start;
|
||||
} else if (!strcasecmp(chan, "pseudo")) {
|
||||
finish = start = CHAN_PSEUDO;
|
||||
found_pseudo = 1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", v->value, chan);
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
if (finish < start) {
|
||||
ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
|
||||
x = finish;
|
||||
finish = start;
|
||||
start = x;
|
||||
}
|
||||
|
||||
for (x = start; x <= finish; x++) {
|
||||
#ifdef HAVE_PRI
|
||||
tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, pri, reload);
|
||||
#else
|
||||
tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, NULL, reload);
|
||||
#endif
|
||||
|
||||
if (tmp) {
|
||||
if (option_verbose > 2) {
|
||||
#ifdef HAVE_PRI
|
||||
if (pri)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup,x, sig2str(tmp->sig));
|
||||
else
|
||||
#endif
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
|
||||
}
|
||||
} else {
|
||||
if (reload == 1)
|
||||
ast_log(LOG_ERROR, "Unable to reconfigure channel '%s'\n", v->value);
|
||||
else
|
||||
ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
chan = strsep(&c, ",");
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
|
||||
if (ast_true(v->value))
|
||||
|
@ -10645,7 +10559,11 @@ static int setup_zap(int reload)
|
|||
cid_name[0] = '\0';
|
||||
} else {
|
||||
ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
|
||||
}
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "fullname")) {
|
||||
ast_copy_string(cid_name, v->value, sizeof(cid_name));
|
||||
} else if (!strcasecmp(v->name, "cid_number")) {
|
||||
ast_copy_string(cid_num, v->value, sizeof(cid_num));
|
||||
} else if (!strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
|
||||
zaptrcallerid = ast_true(v->value);
|
||||
} else if (!strcasecmp(v->name, "restrictcid")) {
|
||||
|
@ -10870,8 +10788,6 @@ static int setup_zap(int reload)
|
|||
switchtype = PRI_SWITCH_QSIG;
|
||||
else {
|
||||
ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
|
||||
ast_config_destroy(cfg);
|
||||
ast_mutex_unlock(&iflock);
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcasecmp(v->name, "nsf")) {
|
||||
|
@ -11084,12 +11000,11 @@ static int setup_zap(int reload)
|
|||
} else if (!strcasecmp(v->name, "defaultozz")) {
|
||||
ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
|
||||
}
|
||||
} else
|
||||
} else if (!skipchannels)
|
||||
ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
|
||||
v = v->next;
|
||||
}
|
||||
if (!found_pseudo && reload == 0) {
|
||||
|
||||
/* Make sure pseudo isn't a member of any groups if
|
||||
we're automatically making it. */
|
||||
cur_group = 0;
|
||||
|
@ -11105,8 +11020,123 @@ static int setup_zap(int reload)
|
|||
ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_zap(int reload)
|
||||
{
|
||||
int x;
|
||||
struct ast_config *cfg;
|
||||
struct ast_variable *v;
|
||||
struct ast_variable *vjb;
|
||||
char *c;
|
||||
int res;
|
||||
|
||||
#ifdef HAVE_PRI
|
||||
int spanno;
|
||||
int i;
|
||||
int logicalspan;
|
||||
int trunkgroup;
|
||||
int dchannels[NUM_DCHANS];
|
||||
#endif
|
||||
|
||||
cfg = ast_config_load(config);
|
||||
|
||||
/* Error if we have no config file */
|
||||
if (!cfg) {
|
||||
ast_log(LOG_ERROR, "Unable to load config %s\n", config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* It's a little silly to lock it, but we mind as well just to be sure */
|
||||
ast_mutex_lock(&iflock);
|
||||
#ifdef HAVE_PRI
|
||||
if (!reload) {
|
||||
/* Process trunkgroups first */
|
||||
v = ast_variable_browse(cfg, "trunkgroups");
|
||||
while (v) {
|
||||
if (!strcasecmp(v->name, "trunkgroup")) {
|
||||
trunkgroup = atoi(v->value);
|
||||
if (trunkgroup > 0) {
|
||||
if ((c = strchr(v->value, ','))) {
|
||||
i = 0;
|
||||
memset(dchannels, 0, sizeof(dchannels));
|
||||
while (c && (i < NUM_DCHANS)) {
|
||||
dchannels[i] = atoi(c + 1);
|
||||
if (dchannels[i] < 0) {
|
||||
ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno);
|
||||
} else
|
||||
i++;
|
||||
c = strchr(c + 1, ',');
|
||||
}
|
||||
if (i) {
|
||||
if (pri_create_trunkgroup(trunkgroup, dchannels)) {
|
||||
ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno);
|
||||
} else if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno);
|
||||
} else if (!strcasecmp(v->name, "spanmap")) {
|
||||
spanno = atoi(v->value);
|
||||
if (spanno > 0) {
|
||||
if ((c = strchr(v->value, ','))) {
|
||||
trunkgroup = atoi(c + 1);
|
||||
if (trunkgroup > 0) {
|
||||
if ((c = strchr(c + 1, ',')))
|
||||
logicalspan = atoi(c + 1);
|
||||
else
|
||||
logicalspan = 0;
|
||||
if (logicalspan >= 0) {
|
||||
if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
|
||||
ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
|
||||
} else if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno);
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
v = ast_variable_browse(cfg, "channels");
|
||||
/* Copy the default jb config over global_jbconf */
|
||||
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
|
||||
/* Traverse all variables to handle jb conf */
|
||||
for (vjb = v; vjb; vjb = vjb->next)
|
||||
ast_jb_read_conf(&global_jbconf, vjb->name, vjb->value);
|
||||
res = process_zap(v, reload, 0);
|
||||
ast_mutex_unlock(&iflock);
|
||||
ast_config_destroy(cfg);
|
||||
if (res)
|
||||
return res;
|
||||
cfg = ast_config_load("users.conf");
|
||||
if (cfg) {
|
||||
char *cat;
|
||||
char *chans;
|
||||
process_zap(ast_variable_browse(cfg, "general"), 1, 1);
|
||||
for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
|
||||
if (!strcasecmp(cat, "general"))
|
||||
continue;
|
||||
chans = ast_variable_retrieve(cfg, cat, "zapchan");
|
||||
if (!ast_strlen_zero(chans)) {
|
||||
process_zap(ast_variable_browse(cfg, cat), 1, 1);
|
||||
build_channels(0, chans, 1, 0, NULL);
|
||||
}
|
||||
}
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
#ifdef HAVE_PRI
|
||||
if (!reload) {
|
||||
for (x = 0; x < NUM_SPANS; x++) {
|
||||
|
|
|
@ -53,6 +53,11 @@ clearglobalvars=no
|
|||
;
|
||||
;priorityjumping=yes
|
||||
;
|
||||
; User context is where entries from users.conf are registered. The
|
||||
; default value is 'default'
|
||||
;
|
||||
;userscontext=default
|
||||
;
|
||||
; You can include other config files, use the #include command
|
||||
; (without the ';'). Note that this is different from the "include" command
|
||||
; that includes contexts within other contexts. The #include command works
|
||||
|
@ -316,6 +321,18 @@ include => parkedcalls
|
|||
;
|
||||
; eswitch => IAX2/context@${CURSERVER}
|
||||
|
||||
[macro-trunkdial]
|
||||
;
|
||||
; Standard trunk dial macro (hangs up on a dialstatus that should
|
||||
; terminate call)
|
||||
; ${ARG1} - What to dial
|
||||
;
|
||||
exten => s,1,Dial(${ARG1})
|
||||
exten => s,n,Goto(s-${DIALSTATUS},1)
|
||||
exten => s-NOANSWER,1,Hangup
|
||||
exten => s-BUSY,1,Hangup
|
||||
exten => _s-.,1,NoOp
|
||||
|
||||
[macro-stdexten];
|
||||
;
|
||||
; Standard extension macro:
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
;
|
||||
; User configuration
|
||||
;
|
||||
; Creating entries in users.conf is a "shorthand" for creating individual
|
||||
; entries in each configuration file. Using users.conf is not intended to
|
||||
; provide you with as much flexibility as using the separate configuration
|
||||
; files (e.g. sip.conf, iax.conf, etc) but is intended to accelerate the
|
||||
; simple task of adding users. Note that creating individual items (e.g.
|
||||
; custom SIP peers, IAX friends, etc.) will allow you to override specific
|
||||
; parameters within this file.
|
||||
;
|
||||
|
||||
[general]
|
||||
fullname = New User
|
||||
userbase = 6000
|
||||
hasvoicemail = yes
|
||||
hassip = yes
|
||||
hasiax = yes
|
||||
hasmanager = no
|
||||
callwaiting = yes
|
||||
threewaycalling = yes
|
||||
callwaitingcallerid = yes
|
||||
transfer = yes
|
||||
canpark = yes
|
||||
cancallforward = yes
|
||||
callreturn = yes
|
||||
callgroup = 1
|
||||
pickupgroup = 1
|
||||
|
||||
|
||||
;[6000]
|
||||
;fullname = Joe User
|
||||
;email = joe@foo.bar
|
||||
;secret = 1234
|
||||
;zapchan = 1
|
||||
;hasvoicemail = yes
|
||||
;hassip = yes
|
||||
;hasiax = no
|
||||
;hasmanager = no
|
||||
;callwaiting = no
|
||||
;context = international
|
|
@ -49,7 +49,12 @@ maxsilence=10
|
|||
silencethreshold=128
|
||||
; Max number of failed login attempts
|
||||
maxlogins=3
|
||||
|
||||
;
|
||||
; User context is where entries from users.conf are registered. The
|
||||
; default value is 'default'
|
||||
;
|
||||
;userscontext=default
|
||||
;
|
||||
; If you need to have an external program, i.e. /usr/bin/myapp
|
||||
; called when a voicemail is left, delivered, or your voicemailbox
|
||||
; is checked, uncomment this. It can also be set to 'smdi' to use
|
||||
|
|
|
@ -172,6 +172,7 @@ int read_config_maps(void);
|
|||
struct ast_config *ast_config_new(void);
|
||||
struct ast_category *ast_config_get_current_category(const struct ast_config *cfg);
|
||||
void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat);
|
||||
char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var);
|
||||
|
||||
struct ast_category *ast_category_new(const char *name);
|
||||
void ast_category_append(struct ast_config *config, struct ast_category *cat);
|
||||
|
|
|
@ -174,6 +174,7 @@ int pbx_exec(struct ast_channel *c, struct ast_app *app, void *data);
|
|||
* \return NULL on failure, and an ast_context structure on success
|
||||
*/
|
||||
struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar);
|
||||
struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar);
|
||||
|
||||
/*!
|
||||
* \brief Merge the temporary contexts into a global contexts list and delete from the
|
||||
|
|
|
@ -649,10 +649,14 @@ int ast_safe_system(const char *s)
|
|||
struct rusage rusage;
|
||||
int status;
|
||||
|
||||
#if HAVE_WORKING_FORK
|
||||
ast_replace_sigchld();
|
||||
#if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
|
||||
ast_replace_sigchld();
|
||||
|
||||
#ifdef HAVE_WORKING_VFORK
|
||||
pid = vfork();
|
||||
#else
|
||||
pid = fork();
|
||||
#endif
|
||||
|
||||
if (pid == 0) {
|
||||
if (ast_opt_high_priority)
|
||||
|
|
|
@ -147,6 +147,16 @@ struct ast_variable *ast_variable_browse(const struct ast_config *config, const
|
|||
return (cat) ? cat->root : NULL;
|
||||
}
|
||||
|
||||
char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = ast_variable_retrieve(cfg, cat, var);
|
||||
if (!tmp)
|
||||
tmp = ast_variable_retrieve(cfg, "general", var);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
|
||||
{
|
||||
struct ast_variable *v;
|
||||
|
|
|
@ -947,6 +947,7 @@ static char mandescr_updateconfig[] =
|
|||
"Variables (X's represent 6 digit number beginning with 000000):\n"
|
||||
" SrcFilename: Configuration filename to read(e.g. foo.conf)\n"
|
||||
" DstFilename: Configuration filename to write(e.g. foo.conf)\n"
|
||||
" Reload: Whether or not a reload should take place (or name of specific module)\n"
|
||||
" Action-XXXXXX: Action to Take (NewCat,RenameCat,DelCat,Update,Delete,Append)\n"
|
||||
" Cat-XXXXXX: Category to operate on\n"
|
||||
" Var-XXXXXX: Variable to work on\n"
|
||||
|
@ -961,6 +962,7 @@ static int action_updateconfig(struct mansession *s, struct message *m)
|
|||
int res;
|
||||
char idText[256] = "";
|
||||
char *id = astman_get_header(m, "ActionID");
|
||||
char *rld = astman_get_header(m, "Reload");
|
||||
|
||||
if (!ast_strlen_zero(id))
|
||||
snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
|
||||
|
@ -981,6 +983,11 @@ static int action_updateconfig(struct mansession *s, struct message *m)
|
|||
return 0;
|
||||
}
|
||||
astman_append(s, "Response: Success\r\n%s\r\n", idText);
|
||||
if (!ast_strlen_zero(rld)) {
|
||||
if (ast_true(rld))
|
||||
rld = NULL;
|
||||
ast_module_reload(rld);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
18
main/pbx.c
18
main/pbx.c
|
@ -3491,7 +3491,7 @@ int ast_unregister_application(const char *app)
|
|||
return tmp ? 0 : -1;
|
||||
}
|
||||
|
||||
struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
|
||||
static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
|
||||
{
|
||||
struct ast_context *tmp, **local_contexts;
|
||||
int length = sizeof(struct ast_context) + strlen(name) + 1;
|
||||
|
@ -3504,10 +3504,13 @@ struct ast_context *ast_context_create(struct ast_context **extcontexts, const c
|
|||
|
||||
for (tmp = *local_contexts; tmp; tmp = tmp->next) {
|
||||
if (!strcasecmp(tmp->name, name)) {
|
||||
ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
|
||||
if (!existsokay) {
|
||||
ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
|
||||
tmp = NULL;
|
||||
}
|
||||
if (!extcontexts)
|
||||
ast_mutex_unlock(&conlock);
|
||||
return NULL;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
if ((tmp = ast_calloc(1, length))) {
|
||||
|
@ -3531,6 +3534,15 @@ struct ast_context *ast_context_create(struct ast_context **extcontexts, const c
|
|||
return tmp;
|
||||
}
|
||||
|
||||
struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
|
||||
{
|
||||
return __ast_context_create(extcontexts, name, registrar, 0);
|
||||
}
|
||||
|
||||
struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
|
||||
{
|
||||
return __ast_context_create(extcontexts, name, registrar, 1);
|
||||
}
|
||||
void __ast_context_destroy(struct ast_context *con, const char *registrar);
|
||||
|
||||
struct store_hint {
|
||||
|
|
106
pbx/pbx_config.c
106
pbx/pbx_config.c
|
@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
|
||||
static char *config = "extensions.conf";
|
||||
static char *registrar = "pbx_config";
|
||||
static char userscontext[AST_MAX_EXTENSION] = "default";
|
||||
|
||||
static int static_config = 0;
|
||||
static int write_protect_config = 1;
|
||||
|
@ -1357,6 +1358,11 @@ static int pbx_load_config(const char *config_file)
|
|||
autofallthrough_config = ast_true(ast_variable_retrieve(cfg, "general", "autofallthrough"));
|
||||
clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
|
||||
ast_set2_flag(&ast_options, ast_true(ast_variable_retrieve(cfg, "general", "priorityjumping")), AST_OPT_FLAG_PRIORITY_JUMPING);
|
||||
|
||||
if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
|
||||
ast_copy_string(userscontext, cxt, sizeof(userscontext));
|
||||
else
|
||||
ast_copy_string(userscontext, "default", sizeof(userscontext));
|
||||
|
||||
for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) {
|
||||
memset(realvalue, 0, sizeof(realvalue));
|
||||
|
@ -1364,11 +1370,10 @@ static int pbx_load_config(const char *config_file)
|
|||
pbx_builtin_setvar_helper(NULL, v->name, realvalue);
|
||||
}
|
||||
for (cxt = NULL; (cxt = ast_category_browse(cfg, cxt)); ) {
|
||||
|
||||
/* All categories but "general" or "globals" are considered contexts */
|
||||
if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals"))
|
||||
continue;
|
||||
con=ast_context_create(&local_contexts,cxt, registrar);
|
||||
con=ast_context_find_or_create(&local_contexts,cxt, registrar);
|
||||
if (con == NULL)
|
||||
continue;
|
||||
|
||||
|
@ -1494,12 +1499,109 @@ static int pbx_load_config(const char *config_file)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void append_interface(char *iface, int maxlen, char *add)
|
||||
{
|
||||
int len = strlen(iface);
|
||||
if (strlen(add) + len < maxlen - 2) {
|
||||
if (strlen(iface)) {
|
||||
iface[len] = '&';
|
||||
strcpy(iface + len + 1, add);
|
||||
} else
|
||||
strcpy(iface, add);
|
||||
}
|
||||
}
|
||||
|
||||
static void pbx_load_users(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *cat, *chan;
|
||||
char *zapchan;
|
||||
char *hasexten;
|
||||
char tmp[256];
|
||||
char iface[256];
|
||||
char zapcopy[256];
|
||||
char *c;
|
||||
int len;
|
||||
int hasvoicemail;
|
||||
int start, finish, x;
|
||||
struct ast_context *con;
|
||||
|
||||
cfg = ast_config_load("users.conf");
|
||||
if (!cfg)
|
||||
return;
|
||||
con = ast_context_find_or_create(&local_contexts, userscontext, registrar);
|
||||
if (!con)
|
||||
return;
|
||||
|
||||
for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
|
||||
if (!strcasecmp(cat, "general"))
|
||||
continue;
|
||||
iface[0] = '\0';
|
||||
len = sizeof(iface);
|
||||
if (ast_true(ast_config_option(cfg, cat, "hassip"))) {
|
||||
snprintf(tmp, sizeof(tmp), "SIP/%s", cat);
|
||||
append_interface(iface, sizeof(iface), tmp);
|
||||
}
|
||||
if (ast_true(ast_config_option(cfg, cat, "hasiax"))) {
|
||||
snprintf(tmp, sizeof(tmp), "IAX/%s", cat);
|
||||
append_interface(iface, sizeof(iface), tmp);
|
||||
}
|
||||
hasexten = ast_config_option(cfg, cat, "hasexten");
|
||||
if (hasexten && !ast_true(hasexten))
|
||||
continue;
|
||||
hasvoicemail = ast_true(ast_config_option(cfg, cat, "hasvoicemail"));
|
||||
zapchan = ast_variable_retrieve(cfg, cat, "zapchan");
|
||||
if (!zapchan)
|
||||
zapchan = ast_variable_retrieve(cfg, "general", "zapchan");
|
||||
if (!ast_strlen_zero(zapchan)) {
|
||||
ast_copy_string(zapcopy, zapchan, sizeof(zapcopy));
|
||||
c = zapcopy;
|
||||
chan = strsep(&c, ",");
|
||||
while (chan) {
|
||||
if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
|
||||
/* Range */
|
||||
} else if (sscanf(chan, "%d", &start)) {
|
||||
/* Just one */
|
||||
finish = start;
|
||||
} else {
|
||||
start = 0; finish = 0;
|
||||
}
|
||||
if (finish < start) {
|
||||
x = finish;
|
||||
finish = start;
|
||||
start = x;
|
||||
}
|
||||
for (x = start; x <= finish; x++) {
|
||||
snprintf(tmp, sizeof(tmp), "Zap/%d", x);
|
||||
append_interface(iface, sizeof(iface), tmp);
|
||||
}
|
||||
chan = strsep(&c, ",");
|
||||
}
|
||||
}
|
||||
if (!ast_strlen_zero(iface)) {
|
||||
/* Add hint */
|
||||
ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, strdup(""), ast_free, registrar);
|
||||
/* If voicemail, use "stdexten" else use plain old dial */
|
||||
if (hasvoicemail) {
|
||||
snprintf(tmp, sizeof(tmp), "stdexten|%s|${HINT}", cat);
|
||||
ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Macro", strdup(tmp), ast_free, registrar);
|
||||
} else {
|
||||
ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Dial", strdup("${HINT}"), ast_free, registrar);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
|
||||
static int pbx_load_module(void)
|
||||
{
|
||||
struct ast_context *con;
|
||||
|
||||
if(!pbx_load_config(config))
|
||||
return AST_MODULE_LOAD_DECLINE;
|
||||
|
||||
pbx_load_users();
|
||||
|
||||
ast_merge_contexts_and_delete(&local_contexts, registrar);
|
||||
|
||||
for (con = NULL; (con = ast_walk_contexts(con));)
|
||||
|
|
Reference in New Issue