Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

asterisk:

 * bump version to [http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-11.8.0-summary.html 11.8.0] revision [http://svnview.digium.com/svn/asterisk/branches/11/?view=log 409917]
 * refs #706


git-svn-id: file:///var/svn/freetz/trunk@11852 149334a1-2f27-0410-a3b9-fc62619ac1e6
  • Loading branch information...
commit 11249da3f2525112e21912920731db28859d28e6 1 parent d41ec66
er13 authored
View
2  CHANGELOG
@@ -20,7 +20,7 @@ Latest changes:
- New patches (read online help for more info):
- New packages, libs, modules:
- * asterisk 11.8.0-rc3
+ * asterisk 11.8.0
* asterisk-chan-capi post-1.1.6 with asterisk11 adjustments by Mihai Moldovan
* asterisk-chan-dongle 1.1-git (asterisk11 branch)
* asterisk-chan-sccp 4.1.0RC1
View
2  make/asterisk/Config.in
@@ -1,5 +1,5 @@
config FREETZ_PACKAGE_ASTERISK
- bool "Asterisk 11.8.0-rc3 - EXPERIMENTAL"
+ bool "Asterisk 11.8.0 - EXPERIMENTAL"
select FREETZ_LIB_libdl
select FREETZ_LIB_libm
select FREETZ_LIB_libpthread
View
4 make/asterisk/asterisk.mk
@@ -1,6 +1,6 @@
-$(call PKG_INIT_BIN, 11.8.0-rc3)
+$(call PKG_INIT_BIN, 11.8.0)
$(PKG)_SOURCE:=$(pkg)-$($(PKG)_VERSION).tar.gz
-$(PKG)_SOURCE_SHA1:=1c38a0beb2e9ae5f77dfad303876f2b5384ec4ed
+$(PKG)_SOURCE_SHA1:=33b9dcb79bdd28de5c5a0f9255461c3bf9731e44
$(PKG)_SITE:=http://downloads.asterisk.org/pub/telephony/asterisk/releases
$(PKG)_CATEGORY:=Unstable
View
1,074 ...erisk/patches/000-asterisk-11-branch-409362.patch → ...erisk/patches/000-asterisk-11-branch-409917.patch
@@ -1226,7 +1226,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409303 $")
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409255 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409473 $")
#include <signal.h>
#include <sys/signal.h>
@@ -1396,6 +1396,15 @@
if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) {
/* This is a blind transfer */
ast_debug(1, "SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context);
+@@ -20079,7 +20099,7 @@
+ print_codec_to_cli(fd, &peer->prefs);
+ ast_cli(fd, ")\n");
+
+- ast_cli(fd, " Auto-Framing : %s \n", AST_CLI_YESNO(peer->autoframing));
++ ast_cli(fd, " Auto-Framing : %s\n", AST_CLI_YESNO(peer->autoframing));
+ ast_cli(fd, " Status : ");
+ peer_status(peer, status, sizeof(status));
+ ast_cli(fd, "%s\n", status);
@@ -24436,7 +24456,9 @@
if (peera && peerb && peerc && (peerb != peerc)) {
@@ -1446,6 +1455,176 @@
sip_pvt_unlock(p);
if (!tmpc) {
dialog_unlink_all(p);
+--- channels/chan_unistim.c
++++ channels/chan_unistim.c
+@@ -38,7 +38,7 @@
+
+ #include "asterisk.h"
+
+-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 396377 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409761 $")
+
+ #include <sys/stat.h>
+ #include <signal.h>
+@@ -3192,6 +3192,11 @@
+ ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
+ s->device->name);
+ }
++ start_rtp(sub);
++ if (!sub->rtp) {
++ ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, s->device->name);
++ return;
++ }
+ if (sub->owner) {
+ ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
+ }
+@@ -4421,7 +4426,7 @@
+ }
+ if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
+ if (unistimdebug) {
+- ast_verb(0, "Handset off hook\n");
++ ast_verb(0, "Handset off hook, current state: %s\n", ptestate_tostr(pte->state));
+ }
+ if (!pte->device) { /* We are not yet registered (asking for a TN in AUTOPROVISIONING_TN) */
+ return;
+@@ -4447,7 +4452,7 @@
+ }
+ if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
+ if (unistimdebug) {
+- ast_verb(0, "Handset on hook\n");
++ ast_verb(0, "Handset on hook, current state: %s\n", ptestate_tostr(pte->state));
+ }
+ if (!pte->device) {
+ return;
+@@ -4824,7 +4829,7 @@
+ unistim_unalloc_sub(d, sub);
+ return 0;
+ }
+- if (sub_real && (sub_real->owner) && (sub->subtype == SUB_THREEWAY)) { /* 3way call cancelled by softkey pressed */
++ if (sub_real && (sub_real->owner) && (sub->subtype == SUB_THREEWAY) && (s->state == STATE_CALL)) { /* 3way call cancelled by softkey pressed */
+ if (unistimdebug) {
+ ast_verb(0, "Real call disconnected, stay in call\n");
+ }
+@@ -4912,9 +4917,6 @@
+ l = sub->parent;
+ d = l->parent;
+
+- if ((!sub->rtp) && (!get_sub(d, SUB_THREEWAY))) {
+- start_rtp(sub);
+- }
+ if (unistimdebug) {
+ ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast_channel_name(ast), l->name,
+ l->parent->name, sub->softkey);
+@@ -5240,9 +5242,12 @@
+ if (sub->subtype == SUB_REAL) {
+ send_callerid_screen(s, sub);
+ }
++ case AST_CONTROL_UPDATE_RTP_PEER:
+ break;
+ case AST_CONTROL_SRCCHANGE:
+- ast_rtp_instance_change_source(sub->rtp);
++ if (sub->rtp) {
++ ast_rtp_instance_change_source(sub->rtp);
++ }
+ break;
+ default:
+ ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
+@@ -5849,14 +5854,7 @@
+ if (unistimdebug) {
+ ast_verb(0, "unistim_request owner = %p\n", sub->owner);
+ }
+- start_rtp(sub);
+- if (!sub->rtp) {
+- ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, d->name);
+- return NULL;
+- }
+-
+ restart_monitor();
+-
+ /* and finish */
+ return tmpc;
+ }
+@@ -6291,6 +6289,13 @@
+ }
+ ast_mutex_init(&d->lock);
+ ast_copy_string(d->name, cat, sizeof(d->name));
++ d->contrast = -1;
++ d->output = OUTPUT_HANDSET;
++ d->previous_output = OUTPUT_HANDSET;
++ d->volume = VOLUME_LOW;
++ d->mute = MUTE_OFF;
++ d->height = DEFAULTHEIGHT;
++ d->selected = -1;
+ } else {
+ /* Delete existing line information */
+ AST_LIST_LOCK(&d->lines);
+@@ -6310,14 +6315,7 @@
+ memset(d->sline, 0, sizeof(d->sline));
+ memset(d->sp, 0, sizeof(d->sp));
+ }
+-
+ ast_copy_string(d->context, DEFAULTCONTEXT, sizeof(d->context));
+- d->contrast = -1;
+- d->output = OUTPUT_HANDSET;
+- d->previous_output = OUTPUT_HANDSET;
+- d->volume = VOLUME_LOW;
+- d->mute = MUTE_OFF;
+- d->height = DEFAULTHEIGHT;
+ d->selected = -1;
+ d->interdigit_timer = DEFAULT_INTERDIGIT_TIMER;
+ linelabel[0] = '\0';
+@@ -6849,15 +6847,51 @@
+ {
+ struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
+
++ if (!sub) {
++ return AST_RTP_GLUE_RESULT_FORBID;
++ }
++ if (!sub->rtp) {
++ return AST_RTP_GLUE_RESULT_FORBID;
++ }
++
+ ao2_ref(sub->rtp, +1);
+ *instance = sub->rtp;
+
+ return AST_RTP_GLUE_RESULT_LOCAL;
+ }
+
++static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active)
++{
++ struct unistim_subchannel *sub;
++ struct sockaddr_in them = { 0, };
++ struct sockaddr_in us = { 0, };
++
++ if (!rtp) {
++ return 0;
++ }
++
++ sub = ast_channel_tech_pvt(chan);
++ if (!sub) {
++ ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
++ return -1;
++ }
++ {
++ struct ast_sockaddr tmp;
++ ast_rtp_instance_get_remote_address(rtp, &tmp);
++ ast_sockaddr_to_sin(&tmp, &them);
++ ast_rtp_instance_get_local_address(rtp, &tmp);
++ ast_sockaddr_to_sin(&tmp, &us);
++ }
++
++ /* TODO: Set rtp on phone in case of direct rtp (not implemented) */
++
++ return 0;
++}
++
+ static struct ast_rtp_glue unistim_rtp_glue = {
+ .type = channel_type,
+ .get_rtp_info = unistim_get_rtp_peer,
++ .update_peer = unistim_set_rtp_peer,
+ };
+
+ /*--- load_module: PBX load module - initialization ---*/
--- channels/sig_pri.c
+++ channels/sig_pri.c
@@ -665,12 +665,7 @@
@@ -1741,11 +1920,55 @@
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.ac Revision: 400768 .
-+# From configure.ac Revision: 405091 .
++# From configure.ac Revision: 406802 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for asterisk trunk.
#
-@@ -26648,6 +26648,117 @@
+@@ -12960,6 +12960,43 @@
+
+ fi
+
++stat_nsec_found=no
++ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "#include <sys/stat.h>
++"
++if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then :
++
++cat >>confdefs.h <<_ACEOF
++#define HAVE_STRUCT_STAT_ST_MTIM 1
++_ACEOF
++
++stat_nsec_found=yes
++fi
++ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimensec" "ac_cv_member_struct_stat_st_mtimensec" "#include <sys/stat.h>
++"
++if test "x$ac_cv_member_struct_stat_st_mtimensec" = xyes; then :
++
++cat >>confdefs.h <<_ACEOF
++#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1
++_ACEOF
++
++stat_nsec_found=yes
++fi
++ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimespec" "ac_cv_member_struct_stat_st_mtimespec" "#include <sys/stat.h>
++"
++if test "x$ac_cv_member_struct_stat_st_mtimespec" = xyes; then :
++
++cat >>confdefs.h <<_ACEOF
++#define HAVE_STRUCT_STAT_ST_MTIMESPEC 1
++_ACEOF
++
++stat_nsec_found=yes
++fi
++
++
++if test "${stat_nsec_found}" != yes; then
++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot determine nanosecond field of struct stat" >&5
++$as_echo "$as_me: WARNING: Cannot determine nanosecond field of struct stat" >&2;}
++fi
+
+ # Checks for library functions.
+ for ac_header in unistd.h
+@@ -26648,6 +26685,117 @@
@@ -1863,7 +2086,7 @@
if test "x${PBX_RADIUS}" != "x1" -a "${USE_RADIUS}" != "no"; then
pbxlibdir=""
-@@ -26752,6 +26863,7 @@
+@@ -26752,6 +26900,7 @@
fi
@@ -1871,6 +2094,28 @@
if test "x${PBX_COROSYNC}" != "x1" -a "${USE_COROSYNC}" != "no"; then
+--- contrib/scripts/astgenkey
++++ contrib/scripts/astgenkey
+@@ -32,7 +32,7 @@
+ echo "need to be moved to /var/lib/asterisk/keys if you want"
+ echo "to use them, and any private keys (.key files) will"
+ echo "need to be initialized at runtime either by running"
+- echo "Asterisk with the '-i' option, or with the 'init keys'"
++ echo "Asterisk with the '-i' option, or with the 'keys init'"
+ echo "command once Asterisk is running."
+ echo ""
+ echo "Press ENTER to continue or ^C to cancel."
+--- contrib/scripts/astgenkey.8
++++ contrib/scripts/astgenkey.8
+@@ -94,7 +94,7 @@
+ To see the currently-installed keys from the asterisk CLI, use the command
+
+ .RS
+-show keys
++keys show
+ .RE
+
+ .SH OPTIONS
--- contrib/scripts/install_prereq
+++ contrib/scripts/install_prereq
@@ -1,6 +1,6 @@
@@ -2180,6 +2425,20 @@
return -1;
}
if (fread(&chans, 1, 2, f) != 2) {
+--- funcs/func_audiohookinherit.c
++++ funcs/func_audiohookinherit.c
+@@ -228,6 +228,11 @@
+ return -1;
+ }
+
++ if (!chan) {
++ ast_log(LOG_WARNING, "No channel was provided to INHERITANCE function.\n");
++ return -1;
++ }
++
+ allow = ast_true(value);
+
+ /* Step 2: retrieve or set up datastore */
--- include/asterisk/autoconfig.h.in
+++ include/asterisk/autoconfig.h.in
@@ -29,6 +29,9 @@
@@ -2192,6 +2451,22 @@
/* Define to 1 if you have the `acos' function. */
#undef HAVE_ACOS
+@@ -863,6 +866,15 @@
+ /* Define to 1 if `st_blksize' is a member of `struct stat'. */
+ #undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
++/* Define to 1 if `st_mtim' is a member of `struct stat'. */
++#undef HAVE_STRUCT_STAT_ST_MTIM
++
++/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
++#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
++
++/* Define to 1 if `st_mtimespec' is a member of `struct stat'. */
++#undef HAVE_STRUCT_STAT_ST_MTIMESPEC
++
+ /* Define to 1 if `cr_uid' is a member of `struct ucred'. */
+ #undef HAVE_STRUCT_UCRED_CR_UID
+
--- include/asterisk/channel.h
+++ include/asterisk/channel.h
@@ -901,6 +901,10 @@
@@ -2298,6 +2573,25 @@
#include "asterisk/_private.h"
+--- main/astobj2.c
++++ main/astobj2.c
+@@ -24,7 +24,7 @@
+
+ #include "asterisk.h"
+
+-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 401783 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409567 $")
+
+ #include "asterisk/_private.h"
+ #include "asterisk/astobj2.h"
+@@ -157,6 +157,7 @@
+ "bad magic number for object %p. Object is likely destroyed.\n",
+ user_data);
+ }
++ ast_assert(0);
+ return NULL;
+ }
+
--- main/cel.c
+++ main/cel.c
@@ -33,7 +33,7 @@
@@ -2815,7 +3109,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 402407 $")
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 408388 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409917 $")
#include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
#include "asterisk/network.h" /* we do some sockaddr manipulation here */
@@ -2833,7 +3127,7 @@
/*! String stuffed in filename[] after the filename string. */
const char *who_asked;
-@@ -1180,6 +1185,61 @@
+@@ -1180,6 +1185,65 @@
ATTRIBUTE_EXEC = 1,
};
@@ -2864,10 +3158,14 @@
+static void cfmstat_save(struct cache_file_mtime *cfmtime, struct stat *statbuf)
+{
+ cfmtime->stat_size = statbuf->st_size;
-+#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || (defined(_POSIX_C_SOURCE) && 200809L <= _POSIX_C_SOURCE) || (defined(_XOPEN_SOURCE) && 700 <= _XOPEN_SOURCE)
++#if defined(HAVE_STRUCT_STAT_ST_MTIM)
+ cfmtime->stat_mtime_nsec = statbuf->st_mtim.tv_nsec;
-+#else
++#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
+ cfmtime->stat_mtime_nsec = statbuf->st_mtimensec;
++#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
++ cfmtime->stat_mtime_nsec = statbuf->st_mtimespec.tv_nsec;
++#else
++ cfmtime->stat_mtime_nsec = 0;
+#endif
+ cfmtime->stat_mtime = statbuf->st_mtime;
+}
@@ -2895,7 +3193,7 @@
static void config_cache_attribute(const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename, const char *who_asked)
{
struct cache_file_mtime *cfmtime;
-@@ -1202,10 +1262,11 @@
+@@ -1202,10 +1266,11 @@
AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
}
@@ -2903,7 +3201,7 @@
- cfmtime->mtime = 0;
- else
- cfmtime->mtime = statbuf.st_mtime;
-+ if (!stat(configfile, &statbuf)) {
++ if (stat(configfile, &statbuf)) {
+ cfmstat_clear(cfmtime);
+ } else {
+ cfmstat_save(cfmtime, &statbuf);
@@ -2911,7 +3209,7 @@
switch (attrtype) {
case ATTRIBUTE_INCLUDE:
-@@ -1587,14 +1648,19 @@
+@@ -1587,14 +1652,19 @@
}
if (!cfmtime) {
cfmtime = cfmtime_new(fn, who_asked);
@@ -2933,7 +3231,7 @@
/* File is unchanged, what about the (cached) includes (if any)? */
int unchanged = 1;
AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
-@@ -1651,8 +1717,9 @@
+@@ -1651,8 +1721,9 @@
return NULL;
}
@@ -2945,7 +3243,7 @@
if (!(f = fopen(fn, "r"))) {
ast_debug(1, "No file to parse: %s\n", fn);
-@@ -2287,7 +2354,6 @@
+@@ -2287,7 +2358,6 @@
ast_log(LOG_ERROR, "Unable to allocate memory for new config\n");
return -1;
}
@@ -3936,7 +4234,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 404045 $")
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409002 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409524 $")
#include <math.h>
@@ -4016,6 +4314,15 @@
/* Since UPDATE_BRIDGE_PEER is only used by the bridging code, don't forward it */
if (fr->subclass.integer != AST_CONTROL_UPDATE_RTP_PEER) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+@@ -1383,7 +1399,7 @@
+ *rc = who;
+ ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass.integer, ast_channel_name(who));
+ res = AST_BRIDGE_COMPLETE;
+- goto remote_bridge_cleanup;
++ break;
+ }
+ } else {
+ if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
@@ -1849,7 +1865,7 @@
/* Now actually fill the buffer with the good information */
if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
@@ -4526,6 +4833,340 @@
if (check_modem_rate(options.modems, options.minrate)) {
ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, options.minrate);
+--- res/res_http_websocket.c
++++ res/res_http_websocket.c
+@@ -29,7 +29,7 @@
+
+ #include "asterisk.h"
+
+-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 391560 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409703 $")
+
+ #include "asterisk/module.h"
+ #include "asterisk/http.h"
+@@ -58,6 +58,16 @@
+ /*! \brief Maximum reconstruction size for multi-frame payload reconstruction. */
+ #define MAXIMUM_RECONSTRUCTION_CEILING 16384
+
++/*! \brief Maximum size of a websocket frame header
++ * 1 byte flags and opcode
++ * 1 byte mask flag + payload len
++ * 8 bytes max extended length
++ * 4 bytes optional masking key
++ * ... payload follows ...
++ * */
++#define MAX_WS_HDR_SZ 14
++#define MIN_WS_HDR_SZ 2
++
+ /*! \brief Structure definition for session */
+ struct ast_websocket {
+ FILE *f; /*!< Pointer to the file instance used for writing and reading */
+@@ -230,6 +240,7 @@
+ if (fwrite(payload, 1, actual_length, session->f) != actual_length) {
+ return -1;
+ }
++ fflush(session->f);
+
+ return 0;
+ }
+@@ -286,111 +297,131 @@
+ return 0;
+ }
+
++/* MAINTENANCE WARNING on ast_websocket_read()!
++ *
++ * We have to keep in mind during this function that the fact that session->fd seems ready
++ * (via poll) does not necessarily mean we have application data ready, because in the case
++ * of an SSL socket, there is some encryption data overhead that needs to be read from the
++ * TCP socket, so poll() may say there are bytes to be read, but whether it is just 1 byte
++ * or N bytes we do not know that, and we do not know how many of those bytes (if any) are
++ * for application data (for us) and not just for the SSL protocol consumption
++ *
++ * There used to be a couple of nasty bugs here that were fixed in last refactoring but I
++ * want to document them so the constraints are clear and we do not re-introduce them:
++ *
++ * - This function would incorrectly assume that fread() would necessarily return more than
++ * 1 byte of data, just because a websocket frame is always >= 2 bytes, but the thing
++ * is we're dealing with a TCP bitstream here, we could read just one byte and that's normal.
++ * The problem before was that if just one byte was read, the function bailed out and returned
++ * an error, effectively dropping the first byte of a websocket frame header!
++ *
++ * - Another subtle bug was that it would just read up to MAX_WS_HDR_SZ (14 bytes) via fread()
++ * then assume that executing poll() would tell you if there is more to read, but since
++ * we're dealing with a buffered stream (session->f is a FILE*), poll would say there is
++ * nothing else to read (in the real tcp socket session->fd) and we would get stuck here
++ * without processing the rest of the data in session->f internal buffers until another packet
++ * came on the network to unblock us!
++ *
++ * Note during the header parsing stage we try to read in small chunks just what we need, this
++ * is buffered data anyways, no expensive syscall required most of the time ...
++ */
++static inline int ws_safe_read(struct ast_websocket *session, char *buf, int len, enum ast_websocket_opcode *opcode)
++{
++ int sanity;
++ size_t rlen;
++ int xlen = len;
++ char *rbuf = buf;
++ for (sanity = 10; sanity; sanity--) {
++ clearerr(session->f);
++ rlen = fread(rbuf, 1, xlen, session->f);
++ if (0 == rlen && ferror(session->f) && errno != EAGAIN) {
++ ast_log(LOG_ERROR, "Error reading from web socket: %s\n", strerror(errno));
++ (*opcode) = AST_WEBSOCKET_OPCODE_CLOSE;
++ session->closing = 1;
++ return -1;
++ }
++ xlen = (xlen - rlen);
++ rbuf = rbuf + rlen;
++ if (0 == xlen) {
++ break;
++ }
++ if (ast_wait_for_input(session->fd, 1000) < 0) {
++ ast_log(LOG_ERROR, "ast_wait_for_input returned err: %s\n", strerror(errno));
++ (*opcode) = AST_WEBSOCKET_OPCODE_CLOSE;
++ session->closing = 1;
++ return -1;
++ }
++ }
++ if (!sanity) {
++ ast_log(LOG_WARNING, "Websocket seems unresponsive, disconnecting ...\n");
++ (*opcode) = AST_WEBSOCKET_OPCODE_CLOSE;
++ session->closing = 1;
++ return -1;
++ }
++ return 0;
++}
++
+ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented)
+ {
+ char buf[MAXIMUM_FRAME_SIZE] = "";
+- size_t frame_size, expected = 2;
++ int fin = 0;
++ int mask_present = 0;
++ char *mask = NULL, *new_payload = NULL;
++ size_t options_len = 0, frame_size = 0;
+
+ *payload = NULL;
+ *payload_len = 0;
+ *fragmented = 0;
+
+- /* We try to read in 14 bytes, which is the largest possible WebSocket header */
+- if ((frame_size = fread(&buf, 1, 14, session->f)) < 1) {
+- return -1;
+- }
+-
+- /* The minimum size for a WebSocket frame is 2 bytes */
+- if (frame_size < expected) {
+- return -1;
++ if (ws_safe_read(session, &buf[0], MIN_WS_HDR_SZ, opcode)) {
++ return 0;
+ }
++ frame_size += MIN_WS_HDR_SZ;
+
++ /* ok, now we have the first 2 bytes, so we know some flags, opcode and payload length (or whether payload length extension will be required) */
+ *opcode = buf[0] & 0xf;
+-
++ *payload_len = buf[1] & 0x7f;
+ if (*opcode == AST_WEBSOCKET_OPCODE_TEXT || *opcode == AST_WEBSOCKET_OPCODE_BINARY || *opcode == AST_WEBSOCKET_OPCODE_CONTINUATION ||
+ *opcode == AST_WEBSOCKET_OPCODE_PING || *opcode == AST_WEBSOCKET_OPCODE_PONG) {
+- int fin = (buf[0] >> 7) & 1;
+- int mask_present = (buf[1] >> 7) & 1;
+- char *mask = NULL, *new_payload;
+- size_t remaining;
+-
+- if (mask_present) {
+- /* The mask should take up 4 bytes */
+- expected += 4;
++ fin = (buf[0] >> 7) & 1;
++ mask_present = (buf[1] >> 7) & 1;
+
+- if (frame_size < expected) {
+- /* Per the RFC 1009 means we received a message that was too large for us to process */
+- ast_websocket_close(session, 1009);
++ /* Based on the mask flag and payload length, determine how much more we need to read before start parsing the rest of the header */
++ options_len += mask_present ? 4 : 0;
++ options_len += (*payload_len == 126) ? 2 : (*payload_len == 127) ? 8 : 0;
++ if (options_len) {
++ /* read the rest of the header options */
++ if (ws_safe_read(session, &buf[frame_size], options_len, opcode)) {
+ return 0;
+ }
++ frame_size += options_len;
+ }
+
+- /* Assume no extended length and no masking at the beginning */
+- *payload_len = buf[1] & 0x7f;
+- *payload = &buf[2];
+-
+- /* Determine if extended length is being used */
+ if (*payload_len == 126) {
+- /* Use the next 2 bytes to get a uint16_t */
+- expected += 2;
+- *payload += 2;
+-
+- if (frame_size < expected) {
+- ast_websocket_close(session, 1009);
+- return 0;
+- }
+-
++ /* Grab the 2-byte payload length */
+ *payload_len = ntohs(get_unaligned_uint16(&buf[2]));
++ mask = &buf[4];
+ } else if (*payload_len == 127) {
+- /* Use the next 8 bytes to get a uint64_t */
+- expected += 8;
+- *payload += 8;
+-
+- if (frame_size < expected) {
+- ast_websocket_close(session, 1009);
+- return 0;
+- }
+-
++ /* Grab the 8-byte payload length */
+ *payload_len = ntohl(get_unaligned_uint64(&buf[2]));
++ mask = &buf[10];
++ } else {
++ /* Just set the mask after the small 2-byte header */
++ mask = &buf[2];
+ }
+
+- /* If masking is present the payload currently points to the mask, so move it over 4 bytes to the actual payload */
+- if (mask_present) {
+- mask = *payload;
+- *payload += 4;
+- }
+-
+- /* Determine how much payload we need to read in as we may have already read some in */
+- remaining = *payload_len - (frame_size - expected);
+-
+- /* If how much payload they want us to read in exceeds what we are capable of close the session, things
+- * will fail no matter what most likely */
+- if (remaining > (MAXIMUM_FRAME_SIZE - frame_size)) {
++ /* Now read the rest of the payload */
++ *payload = &buf[frame_size]; /* payload will start here, at the end of the options, if any */
++ frame_size = frame_size + (*payload_len); /* final frame size is header + optional headers + payload data */
++ if (frame_size > MAXIMUM_FRAME_SIZE) {
++ ast_log(LOG_WARNING, "Cannot fit huge websocket frame of %zd bytes\n", frame_size);
++ /* The frame won't fit :-( */
+ ast_websocket_close(session, 1009);
+- return 0;
++ return -1;
+ }
+
+- new_payload = *payload + (frame_size - expected);
+-
+- /* Read in the remaining payload */
+- while (remaining > 0) {
+- size_t payload_read;
+-
+- /* Wait for data to come in */
+- if (ast_wait_for_input(session->fd, -1) <= 0) {
+- *opcode = AST_WEBSOCKET_OPCODE_CLOSE;
+- *payload = NULL;
+- session->closing = 1;
+- return 0;
+- }
+-
+- /* If some sort of failure occurs notify the caller */
+- if ((payload_read = fread(new_payload, 1, remaining, session->f)) < 1) {
+- return -1;
+- }
+-
+- remaining -= payload_read;
+- new_payload += payload_read;
++ if (ws_safe_read(session, (*payload), (*payload_len), opcode)) {
++ return 0;
+ }
+
+ /* If a mask is present unmask the payload */
+@@ -401,7 +432,9 @@
+ }
+ }
+
+- if (!(new_payload = ast_realloc(session->payload, session->payload_len + *payload_len))) {
++ if (!(new_payload = ast_realloc(session->payload, (session->payload_len + *payload_len)))) {
++ ast_log(LOG_WARNING, "Failed allocation: %p, %zd, %"PRIu64"\n",
++ session->payload, session->payload_len, *payload_len);
+ *payload_len = 0;
+ ast_websocket_close(session, 1009);
+ return 0;
+@@ -413,7 +446,7 @@
+ }
+
+ session->payload = new_payload;
+- memcpy(session->payload + session->payload_len, *payload, *payload_len);
++ memcpy((session->payload + session->payload_len), (*payload), (*payload_len));
+ session->payload_len += *payload_len;
+
+ if (!fin && session->reconstruct && (session->payload_len < session->reconstruct)) {
+@@ -439,15 +472,15 @@
+ session->payload_len = 0;
+ }
+ } else if (*opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
+- char *new_payload;
+-
+- *payload_len = buf[1] & 0x7f;
+-
+ /* Make the payload available so the user can look at the reason code if they so desire */
+ if ((*payload_len) && (new_payload = ast_realloc(session->payload, *payload_len))) {
++ if (ws_safe_read(session, &buf[frame_size], (*payload_len), opcode)) {
++ return 0;
++ }
+ session->payload = new_payload;
+- memcpy(session->payload, &buf[2], *payload_len);
++ memcpy(session->payload, &buf[frame_size], *payload_len);
+ *payload = session->payload;
++ frame_size += (*payload_len);
+ }
+
+ if (!session->closing) {
+@@ -458,6 +491,7 @@
+ session->f = NULL;
+ ast_verb(2, "WebSocket connection from '%s' closed\n", ast_sockaddr_stringify(&session->address));
+ } else {
++ ast_log(LOG_WARNING, "WebSocket unknown opcode %d\n", *opcode);
+ /* We received an opcode that we don't understand, the RFC states that 1003 is for a type of data that can't be accepted... opcodes
+ * fit that, I think. */
+ ast_websocket_close(session, 1003);
+@@ -578,6 +612,7 @@
+ upgrade,
+ base64,
+ protocol);
++ fflush(ser->f);
+ } else {
+
+ /* Specification defined in http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 or completely unknown */
+@@ -634,6 +669,8 @@
+ {
+ int flags, res;
+
++ ast_debug(1, "Entering WebSocket echo loop\n");
++
+ if ((flags = fcntl(ast_websocket_fd(session), F_GETFL)) == -1) {
+ goto end;
+ }
+@@ -652,6 +689,7 @@
+
+ if (ast_websocket_read(session, &payload, &payload_len, &opcode, &fragmented)) {
+ /* We err on the side of caution and terminate the session if any error occurs */
++ ast_log(LOG_WARNING, "Read failure during WebSocket echo loop\n");
+ break;
+ }
+
+@@ -659,10 +697,13 @@
+ ast_websocket_write(session, opcode, payload, payload_len);
+ } else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
+ break;
++ } else {
++ ast_debug(1, "Ignored WebSocket opcode %d\n", opcode);
+ }
+ }
+
+ end:
++ ast_debug(1, "Exitting WebSocket echo loop\n");
+ ast_websocket_unref(session);
+ }
+
--- res/res_pktccops.c
+++ res/res_pktccops.c
@@ -37,7 +37,7 @@
@@ -4553,11 +5194,365 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409150 $")
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409130 $")
++ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409565 $")
#include <sys/time.h>
#include <signal.h>
-@@ -1827,7 +1827,7 @@
+@@ -70,6 +70,7 @@
+ #include "asterisk/unaligned.h"
+ #include "asterisk/module.h"
+ #include "asterisk/rtp_engine.h"
++#include "asterisk/test.h"
+
+ #define MAX_TIMESTAMP_SKEW 640
+
+@@ -266,7 +267,7 @@
+ pj_turn_state_t turn_state; /*!< Current state of the TURN relay session */
+ ast_cond_t cond; /*!< Condition for signaling */
+ unsigned int passthrough:1; /*!< Bit to indicate that the received packet should be passed through */
+- unsigned int ice_started:1; /*!< Bit to indicate ICE connectivity checks have started */
++ unsigned int ice_port; /*!< Port that ICE was started with if it was previously started */
+
+ char remote_ufrag[256]; /*!< The remote ICE username */
+ char remote_passwd[256]; /*!< The remote ICE password */
+@@ -274,8 +275,10 @@
+ char local_ufrag[256]; /*!< The local ICE username */
+ char local_passwd[256]; /*!< The local ICE password */
+
+- struct ao2_container *local_candidates; /*!< The local ICE candidates */
+- struct ao2_container *remote_candidates; /*!< The remote ICE candidates */
++ struct ao2_container *ice_local_candidates; /*!< The local ICE candidates */
++ struct ao2_container *ice_active_remote_candidates; /*!< The remote ICE candidates */
++ struct ao2_container *ice_proposed_remote_candidates; /*!< Incoming remote ICE candidates for new session */
++ struct ast_sockaddr ice_original_rtp_addr; /*!< rtp address that ICE started on first session */
+ #endif
+
+ #ifdef HAVE_OPENSSL_SRTP
+@@ -432,17 +435,32 @@
+ }
+ }
+
++static int ice_candidate_cmp(void *obj, void *arg, int flags)
++{
++ struct ast_rtp_engine_ice_candidate *candidate1 = obj, *candidate2 = arg;
++
++ if (strcmp(candidate1->foundation, candidate2->foundation) ||
++ candidate1->id != candidate2->id ||
++ ast_sockaddr_cmp(&candidate1->address, &candidate2->address) ||
++ candidate1->type != candidate1->type) {
++ return 0;
++ }
++
++ return CMP_MATCH | CMP_STOP;
++}
++
+ static void ast_rtp_ice_add_remote_candidate(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
+ {
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ struct ast_rtp_engine_ice_candidate *remote_candidate;
+
+- if (!rtp->remote_candidates && !(rtp->remote_candidates = ao2_container_alloc(1, NULL, NULL))) {
++ if (!rtp->ice_proposed_remote_candidates &&
++ !(rtp->ice_proposed_remote_candidates = ao2_container_alloc(1, NULL, ice_candidate_cmp))) {
+ return;
+ }
+
+ /* If this is going to exceed the maximum number of ICE candidates don't even add it */
+- if (ao2_container_count(rtp->remote_candidates) == PJ_ICE_MAX_CAND) {
++ if (ao2_container_count(rtp->ice_proposed_remote_candidates) == PJ_ICE_MAX_CAND) {
+ return;
+ }
+
+@@ -458,7 +476,7 @@
+ ast_sockaddr_copy(&remote_candidate->relay_address, &candidate->relay_address);
+ remote_candidate->type = candidate->type;
+
+- ao2_link(rtp->remote_candidates, remote_candidate);
++ ao2_link(rtp->ice_proposed_remote_candidates, remote_candidate);
+ ao2_ref(remote_candidate, -1);
+ }
+
+@@ -500,6 +518,58 @@
+ ast_sockaddr_set_port(cand_address, pj_sockaddr_get_port(&rtp->ice->comp[component - 1].valid_check->rcand->addr));
+ }
+
++static int ice_create(struct ast_rtp_instance *instance, struct ast_sockaddr *addr,
++ int port, int replace);
++
++static void ast_rtp_ice_stop(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ if (!rtp->ice) {
++ return;
++ }
++
++ pj_thread_register_check();
++
++ pj_ice_sess_destroy(rtp->ice);
++ rtp->ice = NULL;
++}
++
++static int ice_reset_session(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ ast_rtp_ice_stop(instance);
++ return ice_create(instance, &rtp->ice_original_rtp_addr, rtp->ice_port, 1);
++}
++
++static int ice_candidates_compare(struct ao2_container *left, struct ao2_container *right)
++{
++ struct ao2_iterator i;
++ struct ast_rtp_engine_ice_candidate *right_candidate;
++
++ if (ao2_container_count(left) != ao2_container_count(right)) {
++ return -1;
++ }
++
++ i = ao2_iterator_init(right, 0);
++ while ((right_candidate = ao2_iterator_next(&i))) {
++ struct ast_rtp_engine_ice_candidate *left_candidate = ao2_find(left, right_candidate, OBJ_POINTER);
++
++ if (!left_candidate) {
++ ao2_ref(right_candidate, -1);
++ ao2_iterator_destroy(&i);
++ return -1;
++ }
++
++ ao2_ref(left_candidate, -1);
++ ao2_ref(right_candidate, -1);
++ }
++ ao2_iterator_destroy(&i);
++
++ return 0;
++}
++
+ static void ast_rtp_ice_start(struct ast_rtp_instance *instance)
+ {
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+@@ -509,13 +579,32 @@
+ struct ast_rtp_engine_ice_candidate *candidate;
+ int cand_cnt = 0;
+
+- if (!rtp->ice || !rtp->remote_candidates || rtp->ice_started) {
++ if (!rtp->ice || !rtp->ice_proposed_remote_candidates) {
++ return;
++ }
++
++ /* Check for equivalence in the lists */
++ if (rtp->ice_active_remote_candidates &&
++ !ice_candidates_compare(rtp->ice_proposed_remote_candidates, rtp->ice_active_remote_candidates)) {
++ ao2_cleanup(rtp->ice_proposed_remote_candidates);
++ rtp->ice_proposed_remote_candidates = NULL;
++ return;
++ }
++
++ /* Out with the old, in with the new */
++ ao2_cleanup(rtp->ice_active_remote_candidates);
++ rtp->ice_active_remote_candidates = rtp->ice_proposed_remote_candidates;
++ rtp->ice_proposed_remote_candidates = NULL;
++
++ /* Reset the ICE session. Is this going to work? */
++ if (ice_reset_session(instance)) {
++ ast_log(LOG_NOTICE, "Failed to create replacement ICE session\n");
+ return;
+ }
+
+ pj_thread_register_check();
+
+- i = ao2_iterator_init(rtp->remote_candidates, 0);
++ i = ao2_iterator_init(rtp->ice_active_remote_candidates, 0);
+
+ while ((candidate = ao2_iterator_next(&i)) && (cand_cnt < PJ_ICE_MAX_CAND)) {
+ pj_str_t address;
+@@ -545,42 +634,31 @@
+ }
+
+ cand_cnt++;
++ ao2_ref(candidate, -1);
+ }
+
+ ao2_iterator_destroy(&i);
+
+- if (pj_ice_sess_create_check_list(rtp->ice, &ufrag, &passwd, ao2_container_count(rtp->remote_candidates), &candidates[0]) == PJ_SUCCESS) {
++ if (pj_ice_sess_create_check_list(rtp->ice, &ufrag, &passwd, ao2_container_count(rtp->ice_active_remote_candidates), &candidates[0]) == PJ_SUCCESS) {
++ ast_test_suite_event_notify("ICECHECKLISTCREATE", "Result: SUCCESS");
+ pj_ice_sess_start_check(rtp->ice);
+ pj_timer_heap_poll(timerheap, NULL);
+- rtp->ice_started = 1;
+ rtp->strict_rtp_state = STRICT_RTP_OPEN;
+ return;
+ }
+
++ ast_test_suite_event_notify("ICECHECKLISTCREATE", "Result: FAILURE");
++
+ /* even though create check list failed don't stop ice as
+ it might still work */
+ ast_debug(1, "Failed to create ICE session check list\n");
+ /* however we do need to reset remote candidates since
+ this function may be re-entered */
+- ao2_ref(rtp->remote_candidates, -1);
+- rtp->remote_candidates = NULL;
++ ao2_ref(rtp->ice_active_remote_candidates, -1);
++ rtp->ice_active_remote_candidates = NULL;
+ rtp->ice->rcand_cnt = rtp->ice->clist.count = 0;
+ }
+
+-static void ast_rtp_ice_stop(struct ast_rtp_instance *instance)
+-{
+- struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+-
+- if (!rtp->ice) {
+- return;
+- }
+-
+- pj_thread_register_check();
+-
+- pj_ice_sess_destroy(rtp->ice);
+- rtp->ice = NULL;
+-}
+-
+ static const char *ast_rtp_ice_get_ufrag(struct ast_rtp_instance *instance)
+ {
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+@@ -599,11 +677,11 @@
+ {
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+- if (rtp->local_candidates) {
+- ao2_ref(rtp->local_candidates, +1);
++ if (rtp->ice_local_candidates) {
++ ao2_ref(rtp->ice_local_candidates, +1);
+ }
+
+- return rtp->local_candidates;
++ return rtp->ice_local_candidates;
+ }
+
+ static void ast_rtp_ice_lite(struct ast_rtp_instance *instance)
+@@ -619,20 +697,6 @@
+ pj_ice_sess_change_role(rtp->ice, PJ_ICE_SESS_ROLE_CONTROLLING);
+ }
+
+-static int ice_candidate_cmp(void *obj, void *arg, int flags)
+-{
+- struct ast_rtp_engine_ice_candidate *candidate1 = obj, *candidate2 = arg;
+-
+- if ((strcmp(candidate1->foundation, candidate2->foundation)) ||
+- (candidate1->id != candidate2->id) ||
+- (ast_sockaddr_cmp(&candidate1->address, &candidate2->address)) ||
+- (candidate1->type != candidate1->type)) {
+- return 0;
+- }
+-
+- return CMP_MATCH | CMP_STOP;
+-}
+-
+ static void ast_rtp_ice_add_cand(struct ast_rtp *rtp, unsigned comp_id, unsigned transport_id, pj_ice_cand_type type, pj_uint16_t local_pref,
+ const pj_sockaddr_t *addr, const pj_sockaddr_t *base_addr, const pj_sockaddr_t *rel_addr, int addr_len)
+ {
+@@ -644,7 +708,7 @@
+
+ pj_ice_calc_foundation(rtp->ice->pool, &foundation, type, addr);
+
+- if (!rtp->local_candidates && !(rtp->local_candidates = ao2_container_alloc(1, NULL, ice_candidate_cmp))) {
++ if (!rtp->ice_local_candidates && !(rtp->ice_local_candidates = ao2_container_alloc(1, NULL, ice_candidate_cmp))) {
+ return;
+ }
+
+@@ -672,7 +736,7 @@
+ candidate->type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED;
+ }
+
+- if ((existing = ao2_find(rtp->local_candidates, candidate, OBJ_POINTER))) {
++ if ((existing = ao2_find(rtp->ice_local_candidates, candidate, OBJ_POINTER))) {
+ ao2_ref(existing, -1);
+ ao2_ref(candidate, -1);
+ return;
+@@ -686,7 +750,7 @@
+ /* By placing the candidate into the ICE session it will have produced the priority, so update the local candidate with it */
+ candidate->priority = rtp->ice->lcand[rtp->ice->lcand_cnt - 1].prio;
+
+- ao2_link(rtp->local_candidates, candidate);
++ ao2_link(rtp->ice_local_candidates, candidate);
+ ao2_ref(candidate, -1);
+ }
+
+@@ -1766,16 +1830,68 @@
+ return (unsigned int) ms;
+ }
+
++#ifdef USE_PJPROJECT
++/*!
++ * \internal
++ * \brief Creates an ICE session. Can be used to replace a destroyed ICE session.
++ *
++ * \param instance RTP instance for which the ICE session is being replaced
++ * \param addr ast_sockaddr to use for adding RTP candidates to the ICE session
++ * \param port port to use for adding RTP candidates to the ICE session
++ * \param replace 0 when creating a new session, 1 when replacing a destroyed session
++ *
++ * \retval 0 on success
++ * \retval -1 on failure
++ */
++static int ice_create(struct ast_rtp_instance *instance, struct ast_sockaddr *addr,
++ int port, int replace)
++{
++ pj_stun_config stun_config;
++ pj_str_t ufrag, passwd;
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ ao2_cleanup(rtp->ice_local_candidates);
++ rtp->ice_local_candidates = NULL;
++
++ pj_thread_register_check();
++
++ pj_stun_config_init(&stun_config, &cachingpool.factory, 0, ioqueue, timerheap);
++
++ ufrag = pj_str(rtp->local_ufrag);
++ passwd = pj_str(rtp->local_passwd);
++
++ /* Create an ICE session for ICE negotiation */
++ if (pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2,
++ &ast_rtp_ice_sess_cb, &ufrag, &passwd, &rtp->ice) == PJ_SUCCESS) {
++ /* Make this available for the callbacks */
++ rtp->ice->user_data = rtp;
++
++ /* Add all of the available candidates to the ICE session */
++ rtp_add_candidates_to_ice(instance, rtp, addr, port, AST_RTP_ICE_COMPONENT_RTP,
++ TRANSPORT_SOCKET_RTP, &ast_rtp_turn_rtp_sock_cb, &rtp->turn_rtp);
++
++ /* Only add the RTCP candidates to ICE when replacing the session. New sessions
++ * handle this in a separate part of the setup phase */
++ if (replace && rtp->rtcp) {
++ rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us,
++ ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP,
++ TRANSPORT_SOCKET_RTCP, &ast_rtp_turn_rtcp_sock_cb, &rtp->turn_rtcp);
++ }
++
++ return 0;
++ }
++
++ return -1;
++
++}
++#endif
++
+ static int ast_rtp_new(struct ast_rtp_instance *instance,
+ struct ast_sched_context *sched, struct ast_sockaddr *addr,
+ void *data)
+ {
+ struct ast_rtp *rtp = NULL;
+ int x, startplace;
+-#ifdef USE_PJPROJECT
+- pj_stun_config stun_config;
+- pj_str_t ufrag, passwd;
+-#endif
+
+ /* Create a new RTP structure to hold all of our data */
+ if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
+@@ -1827,7 +1943,7 @@
}
/* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
@@ -4566,6 +5561,53 @@
ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
close(rtp->s);
ast_free(rtp);
+@@ -1838,22 +1954,17 @@
+ ast_rtp_instance_set_data(instance, rtp);
+
+ #ifdef USE_PJPROJECT
+- pj_thread_register_check();
+-
+- pj_stun_config_init(&stun_config, &cachingpool.factory, 0, ioqueue, timerheap);
+-
+ generate_random_string(rtp->local_ufrag, sizeof(rtp->local_ufrag));
+- ufrag = pj_str(rtp->local_ufrag);
+ generate_random_string(rtp->local_passwd, sizeof(rtp->local_passwd));
+- passwd = pj_str(rtp->local_passwd);
+
+ /* Create an ICE session for ICE negotiation */
+- if (icesupport && pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2, &ast_rtp_ice_sess_cb, &ufrag, &passwd, &rtp->ice) == PJ_SUCCESS) {
+- /* Make this available for the callbacks */
+- rtp->ice->user_data = rtp;
+-
+- /* Add all of the available candidates to the ICE session */
+- rtp_add_candidates_to_ice(instance, rtp, addr, x, AST_RTP_ICE_COMPONENT_RTP, TRANSPORT_SOCKET_RTP, &ast_rtp_turn_rtp_sock_cb, &rtp->turn_rtp);
++ if (icesupport) {
++ if (ice_create(instance, addr, x, 0)) {
++ ast_log(LOG_NOTICE, "Failed to start ICE session\n");
++ } else {
++ rtp->ice_port = x;
++ ast_sockaddr_copy(&rtp->ice_original_rtp_addr, addr);
++ }
+ }
+ #endif
+
+@@ -1919,12 +2030,12 @@
+ }
+
+ /* Destroy any candidates */
+- if (rtp->local_candidates) {
+- ao2_ref(rtp->local_candidates, -1);
++ if (rtp->ice_local_candidates) {
++ ao2_ref(rtp->ice_local_candidates, -1);
+ }
+
+- if (rtp->remote_candidates) {
+- ao2_ref(rtp->remote_candidates, -1);
++ if (rtp->ice_active_remote_candidates) {
++ ao2_ref(rtp->ice_active_remote_candidates, -1);
+ }
+
+ /* Destroy synchronization items */
--- utils/astman.c
+++ utils/astman.c
@@ -27,7 +27,7 @@
View
2  make/asterisk/patches/030-speex_check.patch
@@ -3,7 +3,7 @@ When compiled with no floating numbers support it does provide speex_encode_int
speex_encoder_init is available regardless of "float vs. int"-configuration.
--- configure
+++ configure
-@@ -27085,7 +27085,7 @@
+@@ -27122,7 +27122,7 @@
pbxlibdir="-L${SPEEX_DIR}"
fi
fi
View
2  make/asterisk/patches/035-openssl-libdl.patch
@@ -1,6 +1,6 @@
--- configure
+++ configure
-@@ -27789,7 +27789,7 @@
+@@ -27826,7 +27826,7 @@
# now check for the header.
if test "${AST_OPENSSL_FOUND}" = "yes"; then
View
8 make/asterisk/patches/050-pjproject-2.0.1-to-2.1.0.patch
@@ -1,11 +1,11 @@
--- res/res_rtp_asterisk.c
+++ res/res_rtp_asterisk.c
-@@ -1849,7 +1849,7 @@
- passwd = pj_str(rtp->local_passwd);
+@@ -1863,7 +1863,7 @@
/* Create an ICE session for ICE negotiation */
-- if (icesupport && pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2, &ast_rtp_ice_sess_cb, &ufrag, &passwd, &rtp->ice) == PJ_SUCCESS) {
-+ if (icesupport && pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2, &ast_rtp_ice_sess_cb, &ufrag, &passwd, NULL, &rtp->ice) == PJ_SUCCESS) {
+ if (pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2,
+- &ast_rtp_ice_sess_cb, &ufrag, &passwd, &rtp->ice) == PJ_SUCCESS) {
++ &ast_rtp_ice_sess_cb, &ufrag, &passwd, NULL, &rtp->ice) == PJ_SUCCESS) {
/* Make this available for the callbacks */
rtp->ice->user_data = rtp;
View
4 make/asterisk/patches/060-no_res_nsearch_in_uclibc.patch
@@ -1,6 +1,6 @@
--- configure
+++ configure
-@@ -16410,6 +16410,12 @@
+@@ -16447,6 +16447,12 @@
fi
@@ -13,7 +13,7 @@
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_ninit" >&5
$as_echo_n "checking for res_ninit... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-@@ -16630,6 +16636,7 @@
+@@ -16667,6 +16673,7 @@
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
View
6 make/asterisk/patches/070-libubacktrace_instead_of_libexecinfo.patch
@@ -1,6 +1,6 @@
--- configure
+++ configure
-@@ -21737,7 +21737,7 @@
+@@ -21774,7 +21774,7 @@
@@ -9,7 +9,7 @@
if test "x${PBX_BKTR}" != "x1" -a "${USE_BKTR}" != "no"; then
pbxlibdir=""
-@@ -21755,14 +21755,14 @@
+@@ -21792,14 +21792,14 @@
else
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} "
@@ -28,7 +28,7 @@
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-@@ -21804,7 +21804,7 @@
+@@ -21841,7 +21841,7 @@
# now check for the header.
if test "${AST_BKTR_FOUND}" = "yes"; then
Please sign in to comment.
Something went wrong with that request. Please try again.