Sun Mar 9 07:00:01 CET 2003

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@636 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Matteo Brancaleoni 22 years ago
parent d50ea0e9d4
commit 32b4c314f9

@ -1,3 +1,4 @@
-- Add NAT and dynamic support to MGCP
-- Allow selection of in-band, out-of-band, or INFO based DTMF
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
-- Add "NAT" option to sip user, peer, friend

@ -830,7 +830,7 @@ static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short
static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new)
{
int res = -1;
int res = 0;
int x;
int start;
if (new <= NEW_ALLOW) {
@ -852,7 +852,7 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
for (x = ((nextcallno + 1) % (AST_IAX2_MAX_CALLS - 1)) + 1; iaxs[x] && (x != start); x = (x + 1) % AST_IAX2_MAX_CALLS)
if (x == start) {
ast_log(LOG_WARNING, "Unable to accept more calls\n");
return -1;
return 0;
}
ast_pthread_mutex_lock(&iaxsl[x]);
iaxs[x] = new_iax();
@ -873,7 +873,7 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
strncpy(iaxs[x]->accountcode, accountcode, sizeof(iaxs[x]->accountcode)-1);
} else {
ast_log(LOG_WARNING, "Out of resources\n");
return -1;
return 0;
}
res = x;
nextcallno = x;
@ -4270,7 +4270,7 @@ static int iax2_do_register(struct iax2_registry *reg)
if (option_debug)
ast_log(LOG_DEBUG, "Allocate call number\n");
reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE);
if (reg->callno < 0) {
if (reg->callno < 1) {
ast_log(LOG_WARNING, "Unable to create call for registration\n");
return -1;
} else if (option_debug)
@ -4322,7 +4322,7 @@ static int iax2_poke_peer(struct iax2_peer *peer)
iax2_destroy(peer->callno);
}
peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE);
if (peer->callno < 0) {
if (peer->callno < 1) {
ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
return -1;
}
@ -4374,7 +4374,7 @@ static struct ast_channel *iax2_request(char *type, int format, void *data)
return NULL;
}
callno = find_callno(0, 0, &sin, NEW_FORCE);
if (callno < 0) {
if (callno < 1) {
ast_log(LOG_WARNING, "Unable to create call\n");
return NULL;
}

@ -75,6 +75,8 @@ static char ourhost[256];
static struct in_addr __ourip;
static int ourport;
static int mgcpdebug = 0;
static struct sched_context *sched;
static struct io_context *io;
/* The private structures of the mgcp channels are linked for
@ -141,7 +143,10 @@ struct mgcp_gateway {
/* A gateway containing one or more endpoints */
char name[80];
struct sockaddr_in addr;
struct sockaddr_in defaddr;
struct in_addr ourip;
int dynamic;
int expire; /* XXX Should we ever expire dynamic registrations? XXX */
struct mgcp_endpoint *endpoints;
struct ast_ha *ha;
struct mgcp_gateway *next;
@ -162,7 +167,10 @@ static int transmit_notify_request_with_callerid(struct mgcp_endpoint *p, char *
static int __mgcp_xmit(struct mgcp_endpoint *p, char *data, int len)
{
int res;
res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->addr, sizeof(struct sockaddr_in));
if (p->parent->addr.sin_addr.s_addr)
res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->addr, sizeof(struct sockaddr_in));
else
res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->defaddr, sizeof(struct sockaddr_in));
if (res != len) {
ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
}
@ -172,7 +180,8 @@ static int __mgcp_xmit(struct mgcp_endpoint *p, char *data, int len)
static int send_response(struct mgcp_endpoint *p, struct mgcp_request *req)
{
int res;
printf("Transmitting:\n%s\n to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
if (mgcpdebug)
ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
res = __mgcp_xmit(p, req->data, req->len);
if (res > 0)
res = 0;
@ -182,7 +191,8 @@ static int send_response(struct mgcp_endpoint *p, struct mgcp_request *req)
static int send_request(struct mgcp_endpoint *p, struct mgcp_request *req)
{
int res;
printf("XXX Need to handle Retransmitting XXX:\n%s to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
if (mgcpdebug)
ast_verbose("XXX Need to handle Retransmitting XXX:\n%s to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
res = __mgcp_xmit(p, req->data, req->len);
return res;
}
@ -291,9 +301,11 @@ static struct in_addr *myaddrfor(struct in_addr *them)
#endif
if (((remote_ip & mask) ^ dest) == 0) {
printf("Interface is %s\n",iface);
if (mgcpdebug)
ast_verbose("Interface is %s\n",iface);
temp = lookup_iface(iface);
printf("IP Address is %s\n",inet_ntoa(*temp));
if (mgcpdebug)
ast_verbose("IP Address is %s\n",inet_ntoa(*temp));
break;
}
}
@ -349,7 +361,7 @@ static int mgcp_show_endpoints(int fd, int argc, char *argv[])
g = gateways;
while(g) {
e = g->endpoints;
ast_cli(fd, "Gateway '%s' at %s\n", g->name, inet_ntoa(g->addr.sin_addr));
ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? inet_ntoa(g->addr.sin_addr) : inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
while(e) {
ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->owner ? "active" : "idle");
hasendpoints = 1;
@ -634,8 +646,18 @@ static struct mgcp_endpoint *find_endpoint(char *name, int msgid, struct sockadd
ast_pthread_mutex_lock(&gatelock);
g = gateways;
while(g) {
if (!name || !strcasecmp(g->name, at)) {
/* Found the gateway -- now for the endpoint */
if ((!name || !strcasecmp(g->name, at)) &&
(sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
/* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
if (sin && g->dynamic) {
if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
(g->addr.sin_port != sin->sin_port)) {
memcpy(&g->addr, sin, sizeof(g->addr));
memcpy(&g->ourip, myaddrfor(&g->addr.sin_addr), sizeof(g->ourip));
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
}
}
p = g->endpoints;
while(p) {
if ((name && !strcasecmp(p->name, tmp)) ||
@ -753,9 +775,11 @@ static void parse(struct mgcp_request *req)
}
}
printf("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
if (mgcpdebug) {
ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
req->verb, req->identifier, req->endpoint, req->version);
printf("%d headers, %d lines\n", req->headers, req->lines);
ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
}
if (*c)
ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
}
@ -817,7 +841,8 @@ static int process_sdp(struct mgcp_endpoint *p, struct mgcp_request *req)
codecs += len;
}
p->capability = capability & peercapability;
printf("Capabilities: us - %d, them - %d, combined - %d\n",
if (mgcpdebug)
ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
capability, peercapability, p->capability);
if (!p->capability) {
ast_log(LOG_WARNING, "No compatible codecs!\n");
@ -966,7 +991,8 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_endpoint *p, struct as
dest.sin_port = sin.sin_port;
}
}
printf("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
if (mgcpdebug)
ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
snprintf(v, sizeof(v), "v=0\r\n");
snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
snprintf(s, sizeof(s), "s=session\r\n");
@ -975,7 +1001,8 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_endpoint *p, struct as
snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
if (p->capability & x) {
printf("Answering with capability %d\n", x);
if (mgcpdebug)
ast_verbose("Answering with capability %d\n", x);
if ((codec = ast2rtp(x)) > -1) {
snprintf(costr, sizeof(costr), " %d", codec);
strcat(m, costr);
@ -1192,7 +1219,8 @@ static int handle_request(struct mgcp_endpoint *p, struct mgcp_request *req, str
struct ast_channel *c;
pthread_t t;
struct ast_frame f = { 0, };
printf("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
if (mgcpdebug)
ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
/* Clear out potential response */
if (!strcasecmp(req->verb, "RSIP")) {
if (option_verbose > 2)
@ -1282,7 +1310,8 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
}
req.data[res] = '\0';
req.len = res;
printf("MGCP read: \n%s\n", req.data);
if (mgcpdebug)
ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
parse(&req);
if (req.headers < 1) {
/* Must have at least one header */
@ -1431,6 +1460,7 @@ static struct ast_channel *mgcp_request(char *type, int format, void *data)
ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
return NULL;
}
/* Must be busy */
if (p->owner)
return NULL;
@ -1453,10 +1483,32 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
gw = malloc(sizeof(struct mgcp_gateway));
if (gw) {
memset(gw, 0, sizeof(struct mgcp_gateway));
gw->expire = -1;
strncpy(gw->name, cat, sizeof(gw->name) - 1);
while(v) {
if (!strcasecmp(v->name, "host")) {
if (ast_get_ip(&gw->addr, v->value)) {
if (!strcasecmp(v->value, "dynamic")) {
/* They'll register with us */
gw->dynamic = 1;
memset(&gw->addr.sin_addr, 0, 4);
if (gw->addr.sin_port) {
/* If we've already got a port, make it the default rather than absolute */
gw->defaddr.sin_port = gw->addr.sin_port;
gw->addr.sin_port = 0;
}
} else {
/* Non-dynamic. Make sure we become that way if we're not */
if (gw->expire > -1)
ast_sched_del(sched, gw->expire);
gw->expire = -1;
gw->dynamic = 0;
if (ast_get_ip(&gw->addr, v->value)) {
free(gw);
return NULL;
}
}
} else if (!strcasecmp(v->name, "defaultip")) {
if (ast_get_ip(&gw->defaddr, v->value)) {
free(gw);
return NULL;
}
@ -1503,14 +1555,17 @@ struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
}
}
if (!ntohl(gw->addr.sin_addr.s_addr)) {
ast_log(LOG_WARNING, "Gateway '%s' lacks IP address\n", gw->name);
if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
free(gw);
gw = NULL;
} else if (!ntohs(gw->addr.sin_port)) {
return NULL;
}
if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port))
gw->defaddr.sin_port = htons(DEFAULT_MGCP_PORT);
if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
gw->addr.sin_port = htons(DEFAULT_MGCP_PORT);
if (gw->addr.sin_addr.s_addr)
memcpy(&gw->ourip, myaddrfor(&gw->addr.sin_addr), sizeof(gw->ourip));
}
return gw;
}
@ -1539,6 +1594,38 @@ static struct ast_rtp_protocol mgcp_rtp = {
set_rtp_peer: mgcp_set_rtp_peer,
};
static int mgcp_do_debug(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
mgcpdebug = 1;
ast_cli(fd, "MGCP Debugging Enabled\n");
return RESULT_SUCCESS;
}
static int mgcp_no_debug(int fd, int argc, char *argv[])
{
if (argc != 3)
return RESULT_SHOWUSAGE;
mgcpdebug = 0;
ast_cli(fd, "MGCP Debugging Disabled\n");
return RESULT_SUCCESS;
}
static char debug_usage[] =
"Usage: mgcp debug\n"
" Enables dumping of MGCP packets for debugging purposes\n";
static char no_debug_usage[] =
"Usage: mgcp no debug\n"
" Disables dumping of MGCP packets for debugging purposes\n";
static struct ast_cli_entry cli_debug =
{ { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage };
static struct ast_cli_entry cli_no_debug =
{ { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage };
int load_module()
{
struct ast_config *cfg;
@ -1649,6 +1736,8 @@ int load_module()
mgcp_rtp.type = type;
ast_rtp_proto_register(&mgcp_rtp);
ast_cli_register(&cli_show_endpoints);
ast_cli_register(&cli_debug);
ast_cli_register(&cli_no_debug);
/* And start the monitor for the first time */
restart_monitor();
return 0;

@ -387,6 +387,11 @@ static int create_addr(struct sip_pvt *r, char *peer)
if (!strcasecmp(p->name, peer)) {
found++;
r->capability = p->capability;
r->nat = p->nat;
if (r->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", r->nat);
ast_rtp_setnat(r->rtp, r->nat);
}
strncpy(r->peername, p->username, sizeof(r->peername)-1);
strncpy(r->peersecret, p->secret, sizeof(r->peersecret)-1);
strncpy(r->username, p->username, sizeof(r->username)-1);
@ -2550,8 +2555,10 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
while(user) {
if (!strcasecmp(user->name, of)) {
p->nat = user->nat;
if (p->rtp)
if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
}
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, cmd, uri))) {
strncpy(p->context, user->context, sizeof(p->context) - 1);
if (strlen(user->callerid) && strlen(p->callerid))
@ -3766,6 +3773,7 @@ static struct sip_user *build_user(char *name, struct ast_variable *v)
user->canreinvite = 1;
/* JK02: set default context */
strcpy(user->context, context);
user->dtmfmode = SIP_DTMF_RFC2833;
while(v) {
if (!strcasecmp(v->name, "context")) {
strncpy(user->context, v->value, sizeof(user->context));

@ -16,6 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <asterisk/config.h>
#include <asterisk/options.h>
#include <asterisk/logger.h>
@ -28,12 +29,22 @@ struct ast_category {
char name[80];
struct ast_variable *root;
struct ast_category *next;
struct ast_comment *precomments;
struct ast_comment *sameline;
};
struct ast_config {
/* Maybe this structure isn't necessary but we'll keep it
for now */
struct ast_category *root;
struct ast_category *prev;
struct ast_comment *trailingcomments;
};
struct ast_comment_struct
{
struct ast_comment *root;
struct ast_comment *prev;
};
static char *strip(char *buf)
@ -49,6 +60,16 @@ static char *strip(char *buf)
return start;
}
static void free_comments(struct ast_comment *com)
{
struct ast_comment *l;
while (com) {
l = com;
com = com->next;
free(l);
}
}
void ast_destroy(struct ast_config *ast)
{
struct ast_category *cat, *catn;
@ -64,13 +85,18 @@ void ast_destroy(struct ast_config *ast)
vn = v;
free(v->name);
free(v->value);
free_comments(v->precomments);
free_comments(v->sameline);
v = v->next;
free(vn);
}
catn = cat;
free_comments(cat->precomments);
free_comments(cat->sameline);
cat = cat->next;
free(catn);
}
free_comments(ast->trailingcomments);
free(ast);
}
@ -138,6 +164,220 @@ char *ast_variable_retrieve(struct ast_config *config, char *category, char *val
return NULL;
}
int ast_variable_delete(struct ast_config *cfg, char *category, char *variable, char *value)
{
struct ast_variable *v, *pv, *bv, *bpv;
struct ast_category *cat;
cat = cfg->root;
while(cat) {
if (cat->name == category) {
break;
}
cat = cat->next;
}
if (!cat) {
cat = cfg->root;
while(cat) {
if (!strcasecmp(cat->name, category)) {
break;
}
cat = cat->next;
}
}
if (!cat)
return -1;
v = cat->root;
pv = NULL;
while (v) {
if ((variable == v->name) && (!value || !strcmp(v->value, value)))
break;
pv = v;
v=v->next;
}
if (!v) {
/* Get the last one that looks like it */
bv = NULL;
bpv = NULL;
v = cat->root;
pv = NULL;
while (v) {
if (!strcasecmp(variable, v->name) && (!value || !strcmp(v->value, value))) {
bv = v;
bpv = pv;
}
pv = v;
v=v->next;
}
v = bv;
}
if (v) {
/* Unlink from original position */
if (pv)
pv->next = v->next;
else
cat->root = v->next;
v->next = NULL;
free(v->name);
if (v->value)
free(v->value);
free_comments(v->sameline);
free_comments(v->precomments);
return 0;
}
return -1;
}
int ast_category_delete(struct ast_config *cfg, char *category)
{
struct ast_variable *v, *pv;
struct ast_category *cat, *cprev;
cat = cfg->root;
cprev = NULL;
while(cat) {
if (cat->name == category) {
break;
}
cprev = cat;
cat = cat->next;
}
if (!cat) {
cat = cfg->root;
cprev = NULL;
while(cat) {
if (!strcasecmp(cat->name, category)) {
break;
}
cprev = cat;
cat = cat->next;
}
}
if (!cat)
return -1;
/* Unlink it */
if (cprev)
cprev->next = cat->next;
else
cfg->root = cat->next;
v = cat->root;
while (v) {
pv = v;
v=v->next;
if (pv->value)
free(pv->value);
if (pv->name)
free(pv->name);
free_comments(pv->sameline);
free_comments(pv->precomments);
free(pv);
}
free_comments(cat->sameline);
free_comments(cat->precomments);
free(cat);
return 0;
}
struct ast_variable *ast_variable_append_modify(struct ast_config *config, char *category, char *variable, char *value, int newcat, int newvar, int move)
{
struct ast_variable *v, *pv, *bv, *bpv;
struct ast_category *cat, *pcat;
cat = config->root;
if (!newcat) {
while(cat) {
if (cat->name == category) {
break;
}
cat = cat->next;
}
if (!cat) {
cat = config->root;
while(cat) {
if (!strcasecmp(cat->name, category)) {
break;
}
cat = cat->next;
}
}
}
if (!cat) {
cat = malloc(sizeof(struct ast_category));
if (!cat)
return NULL;
memset(cat, 0, sizeof(struct ast_category));
strncpy(cat->name, category, sizeof(cat->name));
if (config->root) {
/* Put us at the end */
pcat = config->root;
while(pcat->next)
pcat = pcat->next;
pcat->next = cat;
} else {
/* We're the first one */
config->root = cat;
}
}
if (!newvar) {
v = cat->root;
pv = NULL;
while (v) {
if (variable == v->name)
break;
pv = v;
v=v->next;
}
if (!v) {
/* Get the last one that looks like it */
bv = NULL;
bpv = NULL;
v = cat->root;
pv = NULL;
while (v) {
if (!strcasecmp(variable, v->name)) {
bv = v;
bpv = pv;
}
pv = v;
v=v->next;
}
v = bv;
}
} else v = NULL;
if (v && move) {
/* Unlink from original position */
if (pv)
pv->next = v->next;
else
cat->root = v->next;
v->next = NULL;
}
if (!v) {
v = malloc(sizeof(struct ast_variable));
if (!v)
return NULL;
memset(v, 0, sizeof(struct ast_variable));
v->name = strdup(variable);
move = 1;
}
if (v->value)
free(v->value);
if (value)
v->value = strdup(value);
else
v->value = strdup("");
if (move) {
if (cat->root) {
pv = cat->root;
while (pv->next)
pv = pv->next;
pv->next = v;
} else {
cat->root = v;
}
}
return v;
}
int ast_category_exist(struct ast_config *config, char *category_name)
{
struct ast_category *category = NULL;
@ -153,16 +393,33 @@ int ast_category_exist(struct ast_config *config, char *category_name)
return 0;
}
static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel);
static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, char *buf, int lineno, char *configfile, int includelevel)
static struct ast_comment *build_comment(char *cmt)
{
struct ast_comment *c;
c = malloc(sizeof(struct ast_comment));
if (c) {
memset(c, 0, sizeof(struct ast_comment));
c->comment = strdup(cmt);
}
return c;
}
static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel, struct ast_comment_struct *acs);
static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, char *buf, int lineno, char *configfile, int includelevel, struct ast_comment_struct *acs)
{
char *c;
char *cur;
struct ast_variable *v;
struct ast_comment *com = NULL;
int object;
/* Strip off lines using ; as comment */
c = strchr(buf, ';');
if (c)
if (c) {
*c = '\0';
c++;
if (*c != '!')
com = build_comment(c);
}
cur = strip(buf);
if (strlen(cur)) {
/* Actually parse the entry */
@ -181,8 +438,16 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, stru
memset(*_tmpc, 0, sizeof(struct ast_category));
strncpy((*_tmpc)->name, cur+1, sizeof((*_tmpc)->name) - 1);
(*_tmpc)->root = NULL;
(*_tmpc)->next = tmp->root;
tmp->root = *_tmpc;
(*_tmpc)->precomments = acs->root;
(*_tmpc)->sameline = com;
if (!tmp->prev)
tmp->root = *_tmpc;
else
tmp->prev->next = *_tmpc;
tmp->prev = *_tmpc;
acs->root = NULL;
acs->prev = NULL;
*_last = NULL;
} else {
ast_log(LOG_WARNING,
@ -216,7 +481,7 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, stru
break;
}
if (includelevel < MAX_INCLUDE_LEVEL) {
__ast_load(cur, tmp, _tmpc, _last, includelevel + 1);
__ast_load(cur, tmp, _tmpc, _last, includelevel + 1, acs);
} else
ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", includelevel);
} else
@ -237,8 +502,11 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, stru
*c = 0;
c++;
/* Ignore > in => */
if (*c== '>')
if (*c== '>') {
object = 1;
c++;
} else
object = 0;
v = malloc(sizeof(struct ast_variable));
if (v) {
memset(v, 0, sizeof(struct ast_variable));
@ -246,7 +514,14 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, stru
v->name = strdup(strip(cur));
v->value = strdup(strip(c));
v->lineno = lineno;
if (*_last)
v->object = object;
/* Put and reset comments */
v->precomments = acs->root;
v->blanklines = 0;
acs->prev = NULL;
acs->root = NULL;
v->sameline = com;
if (*_last)
(*_last)->next = v;
else
(*_tmpc)->root = v;
@ -260,17 +535,108 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, stru
ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
}
}
} else {
/* store any comments if there are any */
if (com) {
if (acs->prev)
acs->prev->next = com;
else
acs->root = com;
acs->prev = com;
} else {
if (*_last)
(*_last)->blanklines++;
}
}
return 0;
}
static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel)
static void dump_comments(FILE *f, struct ast_comment *comment)
{
while (comment) {
fprintf(f, ";%s", comment->comment);
comment = comment->next;
}
}
int ast_save(char *configfile, struct ast_config *cfg, char *generator)
{
FILE *f;
char fn[256];
char date[256];
time_t t;
struct ast_variable *var;
struct ast_category *cat;
int blanklines = 0;
if (configfile[0] == '/') {
strncpy(fn, configfile, sizeof(fn)-1);
} else {
snprintf(fn, sizeof(fn), "%s/%s", AST_CONFIG_DIR, configfile);
}
time(&t);
strncpy(date, ctime(&t), sizeof(date));
if ((f = fopen(fn, "w"))) {
if ((option_verbose > 1) && !option_debug)
ast_verbose( VERBOSE_PREFIX_2 "Saving '%s': ", fn);
fprintf(f, ";!\n");
fprintf(f, ";! Automatically generated configuration file\n");
fprintf(f, ";! Filename: %s (%s)\n", configfile, fn);
fprintf(f, ";! Generator: %s\n", generator);
fprintf(f, ";! Creation Date: %s", date);
fprintf(f, ";!\n");
cat = cfg->root;
while(cat) {
/* Dump any precomments */
dump_comments(f, cat->precomments);
/* Dump section with any appropriate comment */
if (cat->sameline)
fprintf(f, "[%s] ; %s\n", cat->name, cat->sameline->comment);
else
fprintf(f, "[%s]\n", cat->name);
var = cat->root;
while(var) {
dump_comments(f, var->precomments);
if (var->sameline)
fprintf(f, "%s %s %s ; %s\n", var->name, (var->object ? "=>" : "="), var->value, var->sameline->comment);
else
fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
if (var->blanklines) {
blanklines = var->blanklines;
while (blanklines) {
fprintf(f, "\n");
blanklines--;
}
}
var = var->next;
}
#if 0
/* Put an empty line */
fprintf(f, "\n");
#endif
cat = cat->next;
}
dump_comments(f, cfg->trailingcomments);
} else {
if (option_debug)
printf("Unable to open for writing: %s\n", fn);
else if (option_verbose > 1)
printf( "Unable to write (%s)", strerror(errno));
return -1;
}
fclose(f);
return 0;
}
static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel, struct ast_comment_struct *acs)
{
char fn[256];
char buf[256];
FILE *f;
int lineno=0;
int master=0;
if (configfile[0] == '/') {
strncpy(fn, configfile, sizeof(fn)-1);
@ -290,6 +656,8 @@ static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, s
tmp = malloc(sizeof(struct ast_config));
if (tmp)
memset(tmp, 0, sizeof(struct ast_config));
master = 1;
}
if (!tmp) {
ast_log(LOG_WARNING, "Out of memory\n");
@ -300,7 +668,7 @@ static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, s
fgets(buf, sizeof(buf), f);
lineno++;
if (!feof(f)) {
if (cfg_process(tmp, _tmpc, _last, buf, lineno, configfile, includelevel)) {
if (cfg_process(tmp, _tmpc, _last, buf, lineno, configfile, includelevel, acs)) {
fclose(f);
return NULL;
}
@ -313,6 +681,12 @@ static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, s
else if (option_verbose > 1)
ast_verbose( "Not found (%s)", strerror(errno));
}
if (master) {
/* Keep trailing comments */
tmp->trailingcomments = acs->root;
acs->root = NULL;
acs->prev = NULL;
}
return tmp;
}
@ -320,7 +694,8 @@ struct ast_config *ast_load(char *configfile)
{
struct ast_category *tmpc=NULL;
struct ast_variable *last = NULL;
return __ast_load(configfile, NULL, &tmpc, &last, 0);
struct ast_comment_struct acs = { NULL, NULL };
return __ast_load(configfile, NULL, &tmpc, &last, 0, &acs);
}
char *ast_category_browse(struct ast_config *config, char *prev)

@ -519,6 +519,7 @@ static int dtmf_detect (dtmf_detect_state_t *s,
} /* Don't reset fax hits counter */
} else {
if (s->fax_hits > 5) {
hit = 'f';
s->mhit = 'f';
s->detected_digits++;
if (s->current_digits < MAX_DTMF_DIGITS)

@ -30,6 +30,7 @@ struct ast_variable {
char *value;
int lineno;
int object; /* 0 for variable, 1 for object */
int blanklines; /* Number of blanklines following entry */
struct ast_comment *precomments;
struct ast_comment *sameline;
struct ast_variable *next;

@ -733,5 +733,6 @@ int init_manager(void)
int reload_manager(void)
{
manager_event(EVENT_FLAG_SYSTEM, "Reload", NULL);
return init_manager();
}

@ -282,7 +282,11 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
}
if (rtp->nat) {
/* Send to whoever sent to us */
memcpy(&rtp->them, &sin, sizeof(rtp->them));
if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
(rtp->them.sin_port != sin.sin_port)) {
memcpy(&rtp->them, &sin, sizeof(rtp->them));
ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
}
}
/* Get fields */
seqno = ntohl(rtpheader[0]);

Loading…
Cancel
Save