datafiles: all
if [ x`$(ID) -un` = xroot ]; then sh mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig; fi
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
+ mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/silence
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/priv-callerintros
for x in sounds/digits/*.gsm; do \
if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
exit 1; \
fi; \
done
+ for x in sounds/silence/*.gsm; do \
+ if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
+ $(INSTALL) -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/silence ; \
+ else \
+ echo "No description for $$x"; \
+ exit 1; \
+ fi; \
+ done
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/dictate
for x in sounds/dictate/*.gsm; do \
if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \
static char *cut_synopsis = "Splits a variable's contents using the specified delimiter";
static char *cut_descrip =
-" Cut(newvar=varname,delimiter,fieldspec): This applicaiton will split the\n"
+" Cut(newvar=varname,delimiter,fieldspec): This application will split the\n"
"contents of a variable based on the given delimeter and store the result in\n"
"a new variable.\n"
"Parameters:\n"
" Sort(newvar=key1:val1[,key2:val2[[...],keyN:valN]]): This application will\n"
"sort the list provided in ascending order. The result will be stored in the\n"
"specified variable name.\n"
-" This applicaiton has been deprecated in favor of the SORT function.\n";
+" This application has been deprecated in favor of the SORT function.\n";
STANDARD_LOCAL_USER;
" This application has been deprecated in favor of the DB function.\n";
static char *d_descrip =
-" DBdel(family/key): This applicaiton will delete a key from the Asterisk\n"
+" DBdel(family/key): This application will delete a key from the Asterisk\n"
"database.\n";
static char *dt_descrip =
static char *descrip =
" Dial(Technology/resource[&Tech2/resource2...][|timeout][|options][|URL]):\n"
-"This applicaiton will place calls to one or more specified channels. As soon\n"
+"This application will place calls to one or more specified channels. As soon\n"
"as one of the requested channels answers, the originating channel will be\n"
"answered, if it has not already been answered. These two channels will then\n"
"be active in a bridged call. All other channels that were requested will then\n"
strcpy(status, "NOANSWER");
if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
moh=1;
+ ast_indicate(chan, AST_CONTROL_PROGRESS);
ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]);
} else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
ast_indicate(chan, AST_CONTROL_RINGING);
"the calling channel with a directory of extensions from which they can search\n"
"by name. The list of names and corresponding extensions is retrieved from the\n"
"voicemail configuration file, voicemail.conf.\n"
-" This applicaiton will immediate exit if one of the following DTMF digits are\n"
+" This application will immediately exit if one of the following DTMF digits are\n"
"received and the extension to jump to exists:\n"
" 0 - Jump to the 'o' extension, if it exists.\n"
" * - Jump to the 'a' extension, if it exists.\n\n"
#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <signal.h>
#include "asterisk.h"
if (state->current) {
file_to_stream = state->current->filename;
} else {
- file_to_stream = "silence-10";
+ file_to_stream = "silence/10";
u->playing_silence = 1;
}
FILE *child_commands = NULL;
FILE *child_errors = NULL;
FILE *child_events = NULL;
+ sigset_t fullset, oldset;
LOCAL_USER_ADD(u);
-
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
AST_LIST_HEAD_INIT(&u->playlist);
AST_LIST_HEAD_INIT(&u->finishlist);
u->abort_current_sound = 0;
/* child process */
int i;
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
if (option_highpriority)
ast_set_priority(0);
int waitfds[2] = { child_errors_fd, child_commands_fd };
struct ast_channel *rchan;
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
close(child_stdin[0]);
child_stdin[0] = 0;
close(child_stdout[1]);
#ifdef __PPC__
char c;
#endif
+ sigset_t fullset, oldset;
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
- if (res)
+ if (res) {
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
+ }
for (x=0;x<256;x++) {
if (x != fd)
close(x);
}
if (option_highpriority)
ast_set_priority(0);
-
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
/*IAS */
#ifdef __PPC__
for( x=0; x<length; x+=2)
{
int res;
int x;
+ sigset_t fullset, oldset;
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
- if (res)
+ if (res) {
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
+ }
+
+ /* Stop ignoring PIPE */
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
if (option_highpriority)
ast_set_priority(0);
dup2(fd, STDIN_FILENO);
- for (x=STDERR_FILENO + 1;x<256;x++) {
+ for (x=STDERR_FILENO + 1;x<1024;x++) {
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
close(x);
}
/* As a last-ditch effort, try to use PATH */
execlp("ices", "ices", filename, (char *)NULL);
ast_log(LOG_WARNING, "Execute of ices failed\n");
- return -1;
+ _exit(0);
}
static int ices_exec(struct ast_channel *chan, void *data)
{
int res;
int x;
+ sigset_t fullset, oldset;
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
- if (res)
+ if (res) {
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
+ }
if (option_highpriority)
ast_set_priority(0);
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
dup2(fd, STDOUT_FILENO);
- for (x=0;x<256;x++) {
+ for (x=STDERR_FILENO + 1;x<256;x++) {
if (x != STDOUT_FILENO)
close(x);
}
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
}
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
- return -1;
+ _exit(0);
}
static int timed_read(int fd, void *data, int datalen, int timeout)
{
int res;
int x;
+ sigset_t fullset, oldset;
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
- if (res)
+ if (res) {
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
+ }
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
if (option_highpriority)
ast_set_priority(0);
dup2(fd, STDOUT_FILENO);
- for (x=0;x<256;x++) {
+ for (x = STDERR_FILENO + 1; x < 1024; x++) {
if (x != STDOUT_FILENO)
close(x);
}
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
- return -1;
+ _exit(0);
}
static int timed_read(int fd, void *data, int datalen)
unsigned char p = 2;
h->omsg[0] = 0x91; /* SMS_DATA */
if (h->smsc) { /* deliver */
- h->omsg[p++] = (more ? 4 : 0);
+ h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
p += packaddress (h->omsg + p, h->oa);
h->omsg[p++] = h->pid;
h->omsg[p++] = h->dcs;
#define COMMAND_TIMEOUT 5000
#define VOICEMAIL_DIR_MODE 0700
#define VOICEMAIL_FILE_MODE 0600
+#define CHUNKSIZE 65536
#define VOICEMAIL_CONFIG "voicemail.conf"
#define ASTERISK_USERNAME "asterisk"
goto yuck;
}
if (!strcasecmp(coltitle, "recording")) {
+ off_t offset;
res = SQLGetData(stmt, x + 1, SQL_BINARY, NULL, 0, &colsize);
fdlen = colsize;
if (fd > -1) {
fd = -1;
continue;
}
- if (fd > -1)
- fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- }
- if (fdm) {
- memset(fdm, 0, fdlen);
- res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize);
- if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
- ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
- SQLFreeHandle (SQL_HANDLE_STMT, stmt);
- goto yuck;
+ /* Read out in small chunks */
+ for (offset = 0; offset < colsize; offset += CHUNKSIZE) {
+ /* +1 because SQLGetData likes null-terminating binary data */
+ if ((fdm = mmap(NULL, CHUNKSIZE + 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == -1) {
+ ast_log(LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ goto yuck;
+ } else {
+ res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE + 1, NULL);
+ munmap(fdm, 0);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+ unlink(full_fn);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ goto yuck;
+ }
+ }
}
+ truncate(full_fn, fdlen);
}
} else {
res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
yuck:
if (f)
fclose(f);
- if (fdm)
- munmap(fdm, fdlen);
if (fd > -1)
close(fd);
return x - 1;
{
int bytes = 0;
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
- bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002 LSS, Inc.", "");
+ bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
return bytes;
}
return res;
}
-static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfts,
- char *context, signed char record_gain)
+static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfmts,
+ char *context, signed char record_gain, long *duration)
{
int cmd = 0;
int retries = 0;
- int duration = 0;
signed char zero_gain = 0;
while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
retries = 0;
switch (cmd) {
case '1':
- /* prepend a message to the current message and return */
+ /* prepend a message to the current message, update the metadata and return */
{
- char file[200];
- snprintf(file, sizeof(file), "%s/msg%04d", curdir, curmsg);
+ char msgfile[PATH_MAX];
+ char textfile[PATH_MAX];
+ int prepend_duration = 0;
+ struct ast_config *msg_cfg;
+ char *duration_str;
+
+ make_file(msgfile, sizeof(msgfile), curdir, curmsg);
+ strcpy(textfile, msgfile);
+ strncat(textfile, ".txt", sizeof(textfile) - 1);
+ *duration = 0;
+
+ /* if we can't read the message metadata, stop now */
+ if (!(msg_cfg = ast_config_load(textfile))) {
+ cmd = 0;
+ break;
+ }
+
if (record_gain)
ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
- cmd = ast_play_and_prepend(chan, NULL, file, 0, vmfmts, &duration, 1, silencethreshold, maxsilence);
+
+ cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vmfmts, &prepend_duration, 1, silencethreshold, maxsilence);
if (record_gain)
ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
+
+
+ if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
+ *duration = atoi(duration_str);
+
+ if (prepend_duration) {
+ struct ast_variable *var, *prev = NULL, *varlist;
+ struct ast_category *msg_cat;
+
+ *duration += prepend_duration;
+ msg_cat = ast_category_get(msg_cfg, "message");
+ varlist = ast_category_detach_variables(msg_cat);
+ for (var = varlist; var; prev = var, var = var->next) {
+ if (!strcmp(var->name, "duration")) {
+ if (!prev)
+ varlist = var->next;
+ else
+ prev->next = var->next;
+ free(var);
+ break;
+ }
+ }
+ /* need enough space for a maximum-length message duration */
+ duration_str = alloca(12);
+ snprintf(duration_str, 11, "%ld", *duration);
+ if ((var = ast_variable_new("duration", duration_str))) {
+ ast_variable_append(msg_cat, varlist);
+ ast_variable_append(msg_cat, var);
+ config_text_file_save(textfile, msg_cfg, "app_voicemail");
+ STORE(curdir, vmu->mailbox, context, curmsg);
+ }
+ }
+
+ ast_config_destroy(msg_cfg);
+
break;
}
case '2':
cmd = leave_voicemail(chan, mailbox, &leave_options);
} else {
/* Forward VoiceMail */
+ long duration = 0;
+
RETRIEVE(dir, curmsg);
- cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, context, record_gain);
+ cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, context, record_gain, &duration);
if (!cmd) {
while (!res && vmtmp) {
- copy_message(chan, sender, 0, curmsg, 0, vmtmp, fmt);
+ copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt);
saved_messages++;
vmfree = vmtmp;
}
}
while (vmu) {
- char dirname[256];
- DIR *vmdir;
- struct dirent *vment;
- int vmcount = 0;
- char count[12];
+ int newmsgs = 0, oldmsgs = 0;
+ char count[12], tmp[256] = "";
if ((argc == 3) || ((argc == 5) && !strcmp(argv[4],vmu->context))) {
- make_dir(dirname, 255, vmu->context, vmu->mailbox, "INBOX");
- if ((vmdir = opendir(dirname))) {
- /* No matter what the format of VM, there will always be a .txt file for each message. */
- while ((vment = readdir(vmdir)))
- if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,".txt",4))
- vmcount++;
- closedir(vmdir);
- }
- snprintf(count,sizeof(count),"%d",vmcount);
+ snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
+ messagecount(tmp, &newmsgs, &oldmsgs);
+ snprintf(count,sizeof(count),"%d",newmsgs);
ast_cli(fd, output_format, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
}
vmu = vmu->next;
char *argv[PPP_MAX_ARGS];
int argc = 0;
char *stringp=NULL;
+ sigset_t fullset, oldset;
+
+ sigfillset(&fullset);
+ pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
/* Start by forking */
pid = fork();
- if (pid)
+ if (pid) {
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return pid;
+ }
+
+ /* Restore original signal handlers */
+ for (x=0;x<NSIG;x++)
+ signal(x, SIG_DFL);
+
+ pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
/* Execute RAS on File handles */
dup2(chan->fds[0], STDIN_FILENO);
for (x=STDERR_FILENO + 1;x<1024;x++)
close(x);
- /* Restore original signal handlers */
- for (x=0;x<NSIG;x++)
- signal(x, SIG_DFL);
-
/* Reset all arguments */
memset(argv, 0, sizeof(argv));
next = cdr->next;
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
- ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
+ ast_log(LOG_NOTICE, "CDR on channel '%s' not posted\n", chan);
if (ast_tvzero(cdr->end))
- ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
+ ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan);
if (ast_tvzero(cdr->start))
- ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
+ ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan);
ast_cdr_free_vars(cdr, 0);
free(cdr);
while (cdr) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
- ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
+ ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", chan);
if (ast_tvzero(cdr->end))
- ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
+ ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan);
if (ast_tvzero(cdr->start)) {
- ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
+ ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan);
cdr->disposition = AST_CDR_FAILED;
} else
cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
#
# PGSQL stuff... Autoconf anyone??
#
-ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/postgresql)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/pgsql/include)$(wildcard $(CROSS_COMPILE_TARGET)/usr/include/pgsql)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/pgsql)$(wildcard $(CROSS_COMPILE_TARGET)/opt/pgsql/include)$(wildcard $(CROSS_COMPILE_TARGET)/usr/include/libpq-fe.h),)
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/postgresql/libpq-fe.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/pgsql/include/libpq-fe.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/include/pgsql/libpq-fe.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/pgsql/libpq-fe.h)$(wildcard $(CROSS_COMPILE_TARGET)/opt/pgsql/include/libpq-fe.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/include/libpq-fe.h),)
MODS+=cdr_pgsql.so
endif
AST_MUTEX_DEFINE_STATIC(pgsql_lock);
-PGconn *conn;
-PGresult *result;
+PGconn *conn = NULL;
+PGresult *result = NULL;
static int pgsql_log(struct ast_cdr *cdr)
{
{
struct chanlist *chan, *last=NULL;
- if (option_debug)
+ if (option_debug && tech && tech->type )
ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type);
+ else if (option_debug)
+ ast_log(LOG_DEBUG, "Unregistering channel, tech is NULL!!!\n");
+
ast_mutex_lock(&chlock);
const char *context, const char *exten)
{
const char *msg = prev ? "deadlock" : "initial deadlock";
- int retries, done;
+ int retries;
struct ast_channel *c;
for (retries = 0; retries < 10; retries++) {
+ int done;
+
ast_mutex_lock(&chlock);
for (c = channels; c; c = c->next) {
- if (!prev) {
- /* want head of list */
- if (!name && !exten)
- break;
- if (name) {
- /* want match by full name */
- if (!namelen) {
- if (!strcasecmp(c->name, name))
- break;
- else
- continue;
- }
- /* want match by name prefix */
- if (!strncasecmp(c->name, name, namelen))
- break;
- } else if (exten) {
- /* want match by context and exten */
- if (context && (strcasecmp(c->context, context) &&
- strcasecmp(c->macrocontext, context)))
- continue;
- /* match by exten */
- if (strcasecmp(c->exten, exten) &&
- strcasecmp(c->macroexten, exten))
- continue;
- else
- break;
- }
- } else if (c == prev) { /* found, return c->next */
+ if (prev) { /* look for next item */
+ if (c != prev) /* not this one */
+ continue;
+ /* found, prepare to return c->next */
c = c->next;
- break;
}
+ if (name) { /* want match by name */
+ if ((!namelen && strcasecmp(c->name, name)) ||
+ (namelen && strncasecmp(c->name, name, namelen)))
+ continue; /* name match failed */
+ } else if (exten) {
+ if (context && strcasecmp(c->context, context) &&
+ strcasecmp(c->macrocontext, context))
+ continue; /* context match failed */
+ if (strcasecmp(c->exten, exten) &&
+ strcasecmp(c->macroexten, exten))
+ continue; /* exten match failed */
+ }
+ /* if we get here, c points to the desired record */
+ break;
}
/* exit if chan not found or mutex acquired successfully */
done = (c == NULL) || (ast_mutex_trylock(&c->lock) == 0);
else
res = 0;
break;
+ case AST_FRAME_NULL:
+ case AST_FRAME_IAX:
+ /* Ignore these */
+ res = 0;
+ break;
default:
if (chan->tech->write) {
f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr;
c->cid.cid_num ? c->cid.cid_num : "<unknown>",
c->cid.cid_name ? c->cid.cid_name : "<unknown>",
c->uniqueid);
+ ast_set_flag(c, AST_FLAG_NOTNEW);
}
return c;
}
chan->_state = state;
ast_device_state_changed_literal(chan->name);
manager_event(EVENT_FLAG_CALL,
- (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
+ (oldstate == AST_STATE_DOWN && !ast_test_flag(chan, AST_FLAG_NOTNEW)) ? "Newchannel" : "Newstate",
"Channel: %s\r\n"
"State: %s\r\n"
"CallerID: %s\r\n"
if (!ast_tvzero(nexteventts)) {
now = ast_tvnow();
to = ast_tvdiff_ms(nexteventts, now);
- if (to <= 0) {
+ if (to <= 0 && !config->timelimit) {
res = AST_BRIDGE_COMPLETE;
break;
- }
+ }
+
}
if (config->timelimit) {
break;
}
- if (!to) {
+ if (to <= 0) {
if (time_left_ms >= 5000) {
/* force the time left to round up if appropriate */
if (caller_warning && config->warning_sound && config->play_warning)
}
if (config->warning_freq) {
nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000));
- } else
+ }
+
+ if ( (!config->warning_freq) || ( config->timelimit - ast_tvdiff_ms(nexteventts, config->start_time) < 0)) {
nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
+ }
}
}
o1nativeformats = c1->nativeformats;
}
res = ast_generic_bridge(c0, c1, config, fo, rc, nexteventts);
- if (res != AST_BRIDGE_RETRY)
+ if (res != AST_BRIDGE_RETRY && fo)
break;
}
};
static struct iax2_registry *registrations;
+AST_MUTEX_DEFINE_STATIC(reg_lock);
/* Don't retry more frequently than every 10 ms, or less frequently than every 5 seconds */
#define MIN_RETRY_TIME 100
char iabuf[INET_ADDRSTRLEN];
if (argc != 3)
return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerl.lock);
ast_cli(fd, FORMAT2, "Host", "Username", "Perceived", "Refresh", "State");
+ ast_mutex_lock(®_lock);
for (reg = registrations;reg;reg = reg->next) {
snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), reg->addr.sin_addr), ntohs(reg->addr.sin_port));
if (reg->us.sin_addr.s_addr)
ast_cli(fd, FORMAT, host,
reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
}
- ast_mutex_unlock(&peerl.lock);
+ ast_mutex_unlock(®_lock);
return RESULT_SUCCESS;
#undef FORMAT
#undef FORMAT2
reg->addr.sin_family = AF_INET;
memcpy(®->addr.sin_addr, hp->h_addr, sizeof(®->addr.sin_addr));
reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
+ ast_mutex_lock(®_lock);
reg->next = registrations;
reg->callno = 0;
registrations = reg;
+ ast_mutex_unlock(®_lock);
} else {
ast_log(LOG_ERROR, "Out of memory\n");
return -1;
if (!strcmp(ies.called_number, ast_parking_ext())) {
if (iax_park(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->owner)) {
ast_log(LOG_WARNING, "Failed to park call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
- } else
+ } else if (ast_bridged_channel(iaxs[fr->callno]->owner))
ast_log(LOG_DEBUG, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
} else {
if (ast_async_goto(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->context, ies.called_number, 1))
user = user->next;
}
ast_mutex_unlock(&userl.lock);
+ ast_mutex_lock(®_lock);
for (reg = registrations;reg;) {
regl = reg;
reg = reg->next;
free(regl);
}
registrations = NULL;
+ ast_mutex_unlock(®_lock);
ast_mutex_lock(&peerl.lock);
for (peer=peerl.peers;peer;) {
/* Assume all will be deleted, and we'll find out for sure later */
set_config(config,1);
prune_peers();
prune_users();
+ ast_mutex_lock(®_lock);
for (reg = registrations; reg; reg = reg->next)
iax2_do_register(reg);
+ ast_mutex_unlock(®_lock);
/* Qualify hosts, too */
ast_mutex_lock(&peerl.lock);
for (peer = peerl.peers; peer; peer = peer->next)
buf[0] = '\0';
- if (chan->tech != &iax2_tech)
- return buf;
-
if (!(peername = ast_strdupa(data))) {
ast_log(LOG_ERROR, "Memory Error!\n");
return ret;
/* if our channel, return the IP address of the endpoint of current channel */
if (!strcmp(peername,"CURRENTCHANNEL")) {
- unsigned short callno = PTR_TO_CALLNO(chan->tech_pvt);
+ unsigned short callno;
+ if (chan->tech != &iax2_tech)
+ return buf;
+ callno = PTR_TO_CALLNO(chan->tech_pvt);
ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iaxs[callno]->addr.sin_addr) : "", len);
return buf;
}
ast_netsock_release(netsock);
}
+ ast_mutex_lock(®_lock);
for (reg = registrations; reg; reg = reg->next)
iax2_do_register(reg);
+ ast_mutex_unlock(®_lock);
ast_mutex_lock(&peerl.lock);
for (peer = peerl.peers; peer; peer = peer->next) {
if (peer->sockfd < 0)
int isoutbound;
int res = -1;
+ if (!p)
+ return -1;
+
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
if (isoutbound) {
int res = -1;
int isoutbound;
+ if (!p)
+ return -1;
+
/* Just queue for delivery to the other side */
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
struct local_pvt *p = newchan->tech_pvt;
+
+ if (!p)
+ return -1;
+
ast_mutex_lock(&p->lock);
if ((p->owner != oldchan) && (p->chan != oldchan)) {
struct ast_frame f = { AST_FRAME_CONTROL, };
int isoutbound;
+ if (!p)
+ return -1;
+
/* Queue up a frame representing the indication as a control frame */
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
struct ast_frame f = { AST_FRAME_DTMF, };
int isoutbound;
+ if (!p)
+ return -1;
+
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
f.subclass = digit;
struct ast_frame f = { AST_FRAME_HTML, };
int isoutbound;
+ if (!p)
+ return -1;
+
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
f.subclass = subclass;
int res;
struct ast_var_t *varptr = NULL, *new;
size_t len, namelen;
+
+ if (!p)
+ return -1;
ast_mutex_lock(&p->lock);
struct ast_channel *ochan = NULL;
int glaredetect;
+ if (!p)
+ return -1;
+
ast_mutex_lock(&p->lock);
isoutbound = IS_OUTBOUND(ast, p);
if (isoutbound) {
print_bc_info(fd, help, bc);
} else {
if (help->state == MISDN_HOLDED) {
- chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
- chan_misdn_log(0,0," --> l3_id: %x\n"
+ chan_misdn_log(2, 0, "ITS A HOLDED BC:\n");
+ chan_misdn_log(2,0," --> l3_id: %x\n"
" --> dad:%s oad:%s\n"
,help->l3id
int port=bc->port;
- chan_misdn_log(1,port,"update_config: Getting Config\n");
-
+ chan_misdn_log(7,port,"update_config: Getting Config\n");
int hdlc=0;
misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
chan_misdn_log(1, port, "* CALL: %s\n",dest);
- chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
+ chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
if (ast->exten) {
return -1;
}
- chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
+ chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
ast_setstate(ast, AST_STATE_DIALING);
ast->hangupcause=16;
return -1;
}
- chan_misdn_log(1, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
+ chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
switch (cond) {
case AST_CONTROL_BUSY:
- chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
- chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
ast_setstate(ast,AST_STATE_BUSY);
p->bc->out_cause=17;
return -1;
break;
case AST_CONTROL_RING:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
return -1;
break;
case AST_CONTROL_RINGING:
+ chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
switch (p->state) {
case MISDN_ALERTING:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
break;
case MISDN_CONNECTED:
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
return -1;
break;
default:
p->state=MISDN_ALERTING;
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
misdn_lib_send_event( p->bc, EVENT_ALERTING);
if (p->other_ch && p->other_ch->bc) {
if (misdn_inband_avail(p->other_ch->bc)) {
- chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n");
+ chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
break;
}
if (!p->other_ch->bc->nt) {
- chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
+ chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
break;
}
}
- chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
ast_setstate(ast,AST_STATE_RINGING);
if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
- chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n");
+ chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
else
return -1;
}
chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
break;
default:
- ast_log(LOG_NOTICE, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
+ chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
}
return 0;
}
chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",p->bc?p->bc->pid:-1, ast->context, ast->exten, AST_CID_P(ast), misdn_get_ch_state(p));
- chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
- chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
- chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
- chan_misdn_log(1, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
+ chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
+ chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
+ chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
+ chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
switch (p->state) {
case MISDN_CALLING:
}
- chan_misdn_log(1, bc->port, "Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
+ chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
return 0;
}
/* got hangup .. */
if (!f)
- chan_misdn_log(1,ch1->bc->port,"Read Null Frame\n");
+ chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
else
- chan_misdn_log(1,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
+ chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
*fo=f;
*rc=who;
return;
}
- cb_log(1,port,"hangup_chan\n");
+ cb_log(5,port,"hangup_chan called\n");
if (ch->need_hangup)
{
- cb_log(1,port,"-> hangup\n");
+ cb_log(2,port," --> hangup\n");
send_cause2ast(ch->ast,ch->bc,ch);
ch->need_hangup=0;
ch->need_queue_hangup=0;
}
if (!ch->need_queue_hangup) {
- cb_log(1,port,"No need to queue hangup\n");
+ cb_log(2,port," --> No need to queue hangup\n");
}
ch->need_queue_hangup=0;
if (ch->ast)
ast_queue_hangup(ch->ast);
- cb_log(1,port,"-> queue_hangup\n");
+ cb_log(2,port," --> queue_hangup\n");
} else {
cb_log(1,port,"Cannot hangup chan, no ast\n");
}
ast=ch->ast;
}
- chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
+ chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
/*releaseing jitterbuffer*/
if (ch->jb ) {
tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
if (tmp) {
ch->other_pid=atoi(tmp);
- chan_misdn_log(1,bc->port,"IMPORT_PID: importing pid:%s\n",tmp);
+ chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
if (ch->other_pid >0) {
ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
if (ch->other_ch) ch->other_ch->other_ch=ch;
}
}
+
+ tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
+ if (tmp && (atoi(tmp) == 1)) {
+ bc->sending_complete=1;
+ }
}
void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
{
char tmp[32];
- chan_misdn_log(1,bc->port,"EXPORT_PID: pid:%d\n",bc->pid);
+ chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
sprintf(tmp,"%d",bc->pid);
pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
+
+ if (bc->sending_complete) {
+ sprintf(tmp,"%d",bc->sending_complete);
+ pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
+ }
}
ast_queue_control(ch->ast, AST_CONTROL_RINGING);
ast_setstate(ch->ast, AST_STATE_RINGING);
- cb_log(1,bc->port,"Set State Ringing\n");
+ cb_log(7,bc->port," --> Set State Ringing\n");
if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
start_bc_tones(ch);
} else {
- cb_log(1,bc->port,"We have no inband Data, the other end must create ringing\n");
+ cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
if (ch->far_alerting) {
- cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
+ cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
start_bc_tones(ch);
/*tone_indicate(ch, TONE_FAR_ALERTING);*/
}
int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
if (ret<=0) {
- chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno));
+ chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
+
+ stop_bc_tones(ch);
+ hangup_chan(ch);
+ release_chan(bc);
}
} else {
chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
ch->bc=bc;
ch->state = MISDN_CONNECTED;
+ ch->hold_info.port=0;
+ ch->hold_info.channel=0;
+
struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
if (hold_ast) {
break;
default:
- ast_log(LOG_NOTICE, "Got Unknown Event\n");
+ chan_misdn_log(1,0, "Got Unknown Event\n");
break;
}
return 0;
}
-
- misdn_cfg_init(max_ports);
+ if (misdn_cfg_init(max_ports)<0) {
+ ast_log(LOG_ERROR, "Unable to initialize mISDN Config System\n");
+ return 0;
+ }
+
g_config_initialized=1;
misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
} else {
- ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
+ chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
}
return 0;
#include <linux/telephony.h>
/* Still use some IXJ specific stuff */
#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-# include <linux/compiler.h>
-#endif
#include <linux/ixjuser.h>
#include "asterisk.h"
ast_mutex_unlock(&pkt->owner->owner->lock);
} else {
/* If no channel owner, destroy now */
- ast_set_flag(pkt->owner, SIP_NEEDDESTROY);
+ /* Let the peerpoke system expire packets when the timer expires for poke_noanswer */
+ if (pkt->method != SIP_OPTIONS)
+ ast_set_flag(pkt->owner, SIP_NEEDDESTROY);
}
}
/* In any case, go ahead and remove the packet */
if (sipdebug && option_debug > 3)
ast_log(LOG_DEBUG, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
ast_sched_del(sched, cur->retransid);
+ cur->retransid = -1;
}
free(cur);
res = 0;
if (option_debug > 3 && sipdebug)
ast_log(LOG_DEBUG, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, msg);
ast_sched_del(sched, cur->retransid);
+ cur->retransid = -1;
}
- cur->retransid = -1;
res = 0;
break;
}
}
if (peer->expire > -1)
ast_sched_del(sched, peer->expire);
+
if (peer->pokeexpire > -1)
ast_sched_del(sched, peer->pokeexpire);
register_peer_exten(peer, 0);
case INC_CALL_LIMIT:
if (*call_limit > 0 ) {
if (*inuse >= *call_limit) {
- ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
+ ast_log(LOG_NOTICE, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
if (u)
ASTOBJ_UNREF(u,sip_destroy_user);
else
/* Do we need a timer here if we don't hear from them at all? */
} else {
/* Send a new request: CANCEL */
- transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
+ transmit_request(p, SIP_CANCEL, p->ocseq, 1, 0);
/* Actually don't destroy us yet, wait for the 487 on our original
INVITE, but do set an autodestruct just in case we never get it. */
}
ast_setstate(ast, AST_STATE_UP);
if (option_debug)
ast_log(LOG_DEBUG, "sip_answer(%s)\n", ast->name);
- res = transmit_response_with_sdp(p, "200 OK", &p->initreq, 1);
+ res = transmit_response_with_sdp(p, "200 OK", &p->initreq, 2);
}
ast_mutex_unlock(&p->lock);
return res;
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
struct sip_pvt *p = newchan->tech_pvt;
+ if (!p) {
+ ast_log(LOG_WARNING, "No pvt after masquerade. Strange things may happen\n");
+ return -1;
+ }
+
ast_mutex_lock(&p->lock);
if (p->owner != oldchan) {
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
ast_mutex_unlock(&iflock);
/* If this is a response and we have ignoring of out of dialog responses turned on, then drop it */
+ /* ...and never respond to a SIP ACK message */
if (!sip_methods[intended_method].can_create) {
/* Can't create dialog */
- if (intended_method != SIP_RESPONSE)
+ if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK)
transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist");
} else if (sip_methods[intended_method].can_create == 2) {
char *response = "481 Call leg/transaction does not exist";
p = sip_alloc(callid, sin, 1, intended_method);
if (p)
ast_mutex_lock(&p->lock);
+ else {
+ /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not
+ getting a dialog from sip_alloc.
+
+ Without a dialog we can't retransmit and handle ACKs and all that, but at least
+ send an error message.
+
+ Sorry, we apologize for the inconvienience
+ */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "500 Server internal error");
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n");
+ }
}
return p;
for (x = 0; x < (req->lines - 2); x++) {
if (!strncasecmp(req->line[x], boundary, strlen(boundary)) &&
!strcasecmp(req->line[x + 1], "Content-Type: application/sdp")) {
- req->sdp_start = x + 2;
+ x += 2;
+ req->sdp_start = x;
+
/* search for the end of the body part */
for ( ; x < req->lines; x++) {
if (!strncasecmp(req->line[x], boundary, strlen(boundary)))
add_header(req, "From", ot);
add_header(req, "To", of);
}
- add_header(req, "Contact", p->our_contact);
+ if (sipmethod != SIP_BYE && sipmethod != SIP_CANCEL && sipmethod != SIP_MESSAGE)
+ add_header(req, "Contact", p->our_contact);
copy_header(req, orig, "Call-ID");
add_header(req, "CSeq", tmp);
static int transmit_response_using_temp(char *callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, struct sip_request *req, char *msg)
{
struct sip_pvt *p = alloca(sizeof(*p));
+ struct sip_history *hist = NULL;
memset(p, 0, sizeof(*p));
__transmit_response(p, msg, req, 0);
+ while ((hist = p->history)) {
+ p->history = p->history->next;
+ free(hist);
+ }
+
return 0;
}
ast_copy_string(p->domain, r->domain, sizeof(p->domain));
ast_copy_string(p->opaque, r->opaque, sizeof(p->opaque));
ast_copy_string(p->qop, r->qop, sizeof(p->qop));
- p->noncecount = r->noncecount++;
+ r->noncecount++;
+ p->noncecount = r->noncecount;
memset(digest,0,sizeof(digest));
if(!build_reply_digest(p, sipmethod, digest, sizeof(digest)))
else
p->username[0] = '\0';
- if (p->expire > -1)
+ if (p->expire > -1) {
ast_sched_del(sched, p->expire);
+ p->expire = -1;
+ }
if ((expiry < 1) || (expiry > max_expiry))
expiry = max_expiry;
if (!ast_test_flag(p, SIP_REALTIME))
print_group(fd, peer->pickupgroup, 0);
ast_cli(fd, " Mailbox : %s\n", peer->mailbox);
ast_cli(fd, " VM Extension : %s\n", peer->vmexten);
- ast_cli(fd, " LastMsgsSent : %d\n", peer->lastmsgssent);
+ ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff);
ast_cli(fd, " Call limit : %d\n", peer->call_limit);
ast_cli(fd, " Dynamic : %s\n", (ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)?"Yes":"No"));
ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
if (ast_test_flag(p, SIP_PENDINGBYE)) {
/* if we can't BYE, then this is really a pending CANCEL */
if (!ast_test_flag(p, SIP_CAN_BYE))
- transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
+ transmit_request(p, SIP_CANCEL, p->ocseq, 1, 0);
/* Actually don't destroy us yet, wait for the 487 on our original
INVITE, but do set an autodestruct just in case we never get it. */
else
ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid);
transmit_request(p, SIP_ACK, seqno, 0, 0);
break;
+ case 487: /* Cancelled transaction */
+ /* We have sent CANCEL on an outbound INVITE
+ This transaction is already scheduled to be killed by sip_hangup().
+ */
+ transmit_request(p, SIP_ACK, seqno, 0, 0);
+ if (p->owner && !ignore)
+ ast_queue_hangup(p->owner);
+ else if (!ignore)
+ update_call_counter(p, DEC_CALL_LIMIT);
+ break;
case 491: /* Pending */
/* we have to wait a while, then retransmit */
/* Transmission is rescheduled, so everything should be taken care of.
We should support the retry-after at some point */
break;
case 501: /* Not implemented */
+ transmit_request(p, SIP_ACK, seqno, 0, 0);
if (p->owner)
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
break;
if (global_regattempts_max)
p->registry->regattempts = global_regattempts_max+1;
ast_sched_del(sched, r->timeout);
+ r->timeout = -1;
ast_set_flag(p, SIP_NEEDDESTROY);
break;
case 404: /* Not found */
ast_set_flag(p, SIP_NEEDDESTROY);
r->call = NULL;
ast_sched_del(sched, r->timeout);
+ r->timeout = -1;
break;
case 407: /* Proxy auth */
if ((p->authtries == MAX_AUTHTRIES) || do_register_auth(p, req, "Proxy-Authenticate", "Proxy-Authorization")) {
ast_set_flag(p, SIP_NEEDDESTROY);
r->call = NULL;
ast_sched_del(sched, r->timeout);
+ r->timeout = -1;
break;
case 200: /* 200 OK */
if (!r) {
ast_sched_del(sched, peer->pokeexpire);
if (sipmethod == SIP_INVITE) /* Does this really happen? */
transmit_request(p, SIP_ACK, seqno, 0, 0);
- ast_set_flag(p, SIP_NEEDDESTROY);
+ ast_set_flag(p, SIP_NEEDDESTROY);
/* Try again eventually */
if ((peer->lastms < 0) || (peer->lastms > peer->maxms))
ast_set_flag(p, SIP_NEEDDESTROY);
break;
+ case 487:
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req, ignore, seqno);
+ break;
case 491: /* Pending */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, ignore, seqno);
if ((resp >= 300) && (resp < 700)) {
if ((option_verbose > 2) && (resp != 487))
ast_verbose(VERBOSE_PREFIX_3 "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr));
- ast_set_flag(p, SIP_ALREADYGONE);
if (p->rtp) {
/* Immediately stop RTP */
ast_rtp_stop(p->rtp);
if (p->owner)
ast_queue_control(p->owner, AST_CONTROL_BUSY);
break;
- case 487:
- /* channel now destroyed - dec the inUse counter */
- if (owner)
- ast_queue_hangup(p->owner);
- update_call_counter(p, DEC_CALL_LIMIT);
- break;
case 482: /* SIP is incapable of performing a hairpin call, which
is yet another failure of not having a layer 2 (again, YAY
IETF for thinking ahead). So we treat this as a call
/* This is a call to ourself. Send ourselves an error code and stop
processing immediately, as SIP really has no good mechanism for
being able to call yourself */
- transmit_response(p, "482 Loop Detected", req);
- /* We do NOT destroy p here, so that our response will be accepted */
+ transmit_response_reliable(p, "482 Loop Detected", req, 1);
+ if (!p->lastinvite)
+ ast_set_flag(p, SIP_NEEDDESTROY);
return 0;
}
if (!ignore) {
transmit_fake_auth_response(p, req, p->randdata, sizeof(p->randdata), 1);
} else {
ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
- if (ignore)
- transmit_response(p, "403 Forbidden", req);
- else
- transmit_response_reliable(p, "403 Forbidden", req, 1);
+ transmit_response_reliable(p, "403 Forbidden", req, 1);
}
ast_set_flag(p, SIP_NEEDDESTROY);
p->theirtag[0] = '\0'; /* Forget their to-tag, we'll get a new one */
if (res) {
if (res < 0) {
ast_log(LOG_NOTICE, "Failed to place call for user %s, too many calls\n", p->username);
- if (ignore)
- transmit_response(p, "480 Temporarily Unavailable (Call limit)", req);
- else
- transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req, 1);
+ transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req, 1);
ast_set_flag(p, SIP_NEEDDESTROY);
}
return 0;
build_contact(p);
if (gotdest) {
- if (gotdest < 0) {
- if (ignore)
- transmit_response(p, "404 Not Found", req);
- else
- transmit_response_reliable(p, "404 Not Found", req, 1);
- update_call_counter(p, DEC_CALL_LIMIT);
- } else {
- if (ignore)
- transmit_response(p, "484 Address Incomplete", req);
- else
- transmit_response_reliable(p, "484 Address Incomplete", req, 1);
- update_call_counter(p, DEC_CALL_LIMIT);
- }
+ if (gotdest < 0)
+ transmit_response_reliable(p, "404 Not Found", req, 1);
+ else
+ transmit_response_reliable(p, "484 Address Incomplete", req, 1);
+ update_call_counter(p, DEC_CALL_LIMIT);
ast_set_flag(p, SIP_NEEDDESTROY);
+ return 0;
} else {
/* If no extension was specified, use the s one */
if (ast_strlen_zero(p->exten))
} else {
if (p && !ast_test_flag(p, SIP_NEEDDESTROY) && !ignore) {
if (!p->jointcapability) {
- if (ignore)
- transmit_response(p, "488 Not Acceptable Here (codec error)", req);
- else
- transmit_response_reliable(p, "488 Not Acceptable Here (codec error)", req, 1);
- ast_set_flag(p, SIP_NEEDDESTROY);
+ transmit_response_reliable(p, "488 Not Acceptable Here (codec error)", req, 1);
} else {
ast_log(LOG_NOTICE, "Unable to create/find channel\n");
- if (ignore)
- transmit_response(p, "503 Unavailable", req);
- else
- transmit_response_reliable(p, "503 Unavailable", req, 1);
- ast_set_flag(p, SIP_NEEDDESTROY);
+ transmit_response_reliable(p, "503 Unavailable", req, 1);
}
+ ast_set_flag(p, SIP_NEEDDESTROY);
}
}
return res;
struct ast_channel *bridged_to;
char iabuf[INET_ADDRSTRLEN];
- if (p->pendinginvite && !ast_test_flag(p, SIP_OUTGOING) && !ignore)
+ /* If we have an INCOMING invite that we haven't answered, terminate that transaction */
+ if (p->pendinginvite && !ast_test_flag(p, SIP_OUTGOING) && !ignore && !p->owner)
transmit_response_reliable(p, "487 Request Terminated", &p->initreq, 1);
copy_request(&p->initreq, req);
if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
char iabuf[INET_ADDRSTRLEN];
- ast_log(LOG_ERROR, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension\n", p->exten, p->context, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr));
+ ast_log(LOG_NOTICE, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension\n", p->exten, p->context, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr));
transmit_response(p, "404 Not found", req);
ast_set_flag(p, SIP_NEEDDESTROY);
return 0;
{
/* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things
relatively static */
- struct sip_request resp;
char *cmd;
char *cseq;
char *useragent;
char *e;
int error = 0;
- /* Clear out potential response */
- memset(&resp, 0, sizeof(resp));
-
/* Get Method and Cseq */
cseq = get_header(req, "Cseq");
cmd = req->header[0];
error = 1;
}
if (error) {
- if (!p->initreq.header) /* New call */
+ if (!p->initreq.headers) /* New call */
ast_set_flag(p, SIP_NEEDDESTROY); /* Make sure we destroy this dialog */
return -1;
}
goto retrylock;
}
if (!lockretry) {
- ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", p->owner->name);
+ ast_log(LOG_ERROR, "We could NOT get the channel lock for %s - Call ID %s! \n", p->owner->name, p->callid);
ast_log(LOG_ERROR, "SIP MESSAGE JUST IGNORED: %s \n", req.data);
ast_log(LOG_ERROR, "BAD! BAD! BAD!\n");
return 1;
time(&peer->lastmsgcheck);
/* Return now if it's the same thing we told them last time */
- if (((newmsgs << 8) | (oldmsgs)) == peer->lastmsgssent) {
+ if (((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs)) == peer->lastmsgssent) {
return 0;
}
ast_log(LOG_WARNING, "Unable to build sip pvt data for MWI\n");
return -1;
}
- peer->lastmsgssent = ((newmsgs << 8) | (oldmsgs));
+ peer->lastmsgssent = ((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs));
if (create_addr_from_peer(p, peer)) {
/* Maybe they're not registered, etc. */
sip_destroy(p);
peer->call = NULL;
return 0;
}
- if (peer->call > 0) {
+ if (peer->call) {
if (sipdebug)
ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
sip_destroy(peer->call);
sip_destroy(iterator->call);
}
ASTOBJ_UNLOCK(iterator);
+
} while(0));
+
ASTOBJ_CONTAINER_DESTROYALL(&userl, sip_destroy_user);
ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy);
ASTOBJ_CONTAINER_MARKALL(&peerl);
while (p) {
pl = p;
p = p->next;
- /* Free associated memory */
- ast_mutex_destroy(&pl->lock);
- if (pl->chanvars) {
- ast_variables_destroy(pl->chanvars);
- pl->chanvars = NULL;
- }
- free(pl);
+ __sip_destroy(pl, 1);
}
iflist = NULL;
ast_mutex_unlock(&iflock);
stop if now if appropriate */
if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
ast_moh_stop(ast_bridged_channel(p->subs[SUB_THREEWAY].owner));
- if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
+ if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
}
if (p->subs[SUB_REAL].owner->cdr) {
ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
unalloc_sub(p, SUB_THREEWAY);
} else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
- if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
+ if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
}
ast_moh_stop(ast_bridged_channel(p->subs[SUB_THREEWAY].owner));
}
#endif
res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_RINGTONE);
- if (chan->_state != AST_STATE_UP) {
- if ((chan->_state != AST_STATE_RING) ||
- ((p->sig != SIG_FXSKS) &&
+ if (chan->_state != AST_STATE_UP && chan->_state != AST_STATE_RING) {
+ if ((p->sig != SIG_FXSKS) &&
(p->sig != SIG_FXSLS) &&
- (p->sig != SIG_FXSGS)))
+ (p->sig != SIG_FXSGS))
ast_setstate(chan, AST_STATE_RINGING);
}
break;
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
- zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
+ res = zt_set_hook(i->subs[SUB_REAL].zfd, ZT_OFFHOOK);
+ if (res && (errno == EBUSY))
+ break;
if (i->cidspill) {
/* Cancel VMWI spill */
free(i->cidspill);
};
/* you must call misdn_cfg_init before any other function of this header file */
-void misdn_cfg_init(int max_ports);
+int misdn_cfg_init(int max_ports);
void misdn_cfg_reload(void);
void misdn_cfg_destroy(void);
{
int i;
- cb_log(1,stack->port,"find_free_chan: req_chan:%d\n",channel);
+ cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel);
if (channel < 0 || channel > MAX_BCHANS) {
- cb_log(4, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
+ cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
return 0;
}
for (i = 0; i < stack->b_num; i++) {
if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 Dchannel ;) and work with chan preselection */
if (!stack->channels[i]) {
- cb_log (1, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
+ cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
stack->channels[i] = 1;
return i+1;
}
}
}
- cb_log (4, stack->port, " !! NO FREE CHAN IN STACK\n");
+ cb_log (1, stack->port, " !! NO FREE CHAN IN STACK\n");
dump_chan_list(stack);
return 0;
stack;
stack=stack->next) {
- if ( !stack->ptp && !check) return 1;
-
if (stack->port == port) {
if (stack->blocked) {
return 0;
}
} else {
- if ( stack->l1link)
+ if ( !check || stack->l1link )
return 1;
else {
cb_log(0,port, "Port down PMP\n");
if (stack->ptp)
set_chan_in_stack(stack, bc->channel);
else
- cb_log(0,stack->port," --> PTMP but channel requested\n");
+ cb_log(3,stack->port," --> PTMP but channel requested\n");
} else {
}
cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
- cb_log(1, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
+ cb_log(4, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
misdn_lib_log_ies(bc);
switch (event) {
struct misdn_stack *stack=get_stack_by_bc(bc);
- cb_log(1, stack?stack->port:0,"ec_enable\n");
+ cb_log(4, stack?stack->port:0,"ec_enable\n");
if (!misdn_cap_is_speech(bc->capability)) {
cb_log(1, stack?stack->port:0, " --> no speech? cannot enable EC\n");
}
if (bc->ec_enable) {
- cb_log(1, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d training:%d\n",bc->ec_deftaps, bc->ec_training);
+ cb_log(3, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d training:%d\n",bc->ec_deftaps, bc->ec_training);
switch (bc->ec_deftaps) {
case 4:
{
struct misdn_stack *stack=get_stack_by_bc(bc);
- cb_log(1, stack?stack->port:0,"ec_disable\n");
+ cb_log(4, stack?stack->port:0," --> ec_disable\n");
if (!misdn_cap_is_speech(bc->capability)) {
cb_log(1, stack?stack->port:0, " --> no speech? cannot disable EC\n");
}
if ( ! bc->ec_enable) {
- cb_log(1, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n");
+ cb_log(3, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n");
manager_ph_control(bc, ECHOCAN_OFF, 0);
}
}
manager_ph_control(bc, CMX_RECEIVE_OFF, 0);
manager_ph_control(bc, CMX_CONF_JOIN, conf_id);
- cb_log(1,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id);
+ cb_log(3,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id);
char data[16];
int len=15;
manager_ph_control(bc, CMX_RECEIVE_ON, 0);
manager_ph_control(bc, CMX_CONF_SPLIT, conf_id);
- cb_log(1,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id);
+ cb_log(4,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id);
}
void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) {
int conf_id=bc1->pid +1;
- cb_log(1, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
+ cb_log(4, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
struct misdn_bchannel *bc_list[]={
bc1,bc2,NULL
for (bc=bc_list; *bc; *bc++) {
(*bc)->conf_id=conf_id;
- cb_log(1, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
+ cb_log(4, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
switch((*bc)->bc_state) {
case BCHAN_ACTIVATED:
void misdn_lib_echo(struct misdn_bchannel *bc, int onoff)
{
- cb_log(1,bc->port, " --> ECHO %s\n", onoff?"ON":"OFF");
+ cb_log(3,bc->port, " --> ECHO %s\n", onoff?"ON":"OFF");
manager_ph_control(bc, onoff?CMX_ECHO_ON:CMX_ECHO_OFF, 0);
}
enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
}
+
+ if (bc->sending_complete) {
+ enc_ie_complete(&setup->BEARER,msg, bc->sending_complete, nt, bc);
+ }
#if DEBUG
printf("Building SETUP Msg\n");
{ "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE },
{ "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "yes", NONE },
{ "reject_cause", MISDN_CFG_REJECT_CAUSE, MISDN_CTYPE_INT, "21", NONE },
- { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "no", NONE },
{ "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE },
{ "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE },
{ "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE },
ast_mutex_destroy(&config_mutex);
}
-void misdn_cfg_init (int this_max_ports)
+int misdn_cfg_init (int this_max_ports)
{
char config[] = "misdn.conf";
char *cat, *p;
if (!(cfg = AST_LOAD_CFG(config))) {
ast_log(LOG_WARNING,"no misdn.conf ?\n");
- return;
+ return -1;
}
misdn_cfg_lock();
misdn_cfg_unlock();
AST_DESTROY_CFG(cfg);
+
+ return 0;
}
else
category->root = variable;
category->last = variable;
+ while (category->last->next)
+ category->last = category->last->next;
}
void ast_variables_destroy(struct ast_variable *v)
v = cat->root;
cat->root = NULL;
+ cat->last = NULL;
return v;
}
if ((f = fopen(fn, "w"))) {
#endif
if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Saving '%s': ", fn);
+ 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);
+ if (strcmp(configfile, fn))
+ fprintf(f, ";! Filename: %s (%s)\n", configfile, fn);
+ else
+ fprintf(f, ";! Filename: %s\n", configfile);
fprintf(f, ";! Generator: %s\n", generator);
fprintf(f, ";! Creation Date: %s", date);
fprintf(f, ";!\n");
}
} else {
if (option_debug)
- printf("Unable to open for writing: %s\n", fn);
+ ast_log(LOG_DEBUG, "Unable to open for writing: %s\n", fn);
if (option_verbose > 1)
- printf( "Unable to write (%s)", strerror(errno));
+ ast_verbose(VERBOSE_PREFIX_2 "Unable to write (%s)", strerror(errno));
return -1;
}
fclose(f);
;
; List canonical entries here
;
-;exten => 12564286000,1,Macro(std-exten,6000,IAX2/foo)
+;exten => 12564286000,1,Macro(stdexten,6000,IAX2/foo)
;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7})
[dundi-e164-customers]
; friends expire within this number of seconds instead of the
; registration interval.
-;rtignoreexpire=yes ; When reading a peer from Realtime, if the peer's registration
+;rtignoreregexpire=yes ; When reading a peer from Realtime, if the peer's registration
; has expired based on its registration interval, used the stored
; address information regardless. (yes|no)
; Realms MUST be globally unique according to RFC 3261
; Set this to your host name or domain name
bindport=5060 ; UDP Port to bind to (SIP standard port is 5060)
+ ; bindport is the local UDP port that Asterisk will listen on
bindaddr=0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all)
srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; Note: Asterisk only uses the first host
;usereqphone=yes ; This provider requires ";user=phone" on URI
;call-limit=5 ; permit only 5 simultaneous outgoing calls to this peer
;outboundproxy=proxy.provider.domain ; send outbound signaling to this proxy, not directly to the peer
+;port=80 ; The port number we want to connect to on the remote side
;------------------------------------------------------------------------------
; Definitions of locally connected SIP phones
${CDR(userfield)} The channels uses specified field.
In addition, you can set your own extra variables by using Set(CDR(name)=value).
-
-______________________________
-cdr_csv2
-------------------------------
-
-This module is an experimental new cdr module to demonstrate the cdr vars.
-usage(
-
-*) Create a file called cdr.conf and place it in your /etc/asterisk (or wherever your config files are) in the [cdr_csv2] section.
-*) Add an entry called format to indicate any format you want for the output.
-
-The following format string will emulate the regular cdr file format:
-[cdr_csv2]
-
-format => "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration)}","${CDR(billsec)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}"
-
-You can put anything you want as the value of format incuding new cdr vars you make up or any global variables.
-
+These variables can be output into a text-format CDR by using the cdr_custom
+CDR driver; see the cdr_custom.conf.sample file in the configs directory for
+an example of how to do this.
- Configuration
- Dial and Options String
- misdn cli commands
+- mISDN Variables
- Debugging and sending Bugreports
- Examples
- Known working Configurations
msn (callerid) of the Phone to send the text to.
+mISDN Variables
+---------------
+
+mISDN Exports/Imports a few Variables:
+
+- MISDN_ADDRESS_COMPLETE : Is either set to 1 from the Provider, or you
+ can set it to 1 to force a sending complete.
+
Debugging and sending bug reports
---------------------------------
/* Optimize by sending the frame we just got
on the next read, thus eliminating the douple
copy */
+ if (swap)
+ ast_swapcopy_samples(f->data, f->data, f->samples);
s->opt = f;
return 0;
} else {
we were unable to optimize because there was still
some cruft left over. Lets just drop the cruft so
we can move to a fully optimized path */
+ if (swap)
+ ast_swapcopy_samples(f->data, f->data, f->samples);
s->len = 0;
s->opt = f;
return 0;
so when ->priority is set, it will get incremented before
finding the next priority to run
*/
+#define AST_FLAG_NOTNEW (1 << 10) /*!< see bug:7855 incorrect Newchannel event generation */
/* @} */
#define AST_FEATURE_PLAY_WARNING (1 << 0)
struct ast_variable *ast_variable_new(const char *name, const char *value);
void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
-int ast_variable_delete(struct ast_config *cfg, char *category, char *variable, char *value);
int config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator);
now += o->retrytime;
if (o->callingpid && (o->callingpid == ast_mainpid)) {
safe_append(o, time(NULL), "DelayedRetry");
- free_outgoing(o);
ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn);
+ free_outgoing(o);
} else {
/* Increment retries */
o->retries++;
int audio[2];
int x;
int res;
- sigset_t signal_set;
+ sigset_t signal_set, old_set;
if (!strncasecmp(script, "agi://", 6))
return launch_netscript(script, argv, fds, efd, opid);
return -1;
}
}
+
+ /* Block SIGHUP during the fork - prevents a race */
+ sigfillset(&signal_set);
+ pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
pid = fork();
if (pid < 0) {
ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
} else {
close(STDERR_FILENO + 1);
}
-
+
+ /* Before we unblock our signals, return our trapped signals back to the defaults */
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGURG, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGPIPE, SIG_DFL);
+ signal(SIGXFSZ, SIG_DFL);
+
/* unblock important signal handlers */
- if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
+ if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
_exit(1);
}
fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
_exit(1);
}
+ pthread_sigmask(SIG_SETMASK, &old_set, NULL);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
fds[0] = toast[0];
ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
memset(&config, 0, sizeof(struct ast_bridge_config));
- ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
- ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
- config.timelimit = 0;
- config.play_warning = 0;
- config.warning_freq = 0;
- config.warning_sound=NULL;
res = ast_bridge_call(chan, peer, &config);
/* Simulate the PBX hanging up */
ast_unregister_features();
var = ast_variable_browse(cfg, "applicationmap");
while(var) {
- char *tmp_val=strdup(var->value);
+ char *tmp_val_orig=strdup(var->value);
+ char *tmp_val = tmp_val_orig;
char *exten, *party=NULL, *app=NULL, *app_args=NULL;
if (!tmp_val) {
if (!(app && strlen(app)) || !(exten && strlen(exten)) || !(party && strlen(party)) || !(var->name && strlen(var->name))) {
ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",app,exten,party,var->name);
- free(tmp_val);
+ free(tmp_val_orig);
var = var->next;
continue;
}
}
if (!feature) {
ast_log(LOG_NOTICE, "Malloc failed at feature mapping\n");
- free(tmp_val);
+ free(tmp_val_orig);
var = var->next;
continue;
}
ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
ast_copy_string(feature->app,app,FEATURE_APP_LEN);
ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
- free(tmp_val);
if (app_args)
ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
else {
ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
+ free(tmp_val_orig);
var = var->next;
continue;
}
ast_register_feature(feature);
if (option_verbose >=1) ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);
+ free(tmp_val_orig);
}
var = var->next;
}
if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) {
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, state->origwfmt);
}
- state->save_pos = state->pos + 1;
+ state->save_pos = state->pos;
}
}
int tries;
if (state->save_pos) {
- state->pos = state->save_pos - 1;
+ state->pos = state->save_pos;
state->save_pos = 0;
- } else {
- /* Try 20 times to find something good */
- for (tries=0;tries < 20;tries++) {
- state->samples = 0;
- if (chan->stream) {
- ast_closestream(chan->stream);
- chan->stream = NULL;
- state->pos++;
- }
+ }
- if (ast_test_flag(state->class, MOH_RANDOMIZE))
- state->pos = rand();
+ state->samples = 0;
+ if (chan->stream) {
+ ast_closestream(chan->stream);
+ chan->stream = NULL;
+ state->pos++;
+ state->pos %= state->class->total_files;
+ }
- state->pos %= state->class->total_files;
+ if (ast_test_flag(state->class, MOH_RANDOMIZE)) {
+ /* Try 20 times to find something good */
+ for (tries = 0; tries < 20; tries++) {
+ state->pos = rand() % state->class->total_files;
/* check to see if this file's format can be opened */
if (ast_fileexists(state->class->filearray[state->pos], NULL, NULL) > 0)
break;
-
}
}
- state->pos = state->pos % state->class->total_files;
-
if (!ast_openstream_full(chan, state->class->filearray[state->pos], chan->language, 1)) {
ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", state->class->filearray[state->pos], strerror(errno));
state->pos++;
+ state->pos %= state->class->total_files;
return -1;
}
/* initialize */
memset(state, 0, sizeof(struct moh_files_state));
state->class = class;
+ if (ast_test_flag(state->class, MOH_RANDOMIZE))
+ state->pos = rand() % class->total_files;
}
state->origwfmt = chan->writeformat;
int argc = 0;
DIR *dir = NULL;
struct dirent *de;
+ sigset_t signal_set, old_set;
if (!strcasecmp(class->dir, "nodir")) {
if (time(NULL) - class->start < respawn_time) {
sleep(respawn_time - (time(NULL) - class->start));
}
+
+ /* Block signals during the fork() */
+ sigfillset(&signal_set);
+ pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
+
time(&class->start);
class->pid = fork();
if (class->pid < 0) {
if (option_highpriority)
ast_set_priority(0);
+ /* Reset ignored signals back to default */
+ signal(SIGPIPE, SIG_DFL);
+ pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+
close(fds[0]);
/* Stdout goes to pipe */
dup2(fds[1], STDOUT_FILENO);
_exit(1);
} else {
/* Parent */
+ pthread_sigmask(SIG_SETMASK, &old_set, NULL);
close(fds[1]);
}
return fds[0];
ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ stmt = NULL;
ast_mutex_lock(&obj->lock);
obj->up = 0;
f = _f;
}
ast_rtp_raw_write(rtp, f, codec);
+ if (f != _f)
+ ast_frfree(f);
}
return 0;
%spy-zap.gsm%Zap
+; Silence directory
+
+%1.gsm%1 second of silence
+
+%2.gsm%2 seconds of silence
+
+%3.gsm%3 seconds of silence
+
+%4.gsm%4 seconds of silence
+
+%5.gsm%5 seconds of silence
+
+%6.gsm%6 seconds of silence
+
+%7.gsm%7 seconds of silence
+
+%8.gsm%8 seconds of silence
+
+%9.gsm%9 seconds of silence
+
+%10.gsm%10 seconds of silence
+