aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--apps/app_queue.c11
-rw-r--r--apps/app_speech_utils.c1
-rw-r--r--apps/app_voicemail.c184
-rw-r--r--apps/app_waitforsilence.c29
-rw-r--r--channels/chan_dahdi.c5
-rw-r--r--channels/chan_sip.c44
-rw-r--r--include/asterisk/audiohook.h2
-rw-r--r--main/audiohook.c10
-rw-r--r--main/features.c7
10 files changed, 241 insertions, 54 deletions
diff --git a/Makefile b/Makefile
index 6eb716904..aaa5d760b 100644
--- a/Makefile
+++ b/Makefile
@@ -887,3 +887,5 @@ asterisk.pdf:
$(MAKE) -C doc/tex asterisk.pdf
.PHONY: menuselect menuselect.makeopts main sounds clean dist-clean distclean all prereqs cleantest uninstall _uninstall uninstall-all pdf dont-optimize $(SUBDIRS_INSTALL) $(SUBDIRS_DIST_CLEAN) $(SUBDIRS_CLEAN) $(SUBDIRS_UNINSTALL) $(SUBDIRS) $(MOD_SUBDIRS_EMBED_LDSCRIPT) $(MOD_SUBDIRS_EMBED_LDFLAGS) $(MOD_SUBDIRS_EMBED_LIBS) badshell main/version.c include/asterisk/version.h installdirs
+
+FORCE:
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 98238620a..516664e66 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3057,6 +3057,7 @@ struct queue_transfer_ds {
struct queue_ent *qe;
struct member *member;
int starttime;
+ int callcompletedinsl;
};
static void queue_transfer_destroy(void *data)
@@ -3088,11 +3089,14 @@ static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struc
struct queue_ent *qe = qtds->qe;
struct member *member = qtds->member;
int callstart = qtds->starttime;
+ int callcompletedinsl = qtds->callcompletedinsl;
struct ast_datastore *datastore;
ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld",
new_chan->exten, new_chan->context, (long) (callstart - qe->start),
(long) (time(NULL) - callstart));
+
+ update_queue(qe->parent, member, callcompletedinsl);
if (!(datastore = ast_channel_datastore_find(new_chan, &queue_transfer_info, NULL))) {
ast_log(LOG_WARNING, "Can't find the queue_transfer datastore.\n");
@@ -3116,7 +3120,7 @@ static int attended_transfer_occurred(struct ast_channel *chan)
/*! \brief create a datastore for storing relevant info to log attended transfers in the queue_log
*/
-static void setup_transfer_datastore(struct queue_ent *qe, struct member *member, int starttime)
+static void setup_transfer_datastore(struct queue_ent *qe, struct member *member, int starttime, int callcompletedinsl)
{
struct ast_datastore *ds;
struct queue_transfer_ds *qtds = ast_calloc(1, sizeof(*qtds));
@@ -3137,6 +3141,7 @@ static void setup_transfer_datastore(struct queue_ent *qe, struct member *member
/* This member is refcounted in try_calling, so no need to add it here, too */
qtds->member = member;
qtds->starttime = starttime;
+ qtds->callcompletedinsl = callcompletedinsl;
ds->data = qtds;
ast_channel_datastore_add(qe->chan, ds);
ast_channel_unlock(qe->chan);
@@ -3814,7 +3819,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
time(&callstart);
- setup_transfer_datastore(qe, member, callstart);
+ setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
/* If the queue member did an attended transfer, then the TRANSFER already was logged in the queue_log
@@ -3843,11 +3848,11 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
ast_channel_datastore_free(transfer_ds);
}
ast_channel_unlock(qe->chan);
+ update_queue(qe->parent, member, callcompletedinsl);
}
if (bridge != AST_PBX_NO_HANGUP_PEER)
ast_hangup(peer);
- update_queue(qe->parent, member, callcompletedinsl);
res = bridge ? bridge : 1;
ao2_ref(member, -1);
}
diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c
index 221d2eb5c..6ba68c3b4 100644
--- a/apps/app_speech_utils.c
+++ b/apps/app_speech_utils.c
@@ -727,6 +727,7 @@ static int speech_background(struct ast_channel *chan, void *data)
speech->results->text = ast_strdup(dtmf);
speech->results->grammar = ast_strdup("dtmf");
}
+ ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
}
/* See if it was because they hung up */
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 41c51f709..e06ca84b1 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -3230,7 +3230,8 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu
pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
- pbx_builtin_setvar_helper(ast, "VM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
+ pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
+ ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
pbx_builtin_setvar_helper(ast, "VM_DATE", date);
@@ -3277,6 +3278,90 @@ static const struct ast_tm *vmu_tm(const struct ast_vm_user *vmu, struct ast_tm
return tm;
}
+/*!\brief Check if the string would need encoding within the MIME standard, to
+ * avoid confusing certain mail software that expects messages to be 7-bit
+ * clean.
+ */
+static int check_mime(const char *str)
+{
+ for (; *str; str++) {
+ if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*!\brief Encode a string according to the MIME rules for encoding strings
+ * that are not 7-bit clean or contain control characters.
+ *
+ * Additionally, if the encoded string would exceed the MIME limit of 76
+ * characters per line, then the encoding will be broken up into multiple
+ * sections, separated by a space character, in order to facilitate
+ * breaking up the associated header across multiple lines.
+ *
+ * \param start A string to be encoded
+ * \param end An expandable buffer for holding the result
+ * \param preamble The length of the first line already used for this string,
+ * to ensure that each line maintains a maximum length of 76 chars.
+ * \param postamble the length of any additional characters appended to the
+ * line, used to ensure proper field wrapping.
+ * \retval The encoded string.
+ */
+static char *encode_mime_str(const char *start, char *end, size_t endsize, size_t preamble, size_t postamble)
+{
+ char tmp[80];
+ int first_section = 1;
+ size_t endlen = 0, tmplen = 0;
+ *end = '\0';
+
+ tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
+ for (; *start; start++) {
+ int need_encoding = 0;
+ if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
+ need_encoding = 1;
+ }
+ if ((first_section && need_encoding && preamble + tmplen > 70) ||
+ (first_section && !need_encoding && preamble + tmplen > 72) ||
+ (!first_section && need_encoding && tmplen > 70) ||
+ (!first_section && !need_encoding && tmplen > 72)) {
+ /* Start new line */
+ endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
+ tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
+ first_section = 0;
+ }
+ if (need_encoding && *start == ' ') {
+ tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
+ } else if (need_encoding) {
+ tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
+ } else {
+ tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
+ }
+ }
+ snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
+ return end;
+}
+
+/*!
+ * \brief Creates the email file to be sent to indicate a new voicemail exists for a user.
+ * \param p The output file to generate the email contents into.
+ * \param srcemail The email address to send the email to, presumably the email address for the owner of the mailbox.
+ * \param vmu The voicemail user who is sending the voicemail.
+ * \param msgnum The message index in the mailbox folder.
+ * \param context
+ * \param mailbox The voicemail box to read the voicemail to be notified in this email.
+ * \param cidnum The caller ID number.
+ * \param cidname The caller ID name.
+ * \param attach the name of the sound file to be attached to the email, if attach_user_voicemail == 1.
+ * \param format The message sound file format. i.e. .wav
+ * \param duration The time of the message content, in seconds.
+ * \param attach_user_voicemail if 1, the sound file is attached to the email.
+ * \param chan
+ * \param category
+ * \param imap if == 1, indicates the target folder for the email notification to be sent to will be an IMAP mailstore. This causes additional mailbox headers to be set, which would facilitate searching for the email in the destination IMAP folder.
+ *
+ * The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.
+ */
static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap)
{
char date[256];
@@ -3288,8 +3373,8 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
char tmpcmd[256];
struct ast_tm tm;
char enc_cidnum[256] = "", enc_cidname[256] = "";
- char *passdata2;
- size_t len_passdata;
+ char *passdata = NULL, *passdata2;
+ size_t len_passdata = 0, len_passdata2, tmplen;
char *greeting_attachment;
#ifdef IMAP_STORAGE
@@ -3298,6 +3383,17 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
#define ENDL "\n"
#endif
+ /* One alloca for multiple fields */
+ len_passdata2 = strlen(vmu->fullname);
+ if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
+ len_passdata2 = tmplen;
+ }
+ if ((tmplen = strlen(fromstring)) > len_passdata2) {
+ len_passdata2 = tmplen;
+ }
+ len_passdata2 = len_passdata2 * 3 + 200;
+ passdata2 = alloca(len_passdata2);
+
if (!ast_strlen_zero(cidnum)) {
strip_control(cidnum, enc_cidnum, sizeof(enc_cidnum));
}
@@ -3325,15 +3421,25 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
if (!ast_strlen_zero(fromstring)) {
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
- char *passdata;
- int vmlen = strlen(fromstring) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata, vmlen, category);
- pbx_substitute_variables_helper(ast, fromstring, passdata, vmlen);
- len_passdata = strlen(passdata) * 2 + 3;
- passdata2 = alloca(len_passdata);
- fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata), who);
+ char *ptr;
+ memset(passdata2, 0, len_passdata2);
+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category);
+ pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
+ len_passdata = strlen(passdata2) * 3 + 300;
+ passdata = alloca(len_passdata);
+ if (check_mime(passdata2)) {
+ int first_line = 1;
+ encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
+ while ((ptr = strchr(passdata, ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
+ first_line = 0;
+ passdata = ptr + 1;
+ }
+ fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
+ } else {
+ fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata2), who);
+ }
ast_channel_free(ast);
} else {
ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
@@ -3341,19 +3447,48 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
} else {
fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
}
- len_passdata = strlen(vmu->fullname) * 2 + 3;
- passdata2 = alloca(len_passdata);
- fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata), vmu->email);
+
+ if (check_mime(vmu->fullname)) {
+ int first_line = 1;
+ char *ptr;
+ encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
+ while ((ptr = strchr(passdata2, ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
+ first_line = 0;
+ passdata2 = ptr + 1;
+ }
+ fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
+ } else {
+ fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
+ }
if (!ast_strlen_zero(emailsubject)) {
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
- char *passdata;
int vmlen = strlen(emailsubject) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata, vmlen, category);
- pbx_substitute_variables_helper(ast, emailsubject, passdata, vmlen);
- fprintf(p, "Subject: %s" ENDL, passdata);
+ /* Only allocate more space if the previous was not large enough */
+ if (vmlen > len_passdata) {
+ passdata = alloca(vmlen);
+ len_passdata = vmlen;
+ }
+
+ memset(passdata, 0, len_passdata);
+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, len_passdata, category);
+ pbx_substitute_variables_helper(ast, emailsubject, passdata, len_passdata);
+ if (check_mime(passdata)) {
+ int first_line = 1;
+ char *ptr;
+ encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
+ while ((ptr = strchr(passdata2, ' '))) {
+ *ptr = '\0';
+ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
+ first_line = 0;
+ passdata2 = ptr + 1;
+ }
+ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
+ } else {
+ fprintf(p, "Subject: %s" ENDL, passdata);
+ }
ast_channel_free(ast);
} else {
ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
@@ -6894,8 +7029,11 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm
/* Notify the user that the temp greeting is set and give them the option to remove it */
snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
- if (ast_fileexists(prefile, NULL, NULL) > 0)
+ RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
+ if (ast_fileexists(prefile, NULL, NULL) > 0) {
ast_play_and_wait(chan, "vm-tempgreetactive");
+ }
+ DISPOSE(prefile, -1);
}
/* Play voicemail intro - syntax is different for different languages */
@@ -7186,9 +7324,11 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
default:
cmd = 0;
snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
+ RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
if (ast_fileexists(prefile, NULL, NULL)) {
cmd = ast_play_and_wait(chan, "vm-tmpexists");
}
+ DISPOSE(prefile, -1);
if (!cmd) {
cmd = ast_play_and_wait(chan, "vm-options");
}
diff --git a/apps/app_waitforsilence.c b/apps/app_waitforsilence.c
index e45f24344..38d98fa5d 100644
--- a/apps/app_waitforsilence.c
+++ b/apps/app_waitforsilence.c
@@ -69,7 +69,7 @@ static char *descrip =
"TIMEOUT - if exited without silence detected after timeout\n";
static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstart, int timeout) {
- struct ast_frame *f;
+ struct ast_frame *f = NULL;
int dspsilence = 0;
static int silencethreshold = 128;
int rfmt = 0;
@@ -78,48 +78,47 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
time_t now;
rfmt = chan->readformat; /* Set to linear mode */
- res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
- if (res < 0) {
+ if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
return -1;
}
- sildet = ast_dsp_new(); /* Create the silence detector */
- if (!sildet) {
+ /* Create the silence detector */
+ if (!(sildet = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
return -1;
}
ast_dsp_set_threshold(sildet, silencethreshold);
/* Await silence... */
- f = NULL;
- for(;;) {
+ for (;;) {
/* Start with no silence received */
dspsilence = 0;
res = ast_waitfor(chan, silencereqd);
/* Must have gotten a hangup; let's exit */
- if (res <= 0) {
- f = NULL;
+ if (res < 0) {
+ pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
break;
}
/* We waited and got no frame; sounds like digital silence or a muted digital channel */
- if (!res) {
+ if (res == 0) {
dspsilence = silencereqd;
} else {
/* Looks like we did get a frame, so let's check it out */
- f = ast_read(chan);
- if (!f)
+ if (!(f = ast_read(chan))) {
+ pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
break;
- if (f && f->frametype == AST_FRAME_VOICE) {
+ }
+ if (f->frametype == AST_FRAME_VOICE) {
ast_dsp_silence(sildet, f, &dspsilence);
- ast_frfree(f);
}
+ ast_frfree(f);
}
- ast_verb(3, "Got %dms silence< %dms required\n", dspsilence, silencereqd);
+ ast_verb(6, "Got %dms silence< %dms required\n", dspsilence, silencereqd);
if (dspsilence >= silencereqd) {
ast_verb(3, "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd);
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 46e74fa89..37ff01b3e 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -13547,8 +13547,9 @@ static int process_dahdi(struct dahdi_chan_conf *confp, struct ast_variable *v,
return -1;
} else if (!strcasecmp(v->name, "buffers")) {
int res;
- char policy[8] = "";
- res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
+ char policy[21] = "";
+
+ res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
if (res != 2) {
ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
confp->chan.buf_no = numbufs;
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 925abb1d9..779d3046d 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -189,6 +189,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define XMIT_ERROR -2
+#define SIP_RESERVED ";/?:@&=+$,# "
+
/* #define VOCAL_DATA_HACK */
#define DEFAULT_DEFAULT_EXPIRY 120
@@ -3499,8 +3501,10 @@ static void register_peer_exten(struct sip_peer *peer, int onoff)
context = global_regcontext;
}
if (onoff) {
- ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
- ast_strdup(peer->name), ast_free_ptr, "SIP");
+ if (!ast_exists_extension(NULL, context, ext, 1, NULL)) {
+ ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
+ ast_strdup(peer->name), ast_free, "SIP");
+ }
} else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, NULL, "", E_MATCH)) {
ast_context_remove_extension(context, ext, 1, NULL);
}
@@ -6136,8 +6140,10 @@ static int sip_register(const char *value, int lineno)
enum sip_transport transport = SIP_TRANSPORT_UDP;
char buf[256] = "";
char *username = NULL;
+ char *port = NULL;
char *hostname=NULL, *secret=NULL, *authuser=NULL;
char *callback=NULL;
+ char *reserved = NULL;
if (!value)
return -1;
@@ -6162,12 +6168,34 @@ static int sip_register(const char *value, int lineno)
if (authuser)
*authuser++ = '\0';
}
+ if ((reserved = strpbrk(username, SIP_RESERVED))) {
+ goto invalid_char;
+ }
+ if (!ast_strlen_zero(secret) && (reserved = strpbrk(secret, SIP_RESERVED))) {
+ goto invalid_char;
+ }
+ if (!ast_strlen_zero(authuser) && (reserved = strpbrk(authuser, SIP_RESERVED))) {
+ goto invalid_char;
+ }
/* split host[:port][/contact] */
callback = strchr(hostname, '/');
if (callback)
*callback++ = '\0';
if (ast_strlen_zero(callback))
callback = "s";
+ /* Separate host from port when checking for reserved characters
+ */
+ if ((port = strchr(hostname, ':'))) {
+ *port = '\0';
+ }
+ if ((reserved = strpbrk(hostname, SIP_RESERVED))) {
+ goto invalid_char;
+ }
+ /* And then re-merge the host and port so they are stored correctly
+ */
+ if (port) {
+ *port = ':';
+ }
if (!(reg = ast_calloc(1, sizeof(*reg)))) {
ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
return -1;
@@ -6201,6 +6229,10 @@ static int sip_register(const char *value, int lineno)
ASTOBJ_CONTAINER_LINK(&regl, reg); /* Add the new registry entry to the list */
registry_unref(reg); /* release the reference given by ASTOBJ_INIT. The container has another reference */
return 0;
+
+invalid_char:
+ ast_log(LOG_WARNING, "A reserved character ('%c') was used in a \"register\" line. This registration will not occur\n", *reserved);
+ return -1;
}
/*! \brief Parse multiline SIP headers into one header
@@ -10063,11 +10095,11 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\n", peer->name);
/* Is this a new IP address for us? */
- if (inaddrcmp(&peer->addr, &oldsin)) {
- sip_poke_peer(peer);
- ast_verb(3, "Registered SIP '%s' at %s port %d expires %d\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), expiry);
- register_peer_exten(peer, TRUE);
+ if (VERBOSITY_ATLEAST(2) && inaddrcmp(&peer->addr, &oldsin)) {
+ ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s port %d\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port));
}
+ sip_poke_peer(peer);
+ register_peer_exten(peer, 1);
/* Save User agent */
useragent = get_header(req, "User-Agent");
diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h
index ba5d3b899..d8a6eac6a 100644
--- a/include/asterisk/audiohook.h
+++ b/include/asterisk/audiohook.h
@@ -60,6 +60,8 @@ enum ast_audiohook_flags {
AST_AUDIOHOOK_TRIGGER_SYNC = (1 << 2), /*!< Audiohook wants to be triggered when both sides have combined audio available */
};
+#define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*< Tolerance in milliseconds for audiohooks synchronization */
+
struct ast_audiohook;
/*! \brief Callback function for manipulate audiohook type
diff --git a/main/audiohook.c b/main/audiohook.c
index a85f4cba6..ce0039bdd 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -123,12 +123,18 @@ int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohoo
struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
struct timeval *time = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *time;
+ int our_factory_ms;
+ int other_factory_samples;
+ int other_factory_ms;
/* Update last feeding time to be current */
*time = ast_tvnow();
- /* If we are using a sync trigger and this factory suddenly got audio fed in after a lapse, then flush both factories to ensure they remain in sync */
- if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && ast_slinfactory_available(other_factory) && (ast_tvdiff_ms(*time, previous_time) > (ast_slinfactory_available(other_factory) / 8))) {
+ our_factory_ms = ast_tvdiff_ms(*time, previous_time) + (ast_slinfactory_available(factory) / 8);
+ other_factory_samples = ast_slinfactory_available(other_factory);
+ other_factory_ms = other_factory_samples / 8;
+
+ if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && other_factory_samples && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
if (option_debug)
ast_log(LOG_DEBUG, "Flushing audiohook %p so it remains in sync\n", audiohook);
ast_slinfactory_flush(factory);
diff --git a/main/features.c b/main/features.c
index 21dbcb09b..e9f8a4275 100644
--- a/main/features.c
+++ b/main/features.c
@@ -2192,6 +2192,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
char save_exten[AST_MAX_EXTENSION];
int save_prio;
int found = 0; /* set if we find at least one match */
+ int spawn_error = 0;
if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
ast_cdr_end(bridge_cdr);
@@ -2210,15 +2211,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
ast_copy_string(chan->exten, "h", sizeof(chan->exten));
chan->priority = 1;
ast_channel_unlock(chan);
- while ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) {
+ while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) {
chan->priority++;
}
- if (found && res) {
+ if (found && spawn_error) {
/* Something bad happened, or a hangup has been requested. */
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
- } else if (!found && res) {
- res = 0;
}
/* swap it back */
ast_channel_lock(chan);